From 3722de8b29d0eaa44b5df847d16e9ea14d003f09 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 28 Nov 2019 18:59:15 -0400 Subject: [PATCH 001/689] Prevent redux state mutation (#7598) The `txParams` property of a transaction in Redux state was being mutated. The mutation is now prevented with a shallow clone. --- ui/app/ducks/metamask/metamask.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/app/ducks/metamask/metamask.js b/ui/app/ducks/metamask/metamask.js index 23437610f..8a9739af7 100644 --- a/ui/app/ducks/metamask/metamask.js +++ b/ui/app/ducks/metamask/metamask.js @@ -322,7 +322,9 @@ function reduceMetamask (state, action) { let { selectedAddressTxList } = metamaskState selectedAddressTxList = selectedAddressTxList.map(tx => { if (tx.id === txId) { - tx.txParams = value + const newTx = Object.assign({}, tx) + newTx.txParams = value + return newTx } return tx }) From 5917da63f7d255869d87b170463b2e182b09d731 Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Fri, 29 Nov 2019 10:39:45 -0800 Subject: [PATCH 002/689] add locale fix script (#7580) --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 7b51c827f..f7df8b7e5 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "lint:changed:fix": "{ git ls-files --others --exclude-standard ; git diff-index --name-only --diff-filter=d HEAD ; } | grep --regexp='[.]js$' --regexp='[.]json$' | tr '\\n' '\\0' | xargs -0 eslint --fix", "lint:shellcheck": "shellcheck --version && find . -type f -name '*.sh' ! -path './node_modules/*' -print0 | xargs -0 shellcheck", "verify-locales": "node ./development/verify-locale-strings.js", + "verify-locales:fix": "node ./development/verify-locale-strings.js --fix", "mozilla-lint": "addons-linter dist/firefox", "watch": "cross-env METAMASK_ENV=test mocha --watch --require test/setup.js --reporter min --recursive \"test/unit/**/*.js\" \"ui/app/**/*.test.js\"", "devtools:react": "react-devtools", From 86e7233bd1b8a746c391cfe423ac8fb4fe6e2572 Mon Sep 17 00:00:00 2001 From: Xavier Maysonnave Date: Mon, 2 Dec 2019 19:26:02 +0530 Subject: [PATCH 003/689] Process URL fragment for ens-ipfs redirects (#7604) Also use app.ens.domains instead of manager.ens.domains --- app/scripts/lib/ens-ipfs/setup.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/scripts/lib/ens-ipfs/setup.js b/app/scripts/lib/ens-ipfs/setup.js index f12a22238..a00c750a4 100644 --- a/app/scripts/lib/ens-ipfs/setup.js +++ b/app/scripts/lib/ens-ipfs/setup.js @@ -28,7 +28,7 @@ function setupEnsIpfsResolver ({ provider }) { } // parse ens name const urlData = urlUtil.parse(url) - const { hostname: name, path, search } = urlData + const { hostname: name, path, search, hash: fragment } = urlData const domainParts = name.split('.') const topLevelDomain = domainParts[domainParts.length - 1] // if unsupported TLD, abort @@ -36,16 +36,16 @@ function setupEnsIpfsResolver ({ provider }) { return } // otherwise attempt resolve - attemptResolve({ tabId, name, path, search }) + attemptResolve({ tabId, name, path, search, fragment }) } - async function attemptResolve ({ tabId, name, path, search }) { + async function attemptResolve ({ tabId, name, path, search, fragment }) { extension.tabs.update(tabId, { url: `loading.html` }) - let url = `https://manager.ens.domains/name/${name}` + let url = `https://app.ens.domains/name/${name}` try { const {type, hash} = await resolveEnsToIpfsContentId({ provider, name }) if (type === 'ipfs-ns') { - const resolvedUrl = `https://gateway.ipfs.io/ipfs/${hash}${path}${search || ''}` + const resolvedUrl = `https://gateway.ipfs.io/ipfs/${hash}${path}${search || ''}${fragment || ''}` try { // check if ipfs gateway has result const response = await fetch(resolvedUrl, { method: 'HEAD' }) @@ -56,11 +56,11 @@ function setupEnsIpfsResolver ({ provider }) { console.warn(err) } } else if (type === 'swarm-ns') { - url = `https://swarm-gateways.net/bzz:/${hash}${path}${search || ''}` + url = `https://swarm-gateways.net/bzz:/${hash}${path}${search || ''}${fragment || ''}` } else if (type === 'onion' || type === 'onion3') { - url = `http://${hash}.onion${path}${search || ''}` + url = `http://${hash}.onion${path}${search || ''}${fragment || ''}` } else if (type === 'zeronet') { - url = `http://127.0.0.1:43110/${hash}${path}${search || ''}` + url = `http://127.0.0.1:43110/${hash}${path}${search || ''}${fragment || ''}` } } catch (err) { console.warn(err) From e61745a821ea7a6d0464324292c9879feb33765a Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 3 Dec 2019 11:22:01 -0330 Subject: [PATCH 004/689] Enable no-var rule for ESLint (#7590) * eslint: Enable no-var rule * yarn lint --fix --- .eslintrc | 1 + app/scripts/controllers/network/network.js | 4 +- app/scripts/edge-encryptor.js | 28 ++-- app/scripts/lib/cleanErrorStack.js | 4 +- app/scripts/lib/message-manager.js | 6 +- app/scripts/lib/personal-message-manager.js | 6 +- app/scripts/lib/typed-message-manager.js | 6 +- development/announcer.js | 12 +- development/mock-dev.js | 2 +- development/sourcemap-validator.js | 4 +- test/e2e/web3.spec.js | 32 ++--- test/helper.js | 4 +- test/lib/mock-encryptor.js | 4 +- test/lib/mock-simple-keychain.js | 4 +- test/lib/react-trigger-change.js | 24 ++-- test/unit/actions/config_test.js | 16 +-- .../unit/actions/set_selected_account_test.js | 18 +-- test/unit/actions/tx_test.js | 4 +- test/unit/actions/view_info_test.js | 14 +- test/unit/actions/warning_test.js | 12 +- .../app/controllers/detect-tokens-test.js | 10 +- .../preferences-controller-test.js | 12 +- .../controllers/transactions/tx-utils-test.js | 4 +- test/unit/app/edge-encryptor-test.js | 4 +- test/unit/app/message-manager-test.js | 16 +-- .../unit/app/personal-message-manager-test.js | 28 ++-- test/unit/reducers/unlock_vault_test.js | 10 +- test/unit/util_test.js | 122 +++++++++--------- test/web3/schema.js | 4 +- test/web3/web3.js | 2 +- ui/app/components/app/account-panel.js | 10 +- ui/app/components/app/menu-droppo.js | 4 +- ui/app/components/ui/fiat-value.js | 4 +- ui/app/components/ui/mascot.js | 4 +- ui/app/ducks/app/app.js | 4 +- ui/app/ducks/metamask/metamask.js | 4 +- ui/app/helpers/utils/util.js | 80 ++++++------ ui/app/pages/confirm-transaction/conf-tx.js | 8 +- ui/app/pages/routes/index.js | 2 +- ui/app/store/actions.js | 20 +-- ui/index.js | 2 +- ui/lib/icon-factory.js | 16 +-- ui/lib/persistent-form.js | 4 +- 43 files changed, 290 insertions(+), 289 deletions(-) diff --git a/.eslintrc b/.eslintrc index 2269cb98a..b8a5c4094 100644 --- a/.eslintrc +++ b/.eslintrc @@ -143,6 +143,7 @@ "no-useless-computed-key": 2, "no-useless-constructor": 2, "no-useless-escape": 2, + "no-var": 2, "no-whitespace-before-property": 2, "no-with": 2, "one-var": [2, { "initialized": "never" }], diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index f1be914bb..d78f92f93 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -198,7 +198,7 @@ module.exports = class NetworkController extends EventEmitter { }) this._setNetworkClient(networkClient) // setup networkConfig - var settings = { + const settings = { ticker: 'ETH', } this.networkConfig.putState(settings) @@ -221,7 +221,7 @@ module.exports = class NetworkController extends EventEmitter { nickname, } // setup networkConfig - var settings = { + let settings = { network: chainId, } settings = extend(settings, networks.networkList['rpc']) diff --git a/app/scripts/edge-encryptor.js b/app/scripts/edge-encryptor.js index 012672ed2..d086a854d 100644 --- a/app/scripts/edge-encryptor.js +++ b/app/scripts/edge-encryptor.js @@ -14,17 +14,17 @@ class EdgeEncryptor { * @returns {Promise} Promise resolving to an object with ciphertext */ encrypt (password, dataObject) { - var salt = this._generateSalt() + const salt = this._generateSalt() return this._keyFromPassword(password, salt) .then(function (key) { - var data = JSON.stringify(dataObject) - var dataBuffer = Unibabel.utf8ToBuffer(data) - var vector = global.crypto.getRandomValues(new Uint8Array(16)) - var resultbuffer = asmcrypto.AES_GCM.encrypt(dataBuffer, key, vector) + const data = JSON.stringify(dataObject) + const dataBuffer = Unibabel.utf8ToBuffer(data) + const vector = global.crypto.getRandomValues(new Uint8Array(16)) + const resultbuffer = asmcrypto.AES_GCM.encrypt(dataBuffer, key, vector) - var buffer = new Uint8Array(resultbuffer) - var vectorStr = Unibabel.bufferToBase64(vector) - var vaultStr = Unibabel.bufferToBase64(buffer) + const buffer = new Uint8Array(resultbuffer) + const vectorStr = Unibabel.bufferToBase64(vector) + const vaultStr = Unibabel.bufferToBase64(buffer) return JSON.stringify({ data: vaultStr, iv: vectorStr, @@ -48,7 +48,7 @@ class EdgeEncryptor { const encryptedData = Unibabel.base64ToBuffer(payload.data) const vector = Unibabel.base64ToBuffer(payload.iv) return new Promise((resolve, reject) => { - var result + let result try { result = asmcrypto.AES_GCM.decrypt(encryptedData, key, vector) } catch (err) { @@ -72,12 +72,12 @@ class EdgeEncryptor { */ _keyFromPassword (password, salt) { - var passBuffer = Unibabel.utf8ToBuffer(password) - var saltBuffer = Unibabel.base64ToBuffer(salt) + const passBuffer = Unibabel.utf8ToBuffer(password) + const saltBuffer = Unibabel.base64ToBuffer(salt) const iterations = 10000 const length = 32 // SHA256 hash size return new Promise((resolve) => { - var key = asmcrypto.Pbkdf2HmacSha256(passBuffer, saltBuffer, iterations, length) + const key = asmcrypto.Pbkdf2HmacSha256(passBuffer, saltBuffer, iterations, length) resolve(key) }) } @@ -89,9 +89,9 @@ class EdgeEncryptor { * @returns {string} Randomized base64 encoded data */ _generateSalt (byteCount = 32) { - var view = new Uint8Array(byteCount) + const view = new Uint8Array(byteCount) global.crypto.getRandomValues(view) - var b64encoded = btoa(String.fromCharCode.apply(null, view)) + const b64encoded = btoa(String.fromCharCode.apply(null, view)) return b64encoded } } diff --git a/app/scripts/lib/cleanErrorStack.js b/app/scripts/lib/cleanErrorStack.js index 8adf55db7..58f7ccfdf 100644 --- a/app/scripts/lib/cleanErrorStack.js +++ b/app/scripts/lib/cleanErrorStack.js @@ -4,10 +4,10 @@ * @returns {Error} Error with clean stack trace. */ function cleanErrorStack (err) { - var name = err.name + let name = err.name name = (name === undefined) ? 'Error' : String(name) - var msg = err.message + let msg = err.message msg = (msg === undefined) ? '' : String(msg) if (name === '') { diff --git a/app/scripts/lib/message-manager.js b/app/scripts/lib/message-manager.js index 9f087abad..c66b3a9e1 100644 --- a/app/scripts/lib/message-manager.js +++ b/app/scripts/lib/message-manager.js @@ -109,9 +109,9 @@ module.exports = class MessageManager extends EventEmitter { } msgParams.data = normalizeMsgData(msgParams.data) // create txData obj with parameters and meta data - var time = (new Date()).getTime() - var msgId = createId() - var msgData = { + const time = (new Date()).getTime() + const msgId = createId() + const msgData = { id: msgId, msgParams: msgParams, time: time, diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index eea8e286d..c538ef17f 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -117,9 +117,9 @@ module.exports = class PersonalMessageManager extends EventEmitter { } msgParams.data = this.normalizeMsgData(msgParams.data) // create txData obj with parameters and meta data - var time = (new Date()).getTime() - var msgId = createId() - var msgData = { + const time = (new Date()).getTime() + const msgId = createId() + const msgData = { id: msgId, msgParams: msgParams, time: time, diff --git a/app/scripts/lib/typed-message-manager.js b/app/scripts/lib/typed-message-manager.js index e87704712..7a73e7761 100644 --- a/app/scripts/lib/typed-message-manager.js +++ b/app/scripts/lib/typed-message-manager.js @@ -111,9 +111,9 @@ module.exports = class TypedMessageManager extends EventEmitter { log.debug(`TypedMessageManager addUnapprovedMessage: ${JSON.stringify(msgParams)}`) // create txData obj with parameters and meta data - var time = (new Date()).getTime() - var msgId = createId() - var msgData = { + const time = (new Date()).getTime() + const msgId = createId() + const msgData = { id: msgId, msgParams: msgParams, time: time, diff --git a/development/announcer.js b/development/announcer.js index ea1bfdd36..8b0c1de27 100644 --- a/development/announcer.js +++ b/development/announcer.js @@ -1,11 +1,11 @@ -var manifest = require('../app/manifest.json') -var version = manifest.version +const manifest = require('../app/manifest.json') +const version = manifest.version -var fs = require('fs') -var path = require('path') -var changelog = fs.readFileSync(path.join(__dirname, '..', 'CHANGELOG.md')).toString() +const fs = require('fs') +const path = require('path') +const changelog = fs.readFileSync(path.join(__dirname, '..', 'CHANGELOG.md')).toString() -var log = changelog.split(version)[1].split('##')[0].trim() +const log = changelog.split(version)[1].split('##')[0].trim() const msg = `*MetaMask ${version}* now published! It should auto-update soon!\n${log}` diff --git a/development/mock-dev.js b/development/mock-dev.js index cbb436890..16fdd0273 100644 --- a/development/mock-dev.js +++ b/development/mock-dev.js @@ -94,7 +94,7 @@ function modifyBackgroundConnection (backgroundConnectionModifier) { } // parse opts -var store = configureStore(firstState) +const store = configureStore(firstState) // start app startApp() diff --git a/development/sourcemap-validator.js b/development/sourcemap-validator.js index 44336df9e..22c448862 100644 --- a/development/sourcemap-validator.js +++ b/development/sourcemap-validator.js @@ -96,8 +96,8 @@ async function validateSourcemapForFile ({ buildName }) { } function indicesOf (substring, string) { - var a = [] - var i = -1 + const a = [] + let i = -1 while ((i = string.indexOf(substring, i + 1)) >= 0) { a.push(i) } diff --git a/test/e2e/web3.spec.js b/test/e2e/web3.spec.js index f576b397f..8c0853755 100644 --- a/test/e2e/web3.spec.js +++ b/test/e2e/web3.spec.js @@ -30,7 +30,7 @@ describe('Using MetaMask with an existing account', function () { await delay(largeDelayMs) const [results] = await findElements(driver, By.css('#results')) const resulttext = await results.getText() - var parsedData = JSON.parse(resulttext) + const parsedData = JSON.parse(resulttext) return (parsedData) @@ -153,14 +153,14 @@ describe('Using MetaMask with an existing account', function () { it('testing hexa methods', async () => { - var List = await driver.findElements(By.className('hexaNumberMethods')) + const List = await driver.findElements(By.className('hexaNumberMethods')) for (let i = 0; i < List.length; i++) { try { - var parsedData = await button(List[i]) + const parsedData = await button(List[i]) console.log(parsedData) - var result = parseInt(parsedData.result, 16) + const result = parseInt(parsedData.result, 16) assert.equal((typeof result === 'number'), true) await delay(regularDelayMs) @@ -174,14 +174,14 @@ describe('Using MetaMask with an existing account', function () { it('testing booleanMethods', async () => { - var List = await driver.findElements(By.className('booleanMethods')) + const List = await driver.findElements(By.className('booleanMethods')) for (let i = 0; i < List.length; i++) { try { - var parsedData = await button(List[i]) + const parsedData = await button(List[i]) console.log(parsedData) - var result = parsedData.result + const result = parsedData.result assert.equal(result, false) await delay(regularDelayMs) @@ -197,16 +197,16 @@ describe('Using MetaMask with an existing account', function () { it('testing transactionMethods', async () => { - var List = await driver.findElements(By.className('transactionMethods')) + const List = await driver.findElements(By.className('transactionMethods')) for (let i = 0; i < List.length; i++) { try { - var parsedData = await button(List[i]) + const parsedData = await button(List[i]) console.log(parsedData.result.blockHash) - var result = [] + const result = [] result.push(parseInt(parsedData.result.blockHash, 16)) result.push(parseInt(parsedData.result.blockNumber, 16)) result.push(parseInt(parsedData.result.gas, 16)) @@ -239,17 +239,17 @@ describe('Using MetaMask with an existing account', function () { it('testing blockMethods', async () => { - var List = await driver.findElements(By.className('blockMethods')) + const List = await driver.findElements(By.className('blockMethods')) for (let i = 0; i < List.length; i++) { try { - var parsedData = await button(List[i]) + const parsedData = await button(List[i]) console.log(JSON.stringify(parsedData) + i) console.log(parsedData.result.parentHash) - var result = parseInt(parsedData.result.parentHash, 16) + const result = parseInt(parsedData.result.parentHash, 16) assert.equal((typeof result === 'number'), true) await delay(regularDelayMs) @@ -265,9 +265,9 @@ describe('Using MetaMask with an existing account', function () { it('testing methods', async () => { - var List = await driver.findElements(By.className('methods')) - var parsedData - var result + const List = await driver.findElements(By.className('methods')) + let parsedData + let result for (let i = 0; i < List.length; i++) { try { diff --git a/test/helper.js b/test/helper.js index a49249062..bea0b326c 100644 --- a/test/helper.js +++ b/test/helper.js @@ -17,7 +17,7 @@ server.listen(8545, () => { }) // logging util -var log = require('loglevel') +const log = require('loglevel') log.setDefaultLevel(5) global.log = log @@ -62,7 +62,7 @@ function enableFailureOnUnhandledPromiseRejection () { throw evt.detail.reason }) } else { - var oldOHR = window.onunhandledrejection + const oldOHR = window.onunhandledrejection window.onunhandledrejection = function (evt) { if (typeof oldOHR === 'function') { oldOHR.apply(this, arguments) diff --git a/test/lib/mock-encryptor.js b/test/lib/mock-encryptor.js index 23ab2404f..0f70b5b3c 100644 --- a/test/lib/mock-encryptor.js +++ b/test/lib/mock-encryptor.js @@ -1,5 +1,5 @@ -var mockHex = '0xabcdef0123456789' -var mockKey = Buffer.alloc(32) +const mockHex = '0xabcdef0123456789' +const mockKey = Buffer.alloc(32) let cacheVal module.exports = { diff --git a/test/lib/mock-simple-keychain.js b/test/lib/mock-simple-keychain.js index daf6001c4..74e6fd8a2 100644 --- a/test/lib/mock-simple-keychain.js +++ b/test/lib/mock-simple-keychain.js @@ -1,4 +1,4 @@ -var fakeWallet = { +const fakeWallet = { privKey: '0x123456788890abcdef', address: '0xfedcba0987654321', } @@ -28,7 +28,7 @@ module.exports = class MockSimpleKeychain { } addAccounts (n = 1) { - for (var i = 0; i < n; i++) { + for (let i = 0; i < n; i++) { this.wallets.push(fakeWallet) } } diff --git a/test/lib/react-trigger-change.js b/test/lib/react-trigger-change.js index d169dd614..52fe779c1 100644 --- a/test/lib/react-trigger-change.js +++ b/test/lib/react-trigger-change.js @@ -18,7 +18,7 @@ // Constants and functions are declared inside the closure. // In this way, reactTriggerChange can be passed directly to executeScript in Selenium. module.exports = function reactTriggerChange (node) { - var supportedInputTypes = { + const supportedInputTypes = { color: true, date: true, datetime: true, @@ -35,27 +35,27 @@ module.exports = function reactTriggerChange (node) { url: true, week: true, } - var nodeName = node.nodeName.toLowerCase() - var type = node.type - var event - var descriptor - var initialValue - var initialChecked - var initialCheckedRadio + const nodeName = node.nodeName.toLowerCase() + const type = node.type + let event + let descriptor + let initialValue + let initialChecked + let initialCheckedRadio // Do not try to delete non-configurable properties. // Value and checked properties on DOM elements are non-configurable in PhantomJS. function deletePropertySafe (elem, prop) { - var desc = Object.getOwnPropertyDescriptor(elem, prop) + const desc = Object.getOwnPropertyDescriptor(elem, prop) if (desc && desc.configurable) { delete elem[prop] } } function getCheckedRadio (radio) { - var name = radio.name - var radios - var i + const name = radio.name + let radios + let i if (name) { radios = document.querySelectorAll('input[type="radio"][name="' + name + '"]') for (i = 0; i < radios.length; i += 1) { diff --git a/test/unit/actions/config_test.js b/test/unit/actions/config_test.js index 9127474a8..39224a9b1 100644 --- a/test/unit/actions/config_test.js +++ b/test/unit/actions/config_test.js @@ -1,13 +1,13 @@ // var jsdom = require('mocha-jsdom') -var assert = require('assert') -var freeze = require('deep-freeze-strict') -var path = require('path') +const assert = require('assert') +const freeze = require('deep-freeze-strict') +const path = require('path') -var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js')) -var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js')) +const actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js')) +const reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js')) describe('config view actions', function () { - var initialState = { + const initialState = { metamask: { rpcTarget: 'foo', frequentRpcList: [], @@ -22,7 +22,7 @@ describe('config view actions', function () { describe('SHOW_CONFIG_PAGE', function () { it('should set appState.currentView.name to config', function () { - var result = reducers(initialState, actions.showConfigPage()) + const result = reducers(initialState, actions.showConfigPage()) assert.equal(result.appState.currentView.name, 'config') }) }) @@ -34,7 +34,7 @@ describe('config view actions', function () { value: 'foo', } - var result = reducers(initialState, action) + const result = reducers(initialState, action) assert.equal(result.metamask.provider.type, 'rpc') assert.equal(result.metamask.provider.rpcTarget, 'foo') }) diff --git a/test/unit/actions/set_selected_account_test.js b/test/unit/actions/set_selected_account_test.js index 36d312d7b..0488c844e 100644 --- a/test/unit/actions/set_selected_account_test.js +++ b/test/unit/actions/set_selected_account_test.js @@ -1,14 +1,14 @@ // var jsdom = require('mocha-jsdom') -var assert = require('assert') -var freeze = require('deep-freeze-strict') -var path = require('path') +const assert = require('assert') +const freeze = require('deep-freeze-strict') +const path = require('path') -var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js')) -var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js')) +const actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js')) +const reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js')) describe('SET_SELECTED_ACCOUNT', function () { it('sets the state.appState.activeAddress property of the state to the action.value', function () { - var initialState = { + const initialState = { appState: { activeAddress: 'foo', }, @@ -21,14 +21,14 @@ describe('SET_SELECTED_ACCOUNT', function () { } freeze(action) - var resultingState = reducers(initialState, action) + const resultingState = reducers(initialState, action) assert.equal(resultingState.appState.activeAddress, action.value) }) }) describe('SHOW_ACCOUNT_DETAIL', function () { it('updates metamask state', function () { - var initialState = { + const initialState = { metamask: { selectedAddress: 'foo', }, @@ -41,7 +41,7 @@ describe('SHOW_ACCOUNT_DETAIL', function () { } freeze(action) - var resultingState = reducers(initialState, action) + const resultingState = reducers(initialState, action) assert.equal(resultingState.metamask.selectedAddress, action.value) }) }) diff --git a/test/unit/actions/tx_test.js b/test/unit/actions/tx_test.js index ca1225113..0b2da16aa 100644 --- a/test/unit/actions/tx_test.js +++ b/test/unit/actions/tx_test.js @@ -1,5 +1,5 @@ -var assert = require('assert') -var path = require('path') +const assert = require('assert') +const path = require('path') import configureMockStore from 'redux-mock-store' import thunk from 'redux-thunk' diff --git a/test/unit/actions/view_info_test.js b/test/unit/actions/view_info_test.js index 5785a368c..4792af727 100644 --- a/test/unit/actions/view_info_test.js +++ b/test/unit/actions/view_info_test.js @@ -1,14 +1,14 @@ // var jsdom = require('mocha-jsdom') -var assert = require('assert') -var freeze = require('deep-freeze-strict') -var path = require('path') +const assert = require('assert') +const freeze = require('deep-freeze-strict') +const path = require('path') -var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js')) -var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js')) +const actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js')) +const reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js')) describe('SHOW_INFO_PAGE', function () { it('sets the state.appState.currentView.name property to info', function () { - var initialState = { + const initialState = { appState: { activeAddress: 'foo', }, @@ -16,7 +16,7 @@ describe('SHOW_INFO_PAGE', function () { freeze(initialState) const action = actions.showInfoPage() - var resultingState = reducers(initialState, action) + const resultingState = reducers(initialState, action) assert.equal(resultingState.appState.currentView.name, 'info') }) }) diff --git a/test/unit/actions/warning_test.js b/test/unit/actions/warning_test.js index e57374cda..ac639f600 100644 --- a/test/unit/actions/warning_test.js +++ b/test/unit/actions/warning_test.js @@ -1,14 +1,14 @@ // var jsdom = require('mocha-jsdom') -var assert = require('assert') -var freeze = require('deep-freeze-strict') -var path = require('path') +const assert = require('assert') +const freeze = require('deep-freeze-strict') +const path = require('path') -var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js')) -var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js')) +const actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js')) +const reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js')) describe('action DISPLAY_WARNING', function () { it('sets appState.warning to provided value', function () { - var initialState = { + const initialState = { appState: {}, } freeze(initialState) diff --git a/test/unit/app/controllers/detect-tokens-test.js b/test/unit/app/controllers/detect-tokens-test.js index 8f18406f4..c65ee97ab 100644 --- a/test/unit/app/controllers/detect-tokens-test.js +++ b/test/unit/app/controllers/detect-tokens-test.js @@ -54,7 +54,7 @@ describe('DetectTokensController', () => { controller.isOpen = true controller.isUnlocked = true - var stub = sandbox.stub(controller, 'detectNewTokens') + const stub = sandbox.stub(controller, 'detectNewTokens') clock.tick(1) sandbox.assert.notCalled(stub) @@ -70,7 +70,7 @@ describe('DetectTokensController', () => { controller.isOpen = true controller.isUnlocked = true - var stub = sandbox.stub(controller, 'detectTokenBalance') + const stub = sandbox.stub(controller, 'detectTokenBalance') .withArgs('0x0D262e5dC4A06a0F1c90cE79C7a60C09DfC884E4').returns(true) .withArgs('0xBC86727E770de68B1060C91f6BB6945c73e10388').returns(true) @@ -114,7 +114,7 @@ describe('DetectTokensController', () => { it('should trigger detect new tokens when change address', async () => { controller.isOpen = true controller.isUnlocked = true - var stub = sandbox.stub(controller, 'detectNewTokens') + const stub = sandbox.stub(controller, 'detectNewTokens') await preferences.setSelectedAddress('0xbc86727e770de68b1060c91f6bb6945c73e10388') sandbox.assert.called(stub) }) @@ -122,7 +122,7 @@ describe('DetectTokensController', () => { it('should trigger detect new tokens when submit password', async () => { controller.isOpen = true controller.selectedAddress = '0x0' - var stub = sandbox.stub(controller, 'detectNewTokens') + const stub = sandbox.stub(controller, 'detectNewTokens') await controller._keyringMemStore.updateState({ isUnlocked: true }) sandbox.assert.called(stub) }) @@ -130,7 +130,7 @@ describe('DetectTokensController', () => { it('should not trigger detect new tokens when not open or not unlocked', async () => { controller.isOpen = true controller.isUnlocked = false - var stub = sandbox.stub(controller, 'detectTokenBalance') + const stub = sandbox.stub(controller, 'detectTokenBalance') clock.tick(180000) sandbox.assert.notCalled(stub) controller.isOpen = false diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js index f9dc9c099..f49e518c3 100644 --- a/test/unit/app/controllers/preferences-controller-test.js +++ b/test/unit/app/controllers/preferences-controller-test.js @@ -342,7 +342,7 @@ describe('preferences controller', function () { }) describe('on watchAsset', function () { - var stubNext, stubEnd, stubHandleWatchAssetERC20, asy, req, res + let stubNext, stubEnd, stubHandleWatchAssetERC20, asy, req, res const sandbox = sinon.createSandbox() beforeEach(() => { @@ -359,8 +359,8 @@ describe('preferences controller', function () { it('shouldn not do anything if method not corresponds', async function () { const asy = {next: () => {}, end: () => {}} - var stubNext = sandbox.stub(asy, 'next') - var stubEnd = sandbox.stub(asy, 'end').returns(0) + const stubNext = sandbox.stub(asy, 'next') + const stubEnd = sandbox.stub(asy, 'end').returns(0) req.method = 'metamask' await preferencesController.requestWatchAsset(req, res, asy.next, asy.end) sandbox.assert.notCalled(stubEnd) @@ -368,8 +368,8 @@ describe('preferences controller', function () { }) it('should do something if method is supported', async function () { const asy = {next: () => {}, end: () => {}} - var stubNext = sandbox.stub(asy, 'next') - var stubEnd = sandbox.stub(asy, 'end').returns(0) + const stubNext = sandbox.stub(asy, 'next') + const stubEnd = sandbox.stub(asy, 'end').returns(0) req.method = 'metamask_watchAsset' req.params.type = 'someasset' await preferencesController.requestWatchAsset(req, res, asy.next, asy.end) @@ -400,7 +400,7 @@ describe('preferences controller', function () { }) describe('on watchAsset of type ERC20', function () { - var req + let req const sandbox = sinon.createSandbox() beforeEach(() => { diff --git a/test/unit/app/controllers/transactions/tx-utils-test.js b/test/unit/app/controllers/transactions/tx-utils-test.js index 1c5d20b09..e8bc8a5b7 100644 --- a/test/unit/app/controllers/transactions/tx-utils-test.js +++ b/test/unit/app/controllers/transactions/tx-utils-test.js @@ -5,7 +5,7 @@ const txUtils = require('../../../../../app/scripts/controllers/transactions/lib describe('txUtils', function () { describe('#validateTxParams', function () { it('does not throw for positive values', function () { - var sample = { + const sample = { from: '0x1678a085c290ebd122dc42cba69373b5953b831d', value: '0x01', } @@ -13,7 +13,7 @@ describe('txUtils', function () { }) it('returns error for negative values', function () { - var sample = { + const sample = { from: '0x1678a085c290ebd122dc42cba69373b5953b831d', value: '-0x01', } diff --git a/test/unit/app/edge-encryptor-test.js b/test/unit/app/edge-encryptor-test.js index ad873e351..3f2e8830a 100644 --- a/test/unit/app/edge-encryptor-test.js +++ b/test/unit/app/edge-encryptor-test.js @@ -2,8 +2,8 @@ const assert = require('assert') const EdgeEncryptor = require('../../../app/scripts/edge-encryptor') -var password = 'passw0rd1' -var data = 'some random data' +const password = 'passw0rd1' +const data = 'some random data' global.crypto = global.crypto || { getRandomValues: function (array) { diff --git a/test/unit/app/message-manager-test.js b/test/unit/app/message-manager-test.js index 36ef6c29f..b824acfe7 100644 --- a/test/unit/app/message-manager-test.js +++ b/test/unit/app/message-manager-test.js @@ -10,7 +10,7 @@ describe('Message Manager', function () { describe('#getMsgList', function () { it('when new should return empty array', function () { - var result = messageManager.messages + const result = messageManager.messages assert.ok(Array.isArray(result)) assert.equal(result.length, 0) }) @@ -21,9 +21,9 @@ describe('Message Manager', function () { describe('#addMsg', function () { it('adds a Msg returned in getMsgList', function () { - var Msg = { id: 1, status: 'approved', metamaskNetworkId: 'unit test' } + const Msg = { id: 1, status: 'approved', metamaskNetworkId: 'unit test' } messageManager.addMsg(Msg) - var result = messageManager.messages + const result = messageManager.messages assert.ok(Array.isArray(result)) assert.equal(result.length, 1) assert.equal(result[0].id, 1) @@ -32,10 +32,10 @@ describe('Message Manager', function () { describe('#setMsgStatusApproved', function () { it('sets the Msg status to approved', function () { - var Msg = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test' } + const Msg = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test' } messageManager.addMsg(Msg) messageManager.setMsgStatusApproved(1) - var result = messageManager.messages + const result = messageManager.messages assert.ok(Array.isArray(result)) assert.equal(result.length, 1) assert.equal(result[0].status, 'approved') @@ -44,10 +44,10 @@ describe('Message Manager', function () { describe('#rejectMsg', function () { it('sets the Msg status to rejected', function () { - var Msg = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test' } + const Msg = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test' } messageManager.addMsg(Msg) messageManager.rejectMsg(1) - var result = messageManager.messages + const result = messageManager.messages assert.ok(Array.isArray(result)) assert.equal(result.length, 1) assert.equal(result[0].status, 'rejected') @@ -59,7 +59,7 @@ describe('Message Manager', function () { messageManager.addMsg({ id: '1', status: 'unapproved', metamaskNetworkId: 'unit test' }) messageManager.addMsg({ id: '2', status: 'approved', metamaskNetworkId: 'unit test' }) messageManager._updateMsg({ id: '1', status: 'blah', hash: 'foo', metamaskNetworkId: 'unit test' }) - var result = messageManager.getMsg('1') + const result = messageManager.getMsg('1') assert.equal(result.hash, 'foo') }) }) diff --git a/test/unit/app/personal-message-manager-test.js b/test/unit/app/personal-message-manager-test.js index b07167bff..52cbdb75c 100644 --- a/test/unit/app/personal-message-manager-test.js +++ b/test/unit/app/personal-message-manager-test.js @@ -11,7 +11,7 @@ describe('Personal Message Manager', function () { describe('#getMsgList', function () { it('when new should return empty array', function () { - var result = messageManager.messages + const result = messageManager.messages assert.ok(Array.isArray(result)) assert.equal(result.length, 0) }) @@ -22,9 +22,9 @@ describe('Personal Message Manager', function () { describe('#addMsg', function () { it('adds a Msg returned in getMsgList', function () { - var Msg = { id: 1, status: 'approved', metamaskNetworkId: 'unit test' } + const Msg = { id: 1, status: 'approved', metamaskNetworkId: 'unit test' } messageManager.addMsg(Msg) - var result = messageManager.messages + const result = messageManager.messages assert.ok(Array.isArray(result)) assert.equal(result.length, 1) assert.equal(result[0].id, 1) @@ -33,10 +33,10 @@ describe('Personal Message Manager', function () { describe('#setMsgStatusApproved', function () { it('sets the Msg status to approved', function () { - var Msg = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test' } + const Msg = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test' } messageManager.addMsg(Msg) messageManager.setMsgStatusApproved(1) - var result = messageManager.messages + const result = messageManager.messages assert.ok(Array.isArray(result)) assert.equal(result.length, 1) assert.equal(result[0].status, 'approved') @@ -45,10 +45,10 @@ describe('Personal Message Manager', function () { describe('#rejectMsg', function () { it('sets the Msg status to rejected', function () { - var Msg = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test' } + const Msg = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test' } messageManager.addMsg(Msg) messageManager.rejectMsg(1) - var result = messageManager.messages + const result = messageManager.messages assert.ok(Array.isArray(result)) assert.equal(result.length, 1) assert.equal(result[0].status, 'rejected') @@ -60,7 +60,7 @@ describe('Personal Message Manager', function () { messageManager.addMsg({ id: '1', status: 'unapproved', metamaskNetworkId: 'unit test' }) messageManager.addMsg({ id: '2', status: 'approved', metamaskNetworkId: 'unit test' }) messageManager._updateMsg({ id: '1', status: 'blah', hash: 'foo', metamaskNetworkId: 'unit test' }) - var result = messageManager.getMsg('1') + const result = messageManager.getMsg('1') assert.equal(result.hash, 'foo') }) }) @@ -87,20 +87,20 @@ describe('Personal Message Manager', function () { describe('#normalizeMsgData', function () { it('converts text to a utf8 hex string', function () { - var input = 'hello' - var output = messageManager.normalizeMsgData(input) + const input = 'hello' + const output = messageManager.normalizeMsgData(input) assert.equal(output, '0x68656c6c6f', 'predictably hex encoded') }) it('tolerates a hex prefix', function () { - var input = '0x12' - var output = messageManager.normalizeMsgData(input) + const input = '0x12' + const output = messageManager.normalizeMsgData(input) assert.equal(output, '0x12', 'un modified') }) it('tolerates normal hex', function () { - var input = '12' - var output = messageManager.normalizeMsgData(input) + const input = '12' + const output = messageManager.normalizeMsgData(input) assert.equal(output, '0x12', 'adds prefix') }) }) diff --git a/test/unit/reducers/unlock_vault_test.js b/test/unit/reducers/unlock_vault_test.js index d66891a63..bb992ab40 100644 --- a/test/unit/reducers/unlock_vault_test.js +++ b/test/unit/reducers/unlock_vault_test.js @@ -1,11 +1,11 @@ // var jsdom = require('mocha-jsdom') -var assert = require('assert') +const assert = require('assert') // var freeze = require('deep-freeze-strict') -var path = require('path') -var sinon = require('sinon') +const path = require('path') +const sinon = require('sinon') -var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js')) -var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js')) +const actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'store', 'actions.js')) +const reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'ducks', 'index.js')) describe('#unlockMetamask(selectedAccount)', function () { beforeEach(function () { diff --git a/test/unit/util_test.js b/test/unit/util_test.js index 768288ce7..ffb220276 100644 --- a/test/unit/util_test.js +++ b/test/unit/util_test.js @@ -1,13 +1,13 @@ -var assert = require('assert') -var sinon = require('sinon') +const assert = require('assert') +const sinon = require('sinon') const ethUtil = require('ethereumjs-util') -var path = require('path') -var util = require(path.join(__dirname, '..', '..', 'ui', 'app', 'helpers', 'utils', 'util.js')) +const path = require('path') +const util = require(path.join(__dirname, '..', '..', 'ui', 'app', 'helpers', 'utils', 'util.js')) describe('util', function () { - var ethInWei = '1' - for (var i = 0; i < 18; i++) { + let ethInWei = '1' + for (let i = 0; i < 18; i++) { ethInWei += '0' } @@ -47,52 +47,52 @@ describe('util', function () { describe('#addressSummary', function () { it('should add case-sensitive checksum', function () { - var address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825' - var result = util.addressSummary(address) + const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825' + const result = util.addressSummary(address) assert.equal(result, '0xFDEa65C8...b825') }) it('should accept arguments for firstseg, lastseg, and keepPrefix', function () { - var address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825' - var result = util.addressSummary(address, 4, 4, false) + const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825' + const result = util.addressSummary(address, 4, 4, false) assert.equal(result, 'FDEa...b825') }) }) describe('#isValidAddress', function () { it('should allow 40-char non-prefixed hex', function () { - var address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b825' - var result = util.isValidAddress(address) + const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b825' + const result = util.isValidAddress(address) assert.ok(result) }) it('should allow 42-char non-prefixed hex', function () { - var address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825' - var result = util.isValidAddress(address) + const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825' + const result = util.isValidAddress(address) assert.ok(result) }) it('should not allow less non hex-prefixed', function () { - var address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b85' - var result = util.isValidAddress(address) + const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b85' + const result = util.isValidAddress(address) assert.ok(!result) }) it('should not allow less hex-prefixed', function () { - var address = '0xfdea65ce26263f6d9a1b5de9555d2931a33b85' - var result = util.isValidAddress(address) + const address = '0xfdea65ce26263f6d9a1b5de9555d2931a33b85' + const result = util.isValidAddress(address) assert.ok(!result) }) it('should recognize correct capitalized checksum', function () { - var address = '0xFDEa65C8e26263F6d9A1B5de9555D2931A33b825' - var result = util.isValidAddress(address) + const address = '0xFDEa65C8e26263F6d9A1B5de9555D2931A33b825' + const result = util.isValidAddress(address) assert.ok(result) }) it('should recognize incorrect capitalized checksum', function () { - var address = '0xFDea65C8e26263F6d9A1B5de9555D2931A33b825' - var result = util.isValidAddress(address) + const address = '0xFDea65C8e26263F6d9A1B5de9555D2931A33b825' + const result = util.isValidAddress(address) assert.ok(!result) }) @@ -107,58 +107,58 @@ describe('util', function () { describe('#numericBalance', function () { it('should return a BN 0 if given nothing', function () { - var result = util.numericBalance() + const result = util.numericBalance() assert.equal(result.toString(10), 0) }) it('should work with hex prefix', function () { - var result = util.numericBalance('0x012') + const result = util.numericBalance('0x012') assert.equal(result.toString(10), '18') }) it('should work with no hex prefix', function () { - var result = util.numericBalance('012') + const result = util.numericBalance('012') assert.equal(result.toString(10), '18') }) }) describe('#formatBalance', function () { it('when given nothing', function () { - var result = util.formatBalance() + const result = util.formatBalance() assert.equal(result, 'None', 'should return "None"') }) it('should return eth as string followed by ETH', function () { - var input = new ethUtil.BN(ethInWei, 10).toJSON() - var result = util.formatBalance(input, 4) + const input = new ethUtil.BN(ethInWei, 10).toJSON() + const result = util.formatBalance(input, 4) assert.equal(result, '1.0000 ETH') }) it('should return eth as string followed by ETH', function () { - var input = new ethUtil.BN(ethInWei, 10).div(new ethUtil.BN('2', 10)).toJSON() - var result = util.formatBalance(input, 3) + const input = new ethUtil.BN(ethInWei, 10).div(new ethUtil.BN('2', 10)).toJSON() + const result = util.formatBalance(input, 3) assert.equal(result, '0.500 ETH') }) it('should display specified decimal points', function () { - var input = '0x128dfa6a90b28000' - var result = util.formatBalance(input, 2) + const input = '0x128dfa6a90b28000' + const result = util.formatBalance(input, 2) assert.equal(result, '1.33 ETH') }) it('should default to 3 decimal points', function () { - var input = '0x128dfa6a90b28000' - var result = util.formatBalance(input) + const input = '0x128dfa6a90b28000' + const result = util.formatBalance(input) assert.equal(result, '1.337 ETH') }) it('should show 2 significant digits for tiny balances', function () { - var input = '0x1230fa6a90b28' - var result = util.formatBalance(input) + const input = '0x1230fa6a90b28' + const result = util.formatBalance(input) assert.equal(result, '0.00032 ETH') }) it('should not parse the balance and return value with 2 decimal points with ETH at the end', function () { - var value = '1.2456789' - var needsParse = false - var result = util.formatBalance(value, 2, needsParse) + const value = '1.2456789' + const needsParse = false + const result = util.formatBalance(value, 2, needsParse) assert.equal(result, '1.24 ETH') }) }) @@ -166,7 +166,7 @@ describe('util', function () { describe('normalizing values', function () { describe('#normalizeToWei', function () { it('should convert an eth to the appropriate equivalent values', function () { - var valueTable = { + const valueTable = { wei: '1000000000000000000', kwei: '1000000000000000', mwei: '1000000000000', @@ -181,11 +181,11 @@ describe('util', function () { // gether:'0.000000001', // tether:'0.000000000001', } - var oneEthBn = new ethUtil.BN(ethInWei, 10) + const oneEthBn = new ethUtil.BN(ethInWei, 10) - for (var currency in valueTable) { - var value = new ethUtil.BN(valueTable[currency], 10) - var output = util.normalizeToWei(value, currency) + for (const currency in valueTable) { + const value = new ethUtil.BN(valueTable[currency], 10) + const output = util.normalizeToWei(value, currency) assert.equal(output.toString(10), valueTable.wei, `value of ${output.toString(10)} ${currency} should convert to ${oneEthBn}`) } }) @@ -193,66 +193,66 @@ describe('util', function () { describe('#normalizeEthStringToWei', function () { it('should convert decimal eth to pure wei BN', function () { - var input = '1.23456789' - var output = util.normalizeEthStringToWei(input) + const input = '1.23456789' + const output = util.normalizeEthStringToWei(input) assert.equal(output.toString(10), '1234567890000000000') }) it('should convert 1 to expected wei', function () { - var input = '1' - var output = util.normalizeEthStringToWei(input) + const input = '1' + const output = util.normalizeEthStringToWei(input) assert.equal(output.toString(10), ethInWei) }) it('should account for overflow numbers gracefully by dropping extra precision.', function () { - var input = '1.11111111111111111111' - var output = util.normalizeEthStringToWei(input) + const input = '1.11111111111111111111' + const output = util.normalizeEthStringToWei(input) assert.equal(output.toString(10), '1111111111111111111') }) it('should not truncate very exact wei values that do not have extra precision.', function () { - var input = '1.100000000000000001' - var output = util.normalizeEthStringToWei(input) + const input = '1.100000000000000001' + const output = util.normalizeEthStringToWei(input) assert.equal(output.toString(10), '1100000000000000001') }) }) describe('#normalizeNumberToWei', function () { it('should handle a simple use case', function () { - var input = 0.0002 - var output = util.normalizeNumberToWei(input, 'ether') - var str = output.toString(10) + const input = 0.0002 + const output = util.normalizeNumberToWei(input, 'ether') + const str = output.toString(10) assert.equal(str, '200000000000000') }) it('should convert a kwei number to the appropriate equivalent wei', function () { - var result = util.normalizeNumberToWei(1.111, 'kwei') + const result = util.normalizeNumberToWei(1.111, 'kwei') assert.equal(result.toString(10), '1111', 'accepts decimals') }) it('should convert a ether number to the appropriate equivalent wei', function () { - var result = util.normalizeNumberToWei(1.111, 'ether') + const result = util.normalizeNumberToWei(1.111, 'ether') assert.equal(result.toString(10), '1111000000000000000', 'accepts decimals') }) }) describe('#isHex', function () { it('should return true when given a hex string', function () { - var result = util.isHex('c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2') + const result = util.isHex('c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2') assert(result) }) it('should return false when given a non-hex string', function () { - var result = util.isHex('c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714imnotreal') + const result = util.isHex('c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714imnotreal') assert(!result) }) it('should return false when given a string containing a non letter/number character', function () { - var result = util.isHex('c3ab8ff13720!8ad9047dd39466b3c%8974e592c2fa383d4a396071imnotreal') + const result = util.isHex('c3ab8ff13720!8ad9047dd39466b3c%8974e592c2fa383d4a396071imnotreal') assert(!result) }) it('should return true when given a hex string with hex-prefix', function () { - var result = util.isHex('0xc3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2') + const result = util.isHex('0xc3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2') assert(result) }) }) diff --git a/test/web3/schema.js b/test/web3/schema.js index 336060431..9dc528a57 100644 --- a/test/web3/schema.js +++ b/test/web3/schema.js @@ -1,6 +1,6 @@ /* eslint no-unused-vars: 0 */ -var params = { +const params = { // diffrent params used in the methods param: [], blockHashParams: '0xb3b20624f8f0f86eb50dd04688409e5cea4bd02d700bf6e79e9384d47d6a5a35', @@ -93,7 +93,7 @@ var params = { }, } -var methods = { +const methods = { hexaNumberMethods: { // these are the methods which have output in the form of hexa decimal numbers eth_blockNumber: ['eth_blockNumber', params.param, 'Q'], diff --git a/test/web3/web3.js b/test/web3/web3.js index 8f319f38e..3431ee8ba 100644 --- a/test/web3/web3.js +++ b/test/web3/web3.js @@ -1,6 +1,6 @@ /* eslint no-undef: 0 */ -var json = methods +const json = methods web3.currentProvider.enable().then(() => { diff --git a/ui/app/components/app/account-panel.js b/ui/app/components/app/account-panel.js index 2bae0a296..3ffd97887 100644 --- a/ui/app/components/app/account-panel.js +++ b/ui/app/components/app/account-panel.js @@ -13,12 +13,12 @@ function AccountPanel () { } AccountPanel.prototype.render = function () { - var state = this.props - var identity = state.identity || {} - var account = state.account || {} - var isFauceting = state.isFauceting + const state = this.props + const identity = state.identity || {} + const account = state.account || {} + const isFauceting = state.isFauceting - var panelState = { + const panelState = { key: `accountPanel${identity.address}`, identiconKey: identity.address, identiconLabel: identity.name || '', diff --git a/ui/app/components/app/menu-droppo.js b/ui/app/components/app/menu-droppo.js index 62c5ddb3b..57a0df2fe 100644 --- a/ui/app/components/app/menu-droppo.js +++ b/ui/app/components/app/menu-droppo.js @@ -98,7 +98,7 @@ MenuDroppoComponent.prototype.componentDidMount = function () { this.globalClickHandler = this.globalClickOccurred.bind(this) document.body.addEventListener('click', this.globalClickHandler) // eslint-disable-next-line react/no-find-dom-node - var container = findDOMNode(this) + const container = findDOMNode(this) this.container = container } } @@ -122,7 +122,7 @@ MenuDroppoComponent.prototype.globalClickOccurred = function (event) { } function isDescendant (parent, child) { - var node = child.parentNode + let node = child.parentNode while (node !== null) { if (node === parent) { return true diff --git a/ui/app/components/ui/fiat-value.js b/ui/app/components/ui/fiat-value.js index e3e2fd6be..a02264b01 100644 --- a/ui/app/components/ui/fiat-value.js +++ b/ui/app/components/ui/fiat-value.js @@ -19,8 +19,8 @@ FiatValue.prototype.render = function () { if (value === 'None') { return value } - var fiatDisplayNumber, fiatTooltipNumber - var splitBalance = value.split(' ') + let fiatDisplayNumber, fiatTooltipNumber + const splitBalance = value.split(' ') if (conversionRate !== 0) { fiatTooltipNumber = Number(splitBalance[0]) * conversionRate diff --git a/ui/app/components/ui/mascot.js b/ui/app/components/ui/mascot.js index 9606fb9aa..f84961745 100644 --- a/ui/app/components/ui/mascot.js +++ b/ui/app/components/ui/mascot.js @@ -33,8 +33,8 @@ Mascot.prototype.render = function Mascot () { } Mascot.prototype.componentDidMount = function () { - var targetDivId = 'metamask-mascot-container' - var container = document.getElementById(targetDivId) + const targetDivId = 'metamask-mascot-container' + const container = document.getElementById(targetDivId) container.appendChild(this.logo.container) } diff --git a/ui/app/ducks/app/app.js b/ui/app/ducks/app/app.js index fbdaf7b8d..34291df05 100644 --- a/ui/app/ducks/app/app.js +++ b/ui/app/ducks/app/app.js @@ -21,14 +21,14 @@ export default function reduceApp (state, action) { name = 'confTx' } - var defaultView = { + const defaultView = { name, detailView: null, context: selectedAddress, } // default state - var appState = extend({ + const appState = extend({ shouldClose: false, menuOpen: false, modal: { diff --git a/ui/app/ducks/metamask/metamask.js b/ui/app/ducks/metamask/metamask.js index 8a9739af7..13b6f8b28 100644 --- a/ui/app/ducks/metamask/metamask.js +++ b/ui/app/ducks/metamask/metamask.js @@ -10,7 +10,7 @@ function reduceMetamask (state, action) { let newState // clone + defaults - var metamaskState = extend({ + const metamaskState = extend({ isInitialized: false, isUnlocked: false, isAccountMenuOpen: false, @@ -99,7 +99,7 @@ function reduceMetamask (state, action) { }) case actions.COMPLETED_TX: - var stringId = String(action.id) + const stringId = String(action.id) newState = extend(metamaskState, { unapprovedTxs: {}, unapprovedMsgs: {}, diff --git a/ui/app/helpers/utils/util.js b/ui/app/helpers/utils/util.js index 96557c62e..05be6d406 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/app/helpers/utils/util.js @@ -12,7 +12,7 @@ function formatDate (date, format = 'M/d/y \'at\' T') { return DateTime.fromMillis(date).toFormat(format) } -var valueTable = { +const valueTable = { wei: '1000000000000000000', kwei: '1000000000000000', mwei: '1000000000000', @@ -25,8 +25,8 @@ var valueTable = { gether: '0.000000001', tether: '0.000000000001', } -var bnTable = {} -for (var currency in valueTable) { +const bnTable = {} +for (const currency in valueTable) { bnTable[currency] = new ethUtil.BN(valueTable[currency], 10) } @@ -97,12 +97,12 @@ function miniAddressSummary (address) { if (!address) { return '' } - var checked = checksumAddress(address) + const checked = checksumAddress(address) return checked ? checked.slice(0, 4) + '...' + checked.slice(-4) : '...' } function isValidAddress (address) { - var prefixed = ethUtil.addHexPrefix(address) + const prefixed = ethUtil.addHexPrefix(address) if (address === '0x0000000000000000000000000000000000000000') { return false } @@ -114,7 +114,7 @@ function isValidENSAddress (address) { } function isInvalidChecksumAddress (address) { - var prefixed = ethUtil.addHexPrefix(address) + const prefixed = ethUtil.addHexPrefix(address) if (address === '0x0000000000000000000000000000000000000000') { return false } @@ -125,8 +125,8 @@ function isAllOneCase (address) { if (!address) { return true } - var lower = address.toLowerCase() - var upper = address.toUpperCase() + const lower = address.toLowerCase() + const upper = address.toUpperCase() return address === lower || address === upper } @@ -135,18 +135,18 @@ function numericBalance (balance) { if (!balance) { return new ethUtil.BN(0, 16) } - var stripped = ethUtil.stripHexPrefix(balance) + const stripped = ethUtil.stripHexPrefix(balance) return new ethUtil.BN(stripped, 16) } // Takes hex, returns [beforeDecimal, afterDecimal] function parseBalance (balance) { - var beforeDecimal, afterDecimal + let afterDecimal const wei = numericBalance(balance) - var weiString = wei.toString() + const weiString = wei.toString() const trailingZeros = /0+$/ - beforeDecimal = weiString.length > 18 ? weiString.slice(0, weiString.length - 18) : '0' + const beforeDecimal = weiString.length > 18 ? weiString.slice(0, weiString.length - 18) : '0' afterDecimal = ('000000000000000000' + wei).slice(-18).replace(trailingZeros, '') if (afterDecimal === '') { afterDecimal = '0' @@ -157,14 +157,14 @@ function parseBalance (balance) { // Takes wei hex, returns an object with three properties. // Its "formatted" property is what we generally use to render values. function formatBalance (balance, decimalsToKeep, needsParse = true, ticker = 'ETH') { - var parsed = needsParse ? parseBalance(balance) : balance.split('.') - var beforeDecimal = parsed[0] - var afterDecimal = parsed[1] - var formatted = 'None' + const parsed = needsParse ? parseBalance(balance) : balance.split('.') + const beforeDecimal = parsed[0] + let afterDecimal = parsed[1] + let formatted = 'None' if (decimalsToKeep === undefined) { if (beforeDecimal === '0') { if (afterDecimal !== '0') { - var sigFigs = afterDecimal.match(/^0*(.{2})/) // default: grabs 2 most significant digits + const sigFigs = afterDecimal.match(/^0*(.{2})/) // default: grabs 2 most significant digits if (sigFigs) { afterDecimal = sigFigs[0] } @@ -182,11 +182,11 @@ function formatBalance (balance, decimalsToKeep, needsParse = true, ticker = 'ET function generateBalanceObject (formattedBalance, decimalsToKeep = 1) { - var balance = formattedBalance.split(' ')[0] - var label = formattedBalance.split(' ')[1] - var beforeDecimal = balance.split('.')[0] - var afterDecimal = balance.split('.')[1] - var shortBalance = shortenBalance(balance, decimalsToKeep) + let balance = formattedBalance.split(' ')[0] + const label = formattedBalance.split(' ')[1] + const beforeDecimal = balance.split('.')[0] + const afterDecimal = balance.split('.')[1] + const shortBalance = shortenBalance(balance, decimalsToKeep) if (beforeDecimal === '0' && afterDecimal.substr(0, 5) === '00000') { // eslint-disable-next-line eqeqeq @@ -203,8 +203,8 @@ function generateBalanceObject (formattedBalance, decimalsToKeep = 1) { } function shortenBalance (balance, decimalsToKeep = 1) { - var truncatedValue - var convertedBalance = parseFloat(balance) + let truncatedValue + const convertedBalance = parseFloat(balance) if (convertedBalance > 1000000) { truncatedValue = (balance / 1000000).toFixed(decimalsToKeep) return `${truncatedValue}m` @@ -216,7 +216,7 @@ function shortenBalance (balance, decimalsToKeep = 1) { } else if (convertedBalance < 0.001) { return '<0.001' } else if (convertedBalance < 1) { - var stringBalance = convertedBalance.toString() + const stringBalance = convertedBalance.toString() if (stringBalance.split('.')[1].length > 3) { return convertedBalance.toFixed(3) } else { @@ -228,7 +228,7 @@ function shortenBalance (balance, decimalsToKeep = 1) { } function dataSize (data) { - var size = data ? ethUtil.stripHexPrefix(data).length : 0 + const size = data ? ethUtil.stripHexPrefix(data).length : 0 return size + ' bytes' } @@ -245,7 +245,7 @@ function normalizeEthStringToWei (str) { const parts = str.split('.') let eth = new ethUtil.BN(parts[0], 10).mul(bnTable.wei) if (parts[1]) { - var decimal = parts[1] + let decimal = parts[1] while (decimal.length < 18) { decimal += '0' } @@ -258,24 +258,24 @@ function normalizeEthStringToWei (str) { return eth } -var multiple = new ethUtil.BN('10000', 10) +const multiple = new ethUtil.BN('10000', 10) function normalizeNumberToWei (n, currency) { - var enlarged = n * 10000 - var amount = new ethUtil.BN(String(enlarged), 10) + const enlarged = n * 10000 + const amount = new ethUtil.BN(String(enlarged), 10) return normalizeToWei(amount, currency).div(multiple) } function readableDate (ms) { - var date = new Date(ms) - var month = date.getMonth() - var day = date.getDate() - var year = date.getFullYear() - var hours = date.getHours() - var minutes = '0' + date.getMinutes() - var seconds = '0' + date.getSeconds() - - var dateStr = `${month}/${day}/${year}` - var time = `${hours}:${minutes.substr(-2)}:${seconds.substr(-2)}` + const date = new Date(ms) + const month = date.getMonth() + const day = date.getDate() + const year = date.getFullYear() + const hours = date.getHours() + const minutes = '0' + date.getMinutes() + const seconds = '0' + date.getSeconds() + + const dateStr = `${month}/${day}/${year}` + const time = `${hours}:${minutes.substr(-2)}:${seconds.substr(-2)}` return `${dateStr} ${time}` } diff --git a/ui/app/pages/confirm-transaction/conf-tx.js b/ui/app/pages/confirm-transaction/conf-tx.js index 5d8069d91..91ff4b9e4 100644 --- a/ui/app/pages/confirm-transaction/conf-tx.js +++ b/ui/app/pages/confirm-transaction/conf-tx.js @@ -153,7 +153,7 @@ ConfirmTxScreen.prototype.render = function () { conversionRate, } = this.props - var txData = this.getTxData() || {} + const txData = this.getTxData() || {} const { msgParams, type, msgParams: { version } } = txData log.debug('msgParams detected, rendering pending msg') @@ -186,7 +186,7 @@ ConfirmTxScreen.prototype.render = function () { ConfirmTxScreen.prototype.signMessage = function (msgData, event) { log.info('conf-tx.js: signing message') - var params = msgData.msgParams + const params = msgData.msgParams params.metamaskId = msgData.id this.stopPropagation(event) return this.props.dispatch(actions.signMsg(params)) @@ -200,7 +200,7 @@ ConfirmTxScreen.prototype.stopPropagation = function (event) { ConfirmTxScreen.prototype.signPersonalMessage = function (msgData, event) { log.info('conf-tx.js: signing personal message') - var params = msgData.msgParams + const params = msgData.msgParams params.metamaskId = msgData.id this.stopPropagation(event) return this.props.dispatch(actions.signPersonalMsg(params)) @@ -208,7 +208,7 @@ ConfirmTxScreen.prototype.signPersonalMessage = function (msgData, event) { ConfirmTxScreen.prototype.signTypedMessage = function (msgData, event) { log.info('conf-tx.js: signing typed message') - var params = msgData.msgParams + const params = msgData.msgParams params.metamaskId = msgData.id this.stopPropagation(event) return this.props.dispatch(actions.signTypedMsg(params)) diff --git a/ui/app/pages/routes/index.js b/ui/app/pages/routes/index.js index 64da523d6..93965a9fd 100644 --- a/ui/app/pages/routes/index.js +++ b/ui/app/pages/routes/index.js @@ -260,7 +260,7 @@ class Routes extends Component { toggleMetamaskActive () { if (!this.props.isUnlocked) { // currently inactive: redirect to password box - var passwordBox = document.querySelector('input[type=password]') + const passwordBox = document.querySelector('input[type=password]') if (!passwordBox) { return } diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index c78a8ab15..d6c29fcd6 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -17,7 +17,7 @@ const { hasUnconfirmedTransactions } = require('../helpers/utils/confirm-tx.util const gasDuck = require('../ducks/gas/gas.duck') const WebcamUtils = require('../../lib/webcam-utils') -var actions = { +const actions = { _setBackgroundConnection: _setBackgroundConnection, GO_HOME: 'GO_HOME', @@ -399,7 +399,7 @@ var actions = { module.exports = actions -var background = null +let background = null function _setBackgroundConnection (backgroundConnection) { background = backgroundConnection } @@ -2171,7 +2171,7 @@ function requestExportAccount () { } function exportAccount (password, address) { - var self = this + const self = this return function (dispatch) { dispatch(self.showLoadingIndication()) @@ -2305,7 +2305,7 @@ function pairUpdate (coin) { } function shapeShiftSubview () { - var pair = 'btc_eth' + const pair = 'btc_eth' return (dispatch) => { dispatch(actions.showSubLoadingIndication()) shapeShiftRequest('marketinfo', {pair}, (mktResponse) => { @@ -2334,7 +2334,7 @@ function coinShiftRquest (data, marketData) { if (response.error) { return dispatch(actions.displayWarning(response.error)) } - var message = ` + const message = ` Deposit your ${response.depositType} to the address below:` log.debug(`background.createShapeShiftTx`) background.createShapeShiftTx(response.deposit, response.depositType) @@ -2372,7 +2372,7 @@ function reshowQrCode (data, coin) { return dispatch(actions.displayWarning(mktResponse.error)) } - var message = [ + const message = [ `Deposit your ${coin} to the address below:`, `Deposit Limit: ${mktResponse.limit}`, `Deposit Minimum:${mktResponse.minimum}`, @@ -2385,10 +2385,10 @@ function reshowQrCode (data, coin) { } function shapeShiftRequest (query, options = {}, cb) { - var queryResponse, method + let queryResponse, method options.method ? method = options.method : method = 'GET' - var requestListner = function () { + const requestListner = function () { try { queryResponse = JSON.parse(this.responseText) if (cb) { @@ -2403,12 +2403,12 @@ function shapeShiftRequest (query, options = {}, cb) { } } - var shapShiftReq = new XMLHttpRequest() + const shapShiftReq = new XMLHttpRequest() shapShiftReq.addEventListener('load', requestListner) shapShiftReq.open(method, `https://shapeshift.io/${query}/${options.pair ? options.pair : ''}`, true) if (options.method === 'POST') { - var jsonObj = JSON.stringify(options.data) + const jsonObj = JSON.stringify(options.data) shapShiftReq.setRequestHeader('Content-Type', 'application/json') return shapShiftReq.send(jsonObj) } else { diff --git a/ui/index.js b/ui/index.js index 3360bf077..6f7a43963 100644 --- a/ui/index.js +++ b/ui/index.js @@ -13,7 +13,7 @@ module.exports = launchMetamaskUi log.setLevel(global.METAMASK_DEBUG ? 'debug' : 'warn') function launchMetamaskUi (opts, cb) { - var {backgroundConnection} = opts + const {backgroundConnection} = opts actions._setBackgroundConnection(backgroundConnection) // check if we are unlocked first backgroundConnection.getState(function (err, metamaskState) { diff --git a/ui/lib/icon-factory.js b/ui/lib/icon-factory.js index 2ea943297..cbaa496cd 100644 --- a/ui/lib/icon-factory.js +++ b/ui/lib/icon-factory.js @@ -1,4 +1,4 @@ -var iconFactory +let iconFactory const isValidAddress = require('ethereumjs-util').isValidAddress const { checksumAddress } = require('../app/helpers/utils/util') const contractMap = require('eth-contract-metadata') @@ -26,18 +26,18 @@ IconFactory.prototype.iconForAddress = function (address, diameter) { // returns svg dom element IconFactory.prototype.generateIdenticonSvg = function (address, diameter) { - var cacheId = `${address}:${diameter}` + const cacheId = `${address}:${diameter}` // check cache, lazily generate and populate cache - var identicon = this.cache[cacheId] || (this.cache[cacheId] = this.generateNewIdenticon(address, diameter)) + const identicon = this.cache[cacheId] || (this.cache[cacheId] = this.generateNewIdenticon(address, diameter)) // create a clean copy so you can modify it - var cleanCopy = identicon.cloneNode(true) + const cleanCopy = identicon.cloneNode(true) return cleanCopy } // creates a new identicon IconFactory.prototype.generateNewIdenticon = function (address, diameter) { - var numericRepresentation = jsNumberForAddress(address) - var identicon = this.jazzicon(diameter, numericRepresentation) + const numericRepresentation = jsNumberForAddress(address) + const identicon = this.jazzicon(diameter, numericRepresentation) return identicon } @@ -58,8 +58,8 @@ function imageElFor (address) { } function jsNumberForAddress (address) { - var addr = address.slice(2, 10) - var seed = parseInt(addr, 16) + const addr = address.slice(2, 10) + const seed = parseInt(addr, 16) return seed } diff --git a/ui/lib/persistent-form.js b/ui/lib/persistent-form.js index d4dc20b03..112e4415b 100644 --- a/ui/lib/persistent-form.js +++ b/ui/lib/persistent-form.js @@ -15,7 +15,7 @@ PersistentForm.prototype.componentDidMount = function () { const fields = document.querySelectorAll('[data-persistent-formid]') const store = this.getPersistentStore() - for (var i = 0; i < fields.length; i++) { + for (let i = 0; i < fields.length; i++) { const field = fields[i] const key = field.getAttribute('data-persistent-formid') const cached = store[key] @@ -52,7 +52,7 @@ PersistentForm.prototype.persistentFieldDidUpdate = function (event) { PersistentForm.prototype.componentWillUnmount = function () { const fields = document.querySelectorAll('[data-persistent-formid]') - for (var i = 0; i < fields.length; i++) { + for (let i = 0; i < fields.length; i++) { const field = fields[i] field.removeEventListener(eventName, this.persistentFieldDidUpdate.bind(this)) } From 2c33ad3eb48bdb367784a3edfff1dbc553465471 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 3 Dec 2019 12:00:03 -0330 Subject: [PATCH 005/689] Enable react/no-unused-state rule for ESLint (#7609) * eslint: Enable react/no-unused-state rule * Fix unused state issues * Remove now unused validFileImport localized message --- .eslintrc | 1 + app/_locales/am/messages.json | 3 --- app/_locales/ar/messages.json | 3 --- app/_locales/bg/messages.json | 3 --- app/_locales/bn/messages.json | 3 --- app/_locales/ca/messages.json | 3 --- app/_locales/cs/messages.json | 3 --- app/_locales/da/messages.json | 3 --- app/_locales/de/messages.json | 3 --- app/_locales/el/messages.json | 3 --- app/_locales/en/messages.json | 3 --- app/_locales/es/messages.json | 3 --- app/_locales/es_419/messages.json | 3 --- app/_locales/et/messages.json | 3 --- app/_locales/fa/messages.json | 3 --- app/_locales/fi/messages.json | 3 --- app/_locales/fil/messages.json | 3 --- app/_locales/fr/messages.json | 3 --- app/_locales/he/messages.json | 3 --- app/_locales/hi/messages.json | 3 --- app/_locales/hn/messages.json | 3 --- app/_locales/hr/messages.json | 3 --- app/_locales/ht/messages.json | 3 --- app/_locales/hu/messages.json | 3 --- app/_locales/id/messages.json | 3 --- app/_locales/it/messages.json | 3 --- app/_locales/kn/messages.json | 3 --- app/_locales/ko/messages.json | 3 --- app/_locales/lt/messages.json | 3 --- app/_locales/lv/messages.json | 3 --- app/_locales/ms/messages.json | 3 --- app/_locales/nl/messages.json | 3 --- app/_locales/no/messages.json | 3 --- app/_locales/pl/messages.json | 3 --- app/_locales/pt/messages.json | 3 --- app/_locales/pt_BR/messages.json | 3 --- app/_locales/ro/messages.json | 3 --- app/_locales/ru/messages.json | 3 --- app/_locales/sk/messages.json | 3 --- app/_locales/sl/messages.json | 3 --- app/_locales/sr/messages.json | 3 --- app/_locales/sv/messages.json | 3 --- app/_locales/sw/messages.json | 3 --- app/_locales/ta/messages.json | 3 --- app/_locales/th/messages.json | 3 --- app/_locales/tr/messages.json | 3 --- app/_locales/uk/messages.json | 3 --- app/_locales/zh_CN/messages.json | 3 --- app/_locales/zh_TW/messages.json | 3 --- ...transaction-list-item-details.component.js | 1 - .../sender-to-recipient.component.js | 3 --- ui/app/pages/add-token/add-token.component.js | 6 +---- .../create-account/import-account/json.js | 24 ++++++------------- .../add-recipient/add-recipient.component.js | 1 - .../add-recipient/ens-input.component.js | 5 ++-- .../add-contact/add-contact.component.js | 2 +- 56 files changed, 12 insertions(+), 175 deletions(-) diff --git a/.eslintrc b/.eslintrc index b8a5c4094..f77127da8 100644 --- a/.eslintrc +++ b/.eslintrc @@ -150,6 +150,7 @@ "operator-linebreak": [2, "after", { "overrides": { "?": "ignore", ":": "ignore" } }], "padded-blocks": "off", "quotes": [2, "single", {"avoidEscape": true, "allowTemplateLiterals": true}], + "react/no-unused-state": 2, "react/jsx-boolean-value": 2, "react/jsx-curly-brace-presence": [2, { "props": "never", "children": "never" }], "react/jsx-equals-spacing": 2, diff --git a/app/_locales/am/messages.json b/app/_locales/am/messages.json index 70da475f4..bbb076896 100644 --- a/app/_locales/am/messages.json +++ b/app/_locales/am/messages.json @@ -1332,9 +1332,6 @@ "userName": { "message": "የተጣቃሚ ስም" }, - "validFileImport": { - "message": "የሚያስመጡትን ትክክለኛ ፋይል መምረጥ አለብዎ፡" - }, "viewAccount": { "message": "መለያን ይመልከቱ" }, diff --git a/app/_locales/ar/messages.json b/app/_locales/ar/messages.json index f9bceb60d..2a9451d61 100644 --- a/app/_locales/ar/messages.json +++ b/app/_locales/ar/messages.json @@ -1328,9 +1328,6 @@ "userName": { "message": "اسم المستخدم" }, - "validFileImport": { - "message": "يجب عليك تحديد ملف صالح للاستيراد." - }, "viewAccount": { "message": "عرض حساب" }, diff --git a/app/_locales/bg/messages.json b/app/_locales/bg/messages.json index c029ceb4b..bd66c78c7 100644 --- a/app/_locales/bg/messages.json +++ b/app/_locales/bg/messages.json @@ -1331,9 +1331,6 @@ "userName": { "message": "Потребителско име" }, - "validFileImport": { - "message": "Трябва да изберете валиден файл, който да импортирате." - }, "viewAccount": { "message": "Преглед на профила" }, diff --git a/app/_locales/bn/messages.json b/app/_locales/bn/messages.json index ee2024115..7580e8e53 100644 --- a/app/_locales/bn/messages.json +++ b/app/_locales/bn/messages.json @@ -1335,9 +1335,6 @@ "userName": { "message": "ইউজারনেম" }, - "validFileImport": { - "message": "আমদানি করার জন্য আপনাকে অবশ্যই একটি বৈধ ফাইল নির্বাচন করতে হবে।" - }, "viewAccount": { "message": "আ্যাকাউন্ট দেখুন" }, diff --git a/app/_locales/ca/messages.json b/app/_locales/ca/messages.json index 7b8bdf896..07ec4c914 100644 --- a/app/_locales/ca/messages.json +++ b/app/_locales/ca/messages.json @@ -1304,9 +1304,6 @@ "userName": { "message": "Nom d'usuari" }, - "validFileImport": { - "message": "Has de seleccionar un arxiu vàlid per a importar." - }, "viewAccount": { "message": "Mostra el compte" }, diff --git a/app/_locales/cs/messages.json b/app/_locales/cs/messages.json index 72c4a7bce..452e5fb5e 100644 --- a/app/_locales/cs/messages.json +++ b/app/_locales/cs/messages.json @@ -514,9 +514,6 @@ "usedByClients": { "message": "Používána různými klienty" }, - "validFileImport": { - "message": "Musíte vybrat validní soubor k importu." - }, "viewAccount": { "message": "Zobrazit účet" }, diff --git a/app/_locales/da/messages.json b/app/_locales/da/messages.json index 9d68e86cf..d47cc3046 100644 --- a/app/_locales/da/messages.json +++ b/app/_locales/da/messages.json @@ -1301,9 +1301,6 @@ "userName": { "message": "Brugernavn" }, - "validFileImport": { - "message": "Du skal vælge en gyldig fil at importere." - }, "viewAccount": { "message": "Vis konto" }, diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index 1f7409ee2..5ea773ba3 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -1292,9 +1292,6 @@ "userName": { "message": "Nutzername" }, - "validFileImport": { - "message": "Du musst eine gültige Datei für den Import auswählen." - }, "viewAccount": { "message": " Account einsehen" }, diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index 44fa55db0..9d6725632 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -1329,9 +1329,6 @@ "userName": { "message": "Όνομα χρήστη" }, - "validFileImport": { - "message": "Πρέπει να επιλέξετε έναν έγκυρο φάκελο για εισαγωγή." - }, "viewAccount": { "message": "Προβολή λογαριασμού" }, diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index f85b64a02..2afe8e0c3 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1472,9 +1472,6 @@ "userName": { "message": "Username" }, - "validFileImport": { - "message": "You must select a valid file to import." - }, "viewAccount": { "message": "View Account" }, diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index 79d508a07..5aeb4ebe0 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -1076,9 +1076,6 @@ "usedByClients": { "message": "Utilizado por una variedad de clientes diferentes" }, - "validFileImport": { - "message": "Debes selecionar un archivo valido para importar" - }, "viewAccount": { "message": "Mirar cuenta" }, diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index 39d45ddaf..e75b4c27b 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -1314,9 +1314,6 @@ "userName": { "message": "Nombre de usuario" }, - "validFileImport": { - "message": "Selecciona un archivo válido para importar." - }, "viewAccount": { "message": "Ver cuenta" }, diff --git a/app/_locales/et/messages.json b/app/_locales/et/messages.json index 63c7ca53e..3b5f4ced8 100644 --- a/app/_locales/et/messages.json +++ b/app/_locales/et/messages.json @@ -1325,9 +1325,6 @@ "userName": { "message": "Kasutajanimi" }, - "validFileImport": { - "message": "Peate valima importimiseks sobiva faili." - }, "viewAccount": { "message": "Kuva konto" }, diff --git a/app/_locales/fa/messages.json b/app/_locales/fa/messages.json index 1e93ec772..6d9741344 100644 --- a/app/_locales/fa/messages.json +++ b/app/_locales/fa/messages.json @@ -1335,9 +1335,6 @@ "userName": { "message": "نام کاربری" }, - "validFileImport": { - "message": "شما باید یک فایل معتبر را جهت وارد سازی انتخاب کنید." - }, "viewAccount": { "message": "مشاهده حساب" }, diff --git a/app/_locales/fi/messages.json b/app/_locales/fi/messages.json index e2d8a59c5..352600b26 100644 --- a/app/_locales/fi/messages.json +++ b/app/_locales/fi/messages.json @@ -1332,9 +1332,6 @@ "userName": { "message": "Käyttäjätunnus" }, - "validFileImport": { - "message": "Valittava tuotavaksi kelpaava tiedosto." - }, "viewAccount": { "message": "Näytä tili" }, diff --git a/app/_locales/fil/messages.json b/app/_locales/fil/messages.json index 2734fecc3..8c453bca5 100644 --- a/app/_locales/fil/messages.json +++ b/app/_locales/fil/messages.json @@ -1223,9 +1223,6 @@ "usedByClients": { "message": "Ginagamit ng iba't ibang client" }, - "validFileImport": { - "message": "Dapat kang pumili ng valid na file na ii-import." - }, "viewAccount": { "message": "Tingnan ang Account" }, diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index 98925ad69..ddcddb6be 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -1296,9 +1296,6 @@ "userName": { "message": "Nom d'utilisateur" }, - "validFileImport": { - "message": "Vous devez selectionner un fichier valide à importer." - }, "viewAccount": { "message": "Afficher le compte" }, diff --git a/app/_locales/he/messages.json b/app/_locales/he/messages.json index 9c9966edc..62e69e1d5 100644 --- a/app/_locales/he/messages.json +++ b/app/_locales/he/messages.json @@ -1329,9 +1329,6 @@ "userName": { "message": "שם משתמש" }, - "validFileImport": { - "message": "עליך לבחור קובץ חוקי לייבוא." - }, "viewAccount": { "message": "הצג חשבון" }, diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index 25e8014ff..92fa40af6 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -1329,9 +1329,6 @@ "userName": { "message": "उपयोगकर्ता नाम" }, - "validFileImport": { - "message": "आयात करने के लिए आपको एक मान्य फ़ाइल को चुनना होगा।" - }, "viewAccount": { "message": "खाता देखें" }, diff --git a/app/_locales/hn/messages.json b/app/_locales/hn/messages.json index e15b244ca..1dd4fd117 100644 --- a/app/_locales/hn/messages.json +++ b/app/_locales/hn/messages.json @@ -476,9 +476,6 @@ "usedByClients": { "message": "विभिन्न क्लाइंट्स द्वारा उपयोग किया जाता है" }, - "validFileImport": { - "message": "आयात करने के लिए आपको एक वैध फ़ाइल चुननी होगी।" - }, "viewAccount": { "message": "खाता देखें" }, diff --git a/app/_locales/hr/messages.json b/app/_locales/hr/messages.json index 318713b7d..2e224f36f 100644 --- a/app/_locales/hr/messages.json +++ b/app/_locales/hr/messages.json @@ -1325,9 +1325,6 @@ "userName": { "message": "Korisničko ime" }, - "validFileImport": { - "message": "Morate odabrati valjanu datoteku za uvoz." - }, "viewAccount": { "message": "Prikaz računa" }, diff --git a/app/_locales/ht/messages.json b/app/_locales/ht/messages.json index d3a9dd4ba..472409017 100644 --- a/app/_locales/ht/messages.json +++ b/app/_locales/ht/messages.json @@ -836,9 +836,6 @@ "usedByClients": { "message": "Itilize pa yon varyete de kliyan diferan" }, - "validFileImport": { - "message": "Ou dwe chwazi yon dosye ki valab pou enpòte." - }, "viewAccount": { "message": "Wè Kont" }, diff --git a/app/_locales/hu/messages.json b/app/_locales/hu/messages.json index 870972e5b..f1554299b 100644 --- a/app/_locales/hu/messages.json +++ b/app/_locales/hu/messages.json @@ -1325,9 +1325,6 @@ "userName": { "message": "Felhasználónév" }, - "validFileImport": { - "message": "Ki kell választanod egy érvényes fájlt az importáláshoz." - }, "viewAccount": { "message": "Fiók megtekintése" }, diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index 42d847289..eaddf42eb 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -1304,9 +1304,6 @@ "userName": { "message": "Nama Pengguna" }, - "validFileImport": { - "message": "Anda harus memilih berkas yang sah untuk diimpor." - }, "viewAccount": { "message": "Lihat Akun" }, diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index 83b637859..e51b5a477 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -1295,9 +1295,6 @@ "userName": { "message": "Nome utente" }, - "validFileImport": { - "message": "Devi selezionare un file valido da importare." - }, "viewAccount": { "message": "Vedi Account" }, diff --git a/app/_locales/kn/messages.json b/app/_locales/kn/messages.json index 480abe20d..e4c8b38fe 100644 --- a/app/_locales/kn/messages.json +++ b/app/_locales/kn/messages.json @@ -1335,9 +1335,6 @@ "userName": { "message": "ಬಳಕೆದಾರಹೆಸರು" }, - "validFileImport": { - "message": "ನೀವು ಆಮದು ಮಾಡಲು ಮಾನ್ಯ ಫೈಲ್ ಅನ್ನು ಆಯ್ಕೆಮಾಡಬೇಕು." - }, "viewAccount": { "message": "ಖಾತೆಯನ್ನು ವೀಕ್ಷಿಸಿ" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index 47af1dbff..39c68a85e 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -1326,9 +1326,6 @@ "userName": { "message": "사용자이름" }, - "validFileImport": { - "message": "가져오기 위해 유효한 파일을 선택해야 합니다." - }, "viewAccount": { "message": "계정 보기" }, diff --git a/app/_locales/lt/messages.json b/app/_locales/lt/messages.json index 51113ffe4..961eedc91 100644 --- a/app/_locales/lt/messages.json +++ b/app/_locales/lt/messages.json @@ -1335,9 +1335,6 @@ "userName": { "message": "Vartotojo vardas" }, - "validFileImport": { - "message": "Turite pasirinkti galiojantį failą, kurį pageidaujate importuoti." - }, "viewAccount": { "message": "Žiūrėti paskyrą" }, diff --git a/app/_locales/lv/messages.json b/app/_locales/lv/messages.json index db678240b..18d80c900 100644 --- a/app/_locales/lv/messages.json +++ b/app/_locales/lv/messages.json @@ -1331,9 +1331,6 @@ "userName": { "message": "Lietotājvārds" }, - "validFileImport": { - "message": "Importēšanai jāatlasa derīga datne." - }, "viewAccount": { "message": "Skatīt kontu" }, diff --git a/app/_locales/ms/messages.json b/app/_locales/ms/messages.json index ed1daeb3d..e573eabc4 100644 --- a/app/_locales/ms/messages.json +++ b/app/_locales/ms/messages.json @@ -1303,9 +1303,6 @@ "userName": { "message": "Nama pengguna" }, - "validFileImport": { - "message": "Anda mesti pilih fail yang sah untuk diimport." - }, "viewAccount": { "message": "Paparkan Akaun" }, diff --git a/app/_locales/nl/messages.json b/app/_locales/nl/messages.json index b026ec93a..265542aed 100644 --- a/app/_locales/nl/messages.json +++ b/app/_locales/nl/messages.json @@ -463,9 +463,6 @@ "usedByClients": { "message": "Gebruikt door verschillende klanten" }, - "validFileImport": { - "message": "U moet een geldig bestand selecteren om te importeren." - }, "viewAccount": { "message": "Bekijk account" }, diff --git a/app/_locales/no/messages.json b/app/_locales/no/messages.json index 1f9368421..b0bf0d6de 100644 --- a/app/_locales/no/messages.json +++ b/app/_locales/no/messages.json @@ -1307,9 +1307,6 @@ "userName": { "message": "Brukernavn" }, - "validFileImport": { - "message": "Du må velge en gyldig fil å importere" - }, "viewAccount": { "message": "Se konto" }, diff --git a/app/_locales/pl/messages.json b/app/_locales/pl/messages.json index ea9bac563..3fa36bd39 100644 --- a/app/_locales/pl/messages.json +++ b/app/_locales/pl/messages.json @@ -1320,9 +1320,6 @@ "userName": { "message": "Nazwa użytkownika" }, - "validFileImport": { - "message": "Należy wybrać prawidłowy plik do zaimportowania." - }, "viewAccount": { "message": "Zobacz konto" }, diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index 0c8949603..519369349 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -473,9 +473,6 @@ "usedByClients": { "message": "Utilizado por vários tipos de clientes" }, - "validFileImport": { - "message": "Deve selecionar um ficheiro válido para importar." - }, "viewAccount": { "message": "Ver Conta" }, diff --git a/app/_locales/pt_BR/messages.json b/app/_locales/pt_BR/messages.json index 6f496b57c..44ed790ef 100644 --- a/app/_locales/pt_BR/messages.json +++ b/app/_locales/pt_BR/messages.json @@ -1314,9 +1314,6 @@ "userName": { "message": "Nome de usuário" }, - "validFileImport": { - "message": "Você precisa selecionar um arquivo válido para importar." - }, "viewAccount": { "message": "Visualizar conta" }, diff --git a/app/_locales/ro/messages.json b/app/_locales/ro/messages.json index a5fe91697..f891a40df 100644 --- a/app/_locales/ro/messages.json +++ b/app/_locales/ro/messages.json @@ -1316,9 +1316,6 @@ "userName": { "message": "Nume utilizator" }, - "validFileImport": { - "message": "Trebuie să selectați un fișier valabil pentru importare." - }, "viewAccount": { "message": "Afișați contul" }, diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index ac6aa65e2..660b2799e 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -527,9 +527,6 @@ "usedByClients": { "message": "Используется различными клиентами" }, - "validFileImport": { - "message": "Вам нужно выбрать правильный файл для импорта." - }, "viewAccount": { "message": "Посмотреть счет" }, diff --git a/app/_locales/sk/messages.json b/app/_locales/sk/messages.json index 2de10f9ab..5238e076d 100644 --- a/app/_locales/sk/messages.json +++ b/app/_locales/sk/messages.json @@ -1289,9 +1289,6 @@ "userName": { "message": "Meno používateľa" }, - "validFileImport": { - "message": "Musíte vybrat validní soubor k importu." - }, "viewAccount": { "message": "Zobrazit účet" }, diff --git a/app/_locales/sl/messages.json b/app/_locales/sl/messages.json index 1e1884a26..8530dd43d 100644 --- a/app/_locales/sl/messages.json +++ b/app/_locales/sl/messages.json @@ -1317,9 +1317,6 @@ "userName": { "message": "Uporabniško ime" }, - "validFileImport": { - "message": "Za uvoz morate izbrati pravilno datoteko." - }, "viewAccount": { "message": "Poglej račun" }, diff --git a/app/_locales/sr/messages.json b/app/_locales/sr/messages.json index 58d31c183..d3fd1cbd4 100644 --- a/app/_locales/sr/messages.json +++ b/app/_locales/sr/messages.json @@ -1320,9 +1320,6 @@ "userName": { "message": "Корисничко име" }, - "validFileImport": { - "message": "Morate odabrati važeću datoteku da biste ih uvezli." - }, "viewAccount": { "message": "Прикажи налог" }, diff --git a/app/_locales/sv/messages.json b/app/_locales/sv/messages.json index e808703f1..1b7ecc06e 100644 --- a/app/_locales/sv/messages.json +++ b/app/_locales/sv/messages.json @@ -1310,9 +1310,6 @@ "userName": { "message": "Användarnamn" }, - "validFileImport": { - "message": "Du måste välja en giltig fil för att importera." - }, "viewAccount": { "message": "Visa konto" }, diff --git a/app/_locales/sw/messages.json b/app/_locales/sw/messages.json index ad5878733..c8c2e36ee 100644 --- a/app/_locales/sw/messages.json +++ b/app/_locales/sw/messages.json @@ -1313,9 +1313,6 @@ "userName": { "message": "Jina la mtumiaji" }, - "validFileImport": { - "message": "Ni lazima uchague faili halali ili uhamishe." - }, "viewAccount": { "message": "Angalia Akaunti" }, diff --git a/app/_locales/ta/messages.json b/app/_locales/ta/messages.json index ba173def5..698349c24 100644 --- a/app/_locales/ta/messages.json +++ b/app/_locales/ta/messages.json @@ -539,9 +539,6 @@ "usedByClients": { "message": "பல்வேறு வாடிக்கையாளர்கள் பல்வேறு பயன்படுத்திய" }, - "validFileImport": { - "message": "இறக்குமதி செய்ய சரியான கோப்பு தேர்ந்தெடுக்க வேண்டும்." - }, "viewAccount": { "message": "கணக்கைப் பார்" }, diff --git a/app/_locales/th/messages.json b/app/_locales/th/messages.json index c32044bb1..f07f3421e 100644 --- a/app/_locales/th/messages.json +++ b/app/_locales/th/messages.json @@ -641,9 +641,6 @@ "usedByClients": { "message": "ถูกใช้งานโดยหลายไคลเอนท์" }, - "validFileImport": { - "message": "คุณต้องเลือกไฟล์ที่ถูกต้องเพื่อนำเข้า" - }, "viewAccount": { "message": "ดูบัญชี" }, diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index dbfe3cf08..c6027a42d 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -536,9 +536,6 @@ "usedByClients": { "message": "Farklı istemciler tarafından kullanılmakta" }, - "validFileImport": { - "message": "Almak için geçerli bir dosya seçmelisiniz" - }, "viewAccount": { "message": "Hesabı İncele" }, diff --git a/app/_locales/uk/messages.json b/app/_locales/uk/messages.json index a4252cb3e..49d04a096 100644 --- a/app/_locales/uk/messages.json +++ b/app/_locales/uk/messages.json @@ -1335,9 +1335,6 @@ "userName": { "message": "Ім’я користувача" }, - "validFileImport": { - "message": "Потрібно вибрати дійсний файл для імпорту." - }, "viewAccount": { "message": "Переглянути обліковий запис" }, diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index c0b10a973..cade6ee71 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -1314,9 +1314,6 @@ "userName": { "message": "用户名" }, - "validFileImport": { - "message": "您必须选择一个有效的文件进行导入." - }, "viewAccount": { "message": "查看账户" }, diff --git a/app/_locales/zh_TW/messages.json b/app/_locales/zh_TW/messages.json index 5a0a2e3ea..3d0e299a6 100644 --- a/app/_locales/zh_TW/messages.json +++ b/app/_locales/zh_TW/messages.json @@ -1308,9 +1308,6 @@ "userName": { "message": "使用者名稱" }, - "validFileImport": { - "message": "您必須選擇一個合法的檔案來匯入." - }, "viewAccount": { "message": "查看帳戶" }, diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js index f27c74970..554e99a5b 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js +++ b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js @@ -39,7 +39,6 @@ export default class TransactionListItemDetails extends PureComponent { state = { justCopied: false, - cancelDisabled: false, } handleEtherscanClick = () => { diff --git a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js index 3102f17e3..01ad167ca 100644 --- a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js +++ b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js @@ -39,7 +39,6 @@ export default class SenderToRecipient extends PureComponent { state = { senderAddressCopied: false, - recipientAddressCopied: false, } renderSenderIdenticon () { @@ -112,7 +111,6 @@ export default class SenderToRecipient extends PureComponent {
{ - this.setState({ recipientAddressCopied: true }) copyToClipboard(checksummedRecipientAddress) if (onRecipientClick) { onRecipientClick() @@ -136,7 +134,6 @@ export default class SenderToRecipient extends PureComponent { } wrapperClassName="sender-to-recipient__tooltip-wrapper" containerClassName="sender-to-recipient__tooltip-container" - onHidden={() => this.setState({ recipientAddressCopied: false })} >
{ addressOnly ? `${t('to')}: ` : '' } diff --git a/ui/app/pages/add-token/add-token.component.js b/ui/app/pages/add-token/add-token.component.js index 40c1ff7fd..0db281b29 100644 --- a/ui/app/pages/add-token/add-token.component.js +++ b/ui/app/pages/add-token/add-token.component.js @@ -11,8 +11,6 @@ import PageContainer from '../../components/ui/page-container' import { Tabs, Tab } from '../../components/ui/tabs' const emptyAddr = '0x0000000000000000000000000000000000000000' -const SEARCH_TAB = 'SEARCH' -const CUSTOM_TOKEN_TAB = 'CUSTOM_TOKEN' class AddToken extends Component { static contextTypes = { @@ -42,7 +40,6 @@ class AddToken extends Component { customSymbolError: null, customDecimalsError: null, autoFilled: false, - displayedTab: SEARCH_TAB, forceEditSymbol: false, } } @@ -73,8 +70,7 @@ class AddToken extends Component { decimals: customDecimals = 0, } = customToken - const displayedTab = Object.keys(selectedTokens).length > 0 ? SEARCH_TAB : CUSTOM_TOKEN_TAB - this.setState({ selectedTokens, customAddress, customSymbol, customDecimals, displayedTab }) + this.setState({ selectedTokens, customAddress, customSymbol, customDecimals }) } } diff --git a/ui/app/pages/create-account/import-account/json.js b/ui/app/pages/create-account/import-account/json.js index c9ff8d926..7fd27264d 100644 --- a/ui/app/pages/create-account/import-account/json.js +++ b/ui/app/pages/create-account/import-account/json.js @@ -12,13 +12,8 @@ import Button from '../../../components/ui/button' const HELP_LINK = 'https://metamask.zendesk.com/hc/en-us/articles/360015489351-Importing-Accounts' class JsonImportSubview extends Component { - constructor (props) { - super(props) - - this.state = { - file: null, - fileContents: '', - } + state = { + fileContents: '', } render () { @@ -73,8 +68,10 @@ class JsonImportSubview extends Component { ) } - onLoad (event, file) { - this.setState({file: file, fileContents: event.target.result}) + onLoad (event) { + this.setState({ + fileContents: event.target.result, + }) } createKeyringOnEnter (event) { @@ -86,14 +83,7 @@ class JsonImportSubview extends Component { createNewKeychain () { const { firstAddress, displayWarning, importNewJsonAccount, setSelectedAddress, history } = this.props - const state = this.state - - if (!state) { - const message = this.context.t('validFileImport') - return displayWarning(message) - } - - const { fileContents } = state + const { fileContents } = this.state if (!fileContents) { const message = this.context.t('needImportFile') diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js b/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js index e5edbc08d..bad912c0a 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js +++ b/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js @@ -64,7 +64,6 @@ export default class AddRecipient extends Component { state = { isShowingTransfer: false, - isShowingAllRecent: false, } selectRecipient = (to, nickname = '') => { diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js index 5294388ac..a4b5c8810 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js +++ b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js @@ -37,10 +37,9 @@ export default class EnsInput extends Component { } state = { - recipient: null, input: '', toError: null, - toWarning: null, + ensResolution: undefined, } componentDidMount () { @@ -234,7 +233,7 @@ export default class EnsInput extends Component { } ensIconContents () { - const { loadingEns, ensFailure, ensResolution, toError } = this.state || { ensResolution: ZERO_ADDRESS } + const { loadingEns, ensFailure, ensResolution, toError } = this.state if (toError) { return diff --git a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js index 9e3bc791b..91489be1c 100644 --- a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js +++ b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js @@ -23,7 +23,7 @@ export default class AddContact extends PureComponent { } state = { - nickname: '', + newName: '', ethAddress: '', ensAddress: '', error: '', From 2e69f3233e1891d3633261bfcbe383d862855ed1 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 3 Dec 2019 13:05:44 -0330 Subject: [PATCH 006/689] eslint: Enable more react/jsx-* rules (#7592) --- .eslintrc | 19 +++ development/mock-dev.js | 2 +- .../account-menu/account-menu.component.js | 16 +-- .../app/app-header/app-header.component.js | 3 +- ...onfirm-page-container-summary.component.js | 8 +- ...confirm-page-container-header.component.js | 54 ++++---- ...irm-page-container-navigation.component.js | 24 ++-- .../confirm-page-container.component.js | 20 +-- .../recipient-group.component.js | 8 +- .../components/network-dropdown-icon.js | 14 ++- .../app/dropdowns/tests/menu.test.js | 10 +- .../dropdowns/tests/network-dropdown.test.js | 2 +- .../advanced-gas-inputs.component.js | 22 ++-- .../advanced-tab-content.component.js | 22 ++-- .../advanced-tab-content-component.test.js | 26 ++-- .../basic-tab-content.component.js | 12 +- .../tests/basic-tab-content-component.test.js | 8 +- .../gas-modal-page-container.component.js | 15 +-- ...gas-modal-page-container-component.test.js | 84 +++++++------ .../gas-price-button-group.component.js | 34 ++--- .../gas-price-button-group-component.test.js | 8 +- .../gas-slider/gas-slider.component.js | 2 +- ui/app/components/app/input-number.js | 3 +- .../loading-network-screen.component.js | 64 +++++----- .../account-details-modal.component.js | 18 +-- .../confirm-remove-account.component.js | 4 +- .../deposit-ether-modal.component.js | 3 +- .../edit-approval-permission.component.js | 40 +++--- .../export-private-key-modal.component.js | 2 +- .../metametrics-opt-in-modal.component.js | 3 +- .../multiple-notifications.component.js | 10 +- .../network-display.component.js | 32 ++--- ...ovider-page-container-content.component.js | 2 +- .../tests/selected-account-component.test.js | 10 +- .../app/sidebars/sidebar.component.js | 16 +-- .../sidebars/tests/sidebars-component.test.js | 14 ++- .../signature-request-original.component.js | 50 ++++---- .../signature-request-header.component.js | 10 +- .../tests/signature-request.test.js | 15 ++- .../app/token-cell/token-cell.component.js | 3 +- ui/app/components/app/token-list.js | 12 +- .../transaction-action.component.test.js | 12 +- .../transaction-breakdown.component.js | 26 ++-- ...transaction-list-item-details.component.js | 20 +-- .../transaction-list-item.component.js | 18 +-- .../token-view-balance.component.test.js | 38 +++--- .../app/wallet-view/wallet-view.component.js | 8 +- .../ui/button-group/button-group.stories.js | 8 +- .../tests/button-group-component.test.js | 16 ++- ui/app/components/ui/button/button.stories.js | 28 ++--- .../tests/currency-display.component.test.js | 22 ++-- .../ui/eth-balance/eth-balance.component.js | 44 ++++--- .../tests/hex-to-decimal.component.test.js | 20 +-- .../tests/identicon.component.test.js | 2 +- .../page-container-footer.component.js | 18 +-- .../page-container-footer.component.test.js | 18 +-- .../page-container-header.component.js | 26 ++-- .../page-container-header.component.test.js | 20 +-- .../sender-to-recipient.component.js | 4 +- .../ui/text-field/text-field.stories.js | 28 ++--- .../token-list/token-list.component.js | 3 +- .../confirm-approve-content.component.js | 57 +++++---- .../confirm-approve.component.js | 40 +++--- .../confirm-transaction-base.component.js | 68 +++++----- .../connect-hardware/connect-screen.js | 3 +- .../create-account.component.js | 18 +-- .../create-account/import-account/index.js | 3 +- .../create-account/new-account.component.js | 11 +- .../import-with-seed-phrase.component.js | 3 +- .../new-account/new-account.component.js | 3 +- .../end-of-flow/end-of-flow.component.js | 9 +- .../metametrics-opt-in.component.js | 3 +- .../reveal-seed-phrase.component.js | 21 ++-- ui/app/pages/home/home.component.js | 90 +++++++------- .../account-list-item.component.js | 72 ++++++----- .../tests/account-list-item-component.test.js | 24 ++-- .../add-recipient/add-recipient.component.js | 2 +- .../tests/add-recipient-component.test.js | 36 +++--- .../tests/amount-max-button-component.test.js | 20 +-- .../tests/send-amount-row-component.test.js | 36 +++--- .../send-asset-row.component.js | 3 +- .../send-dropdown-list.component.js | 40 +++--- .../send-dropdown-list-component.test.js | 24 ++-- .../gas-fee-display.component.js | 16 ++- .../test/gas-fee-display.component.test.js | 18 +-- .../send-gas-row/send-gas-row.component.js | 117 ++++++++++-------- .../tests/send-gas-row-component.test.js | 30 ++--- .../send-row-error-message-component.test.js | 10 +- .../tests/send-row-wrapper-component.test.js | 52 ++++---- .../tests/send-footer-component.test.js | 90 +++++++------- .../tests/send-header-component.test.js | 12 +- .../pages/send/tests/send-component.test.js | 56 +++++---- .../add-contact/add-contact.component.js | 12 +- .../contact-list-tab.component.js | 49 +++++--- .../edit-contact/edit-contact.component.js | 2 +- .../networks-tab/networks-tab.component.js | 34 ++--- ui/app/pages/settings/settings.component.js | 20 +-- 97 files changed, 1244 insertions(+), 963 deletions(-) diff --git a/.eslintrc b/.eslintrc index f77127da8..74b30dcbe 100644 --- a/.eslintrc +++ b/.eslintrc @@ -156,6 +156,25 @@ "react/jsx-equals-spacing": 2, "react/no-deprecated": 0, "react/default-props-match-prop-types": 2, + "react/jsx-closing-tag-location": 2, + "react/jsx-no-duplicate-props": 2, + "react/jsx-closing-bracket-location": 2, + "react/jsx-first-prop-new-line": 2, + "react/jsx-max-props-per-line": [2, { "maximum": 1, "when": "multiline"} ], + "react/jsx-tag-spacing": [2, { + "closingSlash": "never", + "beforeSelfClosing": "always", + "afterOpening": "never" + }], + "react/jsx-wrap-multilines": [2, { + "declaration": "parens-new-line", + "assignment": "parens-new-line", + "return": "parens-new-line", + "arrow": "parens-new-line", + "condition": "parens-new-line", + "logical": "parens-new-line", + "prop": "parens-new-line" + }], "semi": [2, "never"], "semi-spacing": [2, { "before": false, "after": true }], "space-before-blocks": [2, "always"], diff --git a/development/mock-dev.js b/development/mock-dev.js index 16fdd0273..51a8cde46 100644 --- a/development/mock-dev.js +++ b/development/mock-dev.js @@ -135,7 +135,7 @@ function startApp () { margin: '20px', }} > - +
, container, diff --git a/ui/app/components/app/account-menu/account-menu.component.js b/ui/app/components/app/account-menu/account-menu.component.js index 7be2bc5dd..c13163a81 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/app/components/app/account-menu/account-menu.component.js @@ -253,12 +253,12 @@ export default class AccountMenu extends PureComponent { }) history.push(NEW_ACCOUNT_ROUTE) }} - icon={ + icon={( - } + )} text={t('createAccount')} /> - } + )} text={t('importAccount')} /> - } + )} text={t('connectHardwareWallet')} /> @@ -328,12 +328,12 @@ export default class AccountMenu extends PureComponent { }, }) }} - icon={ + icon={( - } + )} text={t('settings')} /> diff --git a/ui/app/components/app/app-header/app-header.component.js b/ui/app/components/app/app-header/app-header.component.js index e1bc0cf24..bd01558c5 100644 --- a/ui/app/components/app/app-header/app-header.component.js +++ b/ui/app/components/app/app-header/app-header.component.js @@ -89,7 +89,8 @@ export default class AppHeader extends PureComponent { return (
+ className={classnames('app-header', { 'app-header--back-drop': isUnlocked })} + >
{
{ - hideSubtitle ||
- { subtitleComponent || subtitle } -
+ hideSubtitle || ( +
+ { subtitleComponent || subtitle } +
+ ) } ) diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js index 898d59068..4b91b4ddb 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js @@ -34,36 +34,40 @@ export default class ConfirmPageContainerHeader extends Component { return (
{ !showAccountInHeader - ?
- - onEdit()} + ? ( +
- { this.context.t('edit') } - -
+ + onEdit()} + > + { this.context.t('edit') } + +
+ ) : null } { showAccountInHeader - ?
-
- -
-
- { addressSlicer(accountAddress) } + ? ( +
+
+ +
+
+ { addressSlicer(accountAddress) } +
-
+ ) : null } { !isFullScreen && } diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js index c24d24b17..dd1fd2da4 100755 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js @@ -5,23 +5,28 @@ const ConfirmPageContainerNavigation = props => { const { onNextTx, totalTx, positionOfCurrentTx, nextTxId, prevTxId, showNavigation, firstTx, lastTx, ofText, requestsWaitingText } = props return ( -
-
+ }} + >
onNextTx(firstTx)}> + onClick={() => onNextTx(firstTx)} + >
onNextTx(prevTxId)}> + onClick={() => onNextTx(prevTxId)} + >
@@ -37,15 +42,18 @@ const ConfirmPageContainerNavigation = props => { className="confirm-page-container-navigation__container" style={{ visibility: nextTxId ? 'initial' : 'hidden', - }}> + }} + >
onNextTx(nextTxId)}> + onClick={() => onNextTx(nextTxId)} + >
onNextTx(lastTx)}> + onClick={() => onNextTx(lastTx)} + >
diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container.component.js index 86ce2bff7..9ebae3d95 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container.component.js @@ -133,15 +133,17 @@ export default class ConfirmPageContainer extends Component { > { hideSenderToRecipient ? null - : + : ( + + ) } { diff --git a/ui/app/components/app/contact-list/recipient-group/recipient-group.component.js b/ui/app/components/app/contact-list/recipient-group/recipient-group.component.js index a2248326e..20e2b3494 100644 --- a/ui/app/components/app/contact-list/recipient-group/recipient-group.component.js +++ b/ui/app/components/app/contact-list/recipient-group/recipient-group.component.js @@ -15,9 +15,11 @@ export default function RecipientGroup ({ label, items, onSelect, selectedAddres return (
- {label &&
- {label} -
} + {label && ( +
+ {label} +
+ )} { items.map(({ address, name }) => (
-
+
) } diff --git a/ui/app/components/app/dropdowns/tests/menu.test.js b/ui/app/components/app/dropdowns/tests/menu.test.js index 56cec93a3..b3bc34fa9 100644 --- a/ui/app/components/app/dropdowns/tests/menu.test.js +++ b/ui/app/components/app/dropdowns/tests/menu.test.js @@ -11,7 +11,7 @@ describe('Dropdown Menu Components', () => { beforeEach(() => { wrapper = shallow( - + ) }) @@ -73,9 +73,11 @@ describe('Dropdown Menu Components', () => { const onClickSpy = sinon.spy() beforeEach(() => { - wrapper = shallow() + wrapper = shallow(( + + )) }) it('simulates click', () => { diff --git a/ui/app/components/app/dropdowns/tests/network-dropdown.test.js b/ui/app/components/app/dropdowns/tests/network-dropdown.test.js index 4a81b973f..98cba1d2e 100644 --- a/ui/app/components/app/dropdowns/tests/network-dropdown.test.js +++ b/ui/app/components/app/dropdowns/tests/network-dropdown.test.js @@ -57,7 +57,7 @@ describe('Network Dropdown', () => { beforeEach(() => { wrapper = mountWithRouter( - , + , ) }) diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js b/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js index 7fb5aa6f4..b881db6e5 100644 --- a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js +++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js @@ -119,10 +119,12 @@ export default class AdvancedGasInputs extends Component { value={value} onChange={onChange} /> -
+
onChange({ target: { value: value + 1 } })} @@ -159,21 +161,21 @@ export default class AdvancedGasInputs extends Component { errorText: gasPriceErrorText, errorType: gasPriceErrorType, } = this.gasPriceError({ insufficientBalance, customPriceIsSafe, isSpeedUp, gasPrice }) - const gasPriceErrorComponent = gasPriceErrorType ? + const gasPriceErrorComponent = gasPriceErrorType ? (
{ gasPriceErrorText } -
: - null +
+ ) : null const { errorText: gasLimitErrorText, errorType: gasLimitErrorType, } = this.gasLimitError({ insufficientBalance, gasLimit }) - const gasLimitErrorComponent = gasLimitErrorType ? + const gasLimitErrorComponent = gasLimitErrorType ? (
{ gasLimitErrorText } -
: - null +
+ ) : null return (
diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js index 306dd03a0..19e3aa776 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js @@ -83,17 +83,19 @@ export default class AdvancedTabContent extends Component { />
{ isEthereumNetwork - ?
-
{ t('liveGasPricePredictions') }
- {!gasEstimatesLoading - ? - : - } -
- { t('slower') } - { t('faster') } + ? ( +
+
{ t('liveGasPricePredictions') }
+ {!gasEstimatesLoading + ? + : + } +
+ { t('slower') } + { t('faster') } +
-
+ ) :
{ t('chartOnlyAvailableEth') }
}
diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js index 05075f3ba..16b15df41 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js @@ -18,18 +18,20 @@ describe('AdvancedTabContent Component', function () { let wrapper beforeEach(() => { - wrapper = shallow() + wrapper = shallow(( + + )) }) afterEach(() => { diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js index c804abe3a..94d22ee4a 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js @@ -21,11 +21,13 @@ export default class BasicTabContent extends Component {
{ t('estimatedProcessingTimes') }
{ t('selectAHigherGasFee') }
{!gasPriceButtonGroupProps.loading - ? + ? ( + + ) : }
{ t('acceleratingATransaction') }
diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js index 0989ac677..80fbffe05 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js @@ -38,9 +38,11 @@ describe('BasicTabContent Component', function () { let wrapper beforeEach(() => { - wrapper = shallow() + wrapper = shallow(( + + )) }) describe('render', () => { diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js index f405cb7b9..daf91eae3 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js @@ -160,13 +160,14 @@ export default class GasModalPageContainer extends Component { return ( - {tabsToRender.map(({ name, content }, i) => -
- { content } - { this.renderInfoRows(newTotalFiat, newTotalEth, sendAmount, transactionFee) } -
-
- )} + {tabsToRender.map(({ name, content }, i) => ( + +
+ { content } + { this.renderInfoRows(newTotalFiat, newTotalEth, sendAmount, transactionFee) } +
+
+ ))}
) } diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js index 3e416db49..50efb46f0 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js @@ -63,23 +63,25 @@ describe('GasModalPageContainer Component', function () { let wrapper beforeEach(() => { - wrapper = shallow( 'mockupdateCustomGasPrice'} - updateCustomGasLimit={() => 'mockupdateCustomGasLimit'} - customGasPrice={21} - customGasLimit={54321} - gasPriceButtonGroupProps={mockGasPriceButtonGroupProps} - infoRowProps={mockInfoRowProps} - currentTimeEstimate="1 min 31 sec" - customGasPriceInHex="mockCustomGasPriceInHex" - customGasLimitInHex="mockCustomGasLimitInHex" - insufficientBalance={false} - disableSave={false} - />) + wrapper = shallow(( + 'mockupdateCustomGasPrice'} + updateCustomGasLimit={() => 'mockupdateCustomGasLimit'} + customGasPrice={21} + customGasLimit={54321} + gasPriceButtonGroupProps={mockGasPriceButtonGroupProps} + infoRowProps={mockInfoRowProps} + currentTimeEstimate="1 min 31 sec" + customGasPriceInHex="mockCustomGasPriceInHex" + customGasLimitInHex="mockCustomGasLimitInHex" + insufficientBalance={false} + disableSave={false} + /> + )) }) afterEach(() => { @@ -134,10 +136,12 @@ describe('GasModalPageContainer Component', function () { it('should pass the correct renderTabs property to PageContainer', () => { sinon.stub(GP, 'renderTabs').returns('mockTabs') - const renderTabsWrapperTester = shallow(, { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } }) + const renderTabsWrapperTester = shallow(( + + ), { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } }) const { tabsComponent } = renderTabsWrapperTester.find(PageContainer).props() assert.equal(tabsComponent, 'mockTabs') GasModalPageContainer.prototype.renderTabs.restore() @@ -184,24 +188,26 @@ describe('GasModalPageContainer Component', function () { }) it('should not render the basic tab if hideBasic is true', () => { - wrapper = shallow( 'mockupdateCustomGasPrice'} - updateCustomGasLimit={() => 'mockupdateCustomGasLimit'} - customGasPrice={21} - customGasLimit={54321} - gasPriceButtonGroupProps={mockGasPriceButtonGroupProps} - infoRowProps={mockInfoRowProps} - currentTimeEstimate="1 min 31 sec" - customGasPriceInHex="mockCustomGasPriceInHex" - customGasLimitInHex="mockCustomGasLimitInHex" - insufficientBalance={false} - disableSave={false} - hideBasic - />) + wrapper = shallow(( + 'mockupdateCustomGasPrice'} + updateCustomGasLimit={() => 'mockupdateCustomGasLimit'} + customGasPrice={21} + customGasLimit={54321} + gasPriceButtonGroupProps={mockGasPriceButtonGroupProps} + infoRowProps={mockInfoRowProps} + currentTimeEstimate="1 min 31 sec" + customGasPriceInHex="mockCustomGasPriceInHex" + customGasLimitInHex="mockCustomGasLimitInHex" + insufficientBalance={false} + disableSave={false} + hideBasic + /> + )) const renderTabsResult = wrapper.instance().renderTabs() const renderedTabs = shallow(renderTabsResult) diff --git a/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js b/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js index 0412b3381..b578ff1ed 100644 --- a/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js +++ b/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js @@ -49,13 +49,15 @@ export default class GasPriceButtonGroup extends Component { className, showCheck, }) { - return (
- { gasEstimateType &&
{ this.gasEstimateTypeLabel(gasEstimateType) }
} - { timeEstimate &&
{ timeEstimate }
} - { feeInPrimaryCurrency &&
{ feeInPrimaryCurrency }
} - { feeInSecondaryCurrency &&
{ feeInSecondaryCurrency }
} - { showCheck &&
} -
) + return ( +
+ { gasEstimateType &&
{ this.gasEstimateTypeLabel(gasEstimateType) }
} + { timeEstimate &&
{ timeEstimate }
} + { feeInPrimaryCurrency &&
{ feeInPrimaryCurrency }
} + { feeInSecondaryCurrency &&
{ feeInSecondaryCurrency }
} + { showCheck &&
} +
+ ) } renderButton ({ @@ -88,14 +90,16 @@ export default class GasPriceButtonGroup extends Component { return ( !buttonDataLoading - ? - { gasButtonInfo.map((obj, index) => this.renderButton(obj, buttonPropsAndFlags, index)) } - + ? ( + + { gasButtonInfo.map((obj, index) => this.renderButton(obj, buttonPropsAndFlags, index)) } + + ) :
{ this.context.t('loading') }
) } diff --git a/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js b/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js index 85f53d08e..1d924f850 100644 --- a/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js +++ b/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js @@ -48,9 +48,11 @@ describe('GasPriceButtonGroup Component', function () { let wrapper beforeEach(() => { - wrapper = shallow() + wrapper = shallow(( + + )) }) afterEach(() => { diff --git a/ui/app/components/app/gas-customization/gas-slider/gas-slider.component.js b/ui/app/components/app/gas-customization/gas-slider/gas-slider.component.js index 8233dedb5..629d81f0e 100644 --- a/ui/app/components/app/gas-customization/gas-slider/gas-slider.component.js +++ b/ui/app/components/app/gas-customization/gas-slider/gas-slider.component.js @@ -36,7 +36,7 @@ export default class GasSlider extends Component { onChange={event => onChange(event.target.value)} />
-
+
{lowLabel} diff --git a/ui/app/components/app/input-number.js b/ui/app/components/app/input-number.js index d511dd0d6..7506808b3 100644 --- a/ui/app/components/app/input-number.js +++ b/ui/app/components/app/input-number.js @@ -69,7 +69,8 @@ InputNumber.prototype.render = function InputNumber () { /> {unitLabel}
-
this.setValue(addCurrencies(value, step, { toNumericBase: 'dec' }))} > diff --git a/ui/app/components/app/loading-network-screen/loading-network-screen.component.js b/ui/app/components/app/loading-network-screen/loading-network-screen.component.js index 97b16d08f..22419aabe 100644 --- a/ui/app/components/app/loading-network-screen/loading-network-screen.component.js +++ b/ui/app/components/app/loading-network-screen/loading-network-screen.component.js @@ -61,42 +61,46 @@ export default class LoadingNetworkScreen extends PureComponent { } renderLoadingScreenContent = () => { - return
- - {this.renderMessage()} -
+ return ( +
+ + {this.renderMessage()} +
+ ) } renderErrorScreenContent = () => { const { showNetworkDropdown, setProviderArgs, setProviderType } = this.props - return
- 😞 - { this.context.t('somethingWentWrong') } -
- - - + return ( +
+ 😞 + { this.context.t('somethingWentWrong') } +
+ + + +
-
+ ) } cancelCall = () => { diff --git a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js index 1b9a6a718..b2ed1a8cc 100644 --- a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js +++ b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js @@ -56,7 +56,7 @@ export default class AccountDetailsModal extends Component { }} /> -
+
+ ? ( + + ) : null } diff --git a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js b/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js index 7fe79be5b..7bea983b4 100644 --- a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js +++ b/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js @@ -78,7 +78,9 @@ export default class ConfirmRemoveAccount extends Component { + target="_blank" + href="https://metamask.zendesk.com/hc/en-us/articles/360015289932" + > { t('learnMore') }
diff --git a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js index c251aee66..d503d950e 100644 --- a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js +++ b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js @@ -84,7 +84,8 @@ export default class DepositEtherModal extends Component { return (
+ className="page-container page-container--full-width page-container--full-height" + >
{this.context.t('depositEther')} diff --git a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js index 53ff473e4..661bbdefd 100644 --- a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js +++ b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js @@ -76,18 +76,22 @@ export default class EditApprovalPermission extends PureComponent { className="edit-approval-permission__edit-section__radio-button" onClick={() => this.setState({ selectedOptionIsUnlimited: true })} > -
+
{ selectedOptionIsUnlimited &&
}
-
+
{ tokenAmount < tokenBalance ? t('proposedApprovalLimit') @@ -107,18 +111,22 @@ export default class EditApprovalPermission extends PureComponent { className="edit-approval-permission__edit-section__radio-button" onClick={() => this.setState({ selectedOptionIsUnlimited: false })} > -
+
{ !selectedOptionIsUnlimited &&
}
-
+
{ t('customSpendLimit') }
diff --git a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js index 264bcc041..fd70cbc5b 100644 --- a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js +++ b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js @@ -149,7 +149,7 @@ export default class ExportPrivateKeyModal extends Component { inputClass="qr-ellip-address ellip-address" value={checksumAddress(address)} /> -
+
{this.context.t('showPrivateKeys')}
{this.renderPasswordLabel(privateKey)} diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.component.js b/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.component.js index 6f3225382..9dc953315 100644 --- a/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.component.js +++ b/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.component.js @@ -75,7 +75,8 @@ export default class MetaMetricsOptInModal extends Component {
- This data is aggregated and is therefore anonymous for the purposes of General Data Protection Regulation (EU) 2016/679. For more information in relation to our privacy practices, please see our this.setState({ showAll: !showAll })} > - {childrenToRender.length > 1 ? : null} + {childrenToRender.length > 1 ? ( + + ) : null}
) diff --git a/ui/app/components/app/network-display/network-display.component.js b/ui/app/components/app/network-display/network-display.component.js index bcac637bd..1ecec3179 100644 --- a/ui/app/components/app/network-display/network-display.component.js +++ b/ui/app/components/app/network-display/network-display.component.js @@ -38,13 +38,15 @@ export default class NetworkDisplay extends Component { return networkClass ?
- :
+ : ( +
+ ) } render () { @@ -61,13 +63,15 @@ export default class NetworkDisplay extends Component { { networkClass ?
- :
+ : ( +
+ ) }
{ type === 'rpc' && nickname ? nickname : this.context.t(type) } diff --git a/ui/app/components/app/provider-page-container/provider-page-container-content/provider-page-container-content.component.js b/ui/app/components/app/provider-page-container/provider-page-container-content/provider-page-container-content.component.js index 4062b130f..4f94015b1 100644 --- a/ui/app/components/app/provider-page-container/provider-page-container-content/provider-page-container-content.component.js +++ b/ui/app/components/app/provider-page-container/provider-page-container-content/provider-page-container-content.component.js @@ -68,7 +68,7 @@ export default class ProviderPageContainerContent extends PureComponent {

{t('providerRequest', [title])}

{t('providerRequestInfo')} -
+
{ it('should render checksummed address', () => { - const wrapper = render(, { context: { t: () => {}}}) + const wrapper = render(( + + ), { context: { t: () => {}}}) // Checksummed version of address is displayed assert.equal(wrapper.find('.selected-account__address').text(), '0x1B82...5C9D') assert.equal(wrapper.find('.selected-account__name').text(), 'testName') diff --git a/ui/app/components/app/sidebars/sidebar.component.js b/ui/app/components/app/sidebars/sidebar.component.js index 484b87e4b..6437675c9 100644 --- a/ui/app/components/app/sidebars/sidebar.component.js +++ b/ui/app/components/app/sidebars/sidebar.component.js @@ -20,13 +20,15 @@ export default class Sidebar extends Component { renderOverlay () { const { onOverlayClose } = this.props - return

{ - onOverlayClose && onOverlayClose() - this.props.hideSidebar() - } - } /> + return ( +
{ + onOverlayClose && onOverlayClose() + this.props.hideSidebar() + }} + /> + ) } renderSidebarContent () { diff --git a/ui/app/components/app/sidebars/tests/sidebars-component.test.js b/ui/app/components/app/sidebars/tests/sidebars-component.test.js index 5f6657dde..3416ad8f6 100644 --- a/ui/app/components/app/sidebars/tests/sidebars-component.test.js +++ b/ui/app/components/app/sidebars/tests/sidebars-component.test.js @@ -16,12 +16,14 @@ describe('Sidebar Component', function () { let wrapper beforeEach(() => { - wrapper = shallow() + wrapper = shallow(( + + )) }) afterEach(() => { diff --git a/ui/app/components/app/signature-request-original/signature-request-original.component.js b/ui/app/components/app/signature-request-original/signature-request-original.component.js index 2485ae506..9a92ba5fb 100644 --- a/ui/app/components/app/signature-request-original/signature-request-original.component.js +++ b/ui/app/components/app/signature-request-original/signature-request-original.component.js @@ -171,22 +171,26 @@ export default class SignatureRequestOriginal extends Component {
{ domain - ?
-

- Domain -

- -
+ ? ( +
+

+ Domain +

+ +
+ ) : '' } { message - ?
-

- Message -

- -
+ ? ( +
+

+ Message +

+ +
+ ) : '' }
@@ -221,16 +225,18 @@ export default class SignatureRequestOriginal extends Component { { notice } { type === 'eth_sign' - ? { - global.platform.openWindow({ - url: 'https://metamask.zendesk.com/hc/en-us/articles/360015488751', - }) - }} - > - { this.context.t('learnMore') } - + ? ( + { + global.platform.openWindow({ + url: 'https://metamask.zendesk.com/hc/en-us/articles/360015488751', + }) + }} + > + { this.context.t('learnMore') } + + ) : null }
diff --git a/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js b/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js index 3ac0c9afb..661a933a0 100644 --- a/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js +++ b/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js @@ -14,10 +14,12 @@ export default class SignatureRequestHeader extends PureComponent { return (
- {selectedAccount && } + {selectedAccount && ( + + )} {name}
diff --git a/ui/app/components/app/signature-request/tests/signature-request.test.js b/ui/app/components/app/signature-request/tests/signature-request.test.js index 68b114dd8..6ff07effc 100644 --- a/ui/app/components/app/signature-request/tests/signature-request.test.js +++ b/ui/app/components/app/signature-request/tests/signature-request.test.js @@ -8,11 +8,16 @@ describe('Signature Request Component', function () { let wrapper beforeEach(() => { - wrapper = shallow() + wrapper = shallow(( + + )) }) describe('render', () => { diff --git a/ui/app/components/app/token-cell/token-cell.component.js b/ui/app/components/app/token-cell/token-cell.component.js index 10a3447d1..dc2bbb6d3 100644 --- a/ui/app/components/app/token-cell/token-cell.component.js +++ b/ui/app/components/app/token-cell/token-cell.component.js @@ -107,7 +107,8 @@ export default class TokenCell extends Component {
)}
- { e.stopPropagation() this.setState({ tokenMenuOpen: true }) diff --git a/ui/app/components/app/token-list.js b/ui/app/components/app/token-list.js index 7917cd54a..ee2f85cac 100644 --- a/ui/app/components/app/token-list.js +++ b/ui/app/components/app/token-list.js @@ -66,12 +66,16 @@ TokenList.prototype.render = function TokenList () { if (error) { log.error(error) return ( -
+
{this.context.t('troubleTokenBalances')} { }, } - const wrapper = shallow(, { context: { t }}) + const wrapper = shallow(( + + ), { context: { t }}) assert.equal(wrapper.find('.transaction-action').length, 1) wrapper.setState({ transactionAction: 'sentEther' }) diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js index 5642e0fa5..0e1073337 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js @@ -50,10 +50,12 @@ export default class TransactionBreakdown extends PureComponent { className="transaction-breakdown__row-title" > {typeof gas !== 'undefined' - ? + ? ( + + ) : '?' } @@ -72,13 +74,15 @@ export default class TransactionBreakdown extends PureComponent { } {typeof gasPrice !== 'undefined' - ? + ? ( + + ) : '?' } diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js index 554e99a5b..f3bd51b93 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js +++ b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js @@ -191,15 +191,17 @@ export default class TransactionListItemDetails extends PureComponent { { - showRetry && - - + showRetry && ( + + + + ) }
diff --git a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js b/ui/app/components/app/transaction-list-item/transaction-list-item.component.js index 9ab0105f9..3106f7fc3 100644 --- a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js +++ b/ui/app/components/app/transaction-list-item/transaction-list-item.component.js @@ -236,18 +236,22 @@ export default class TransactionListItem extends PureComponent { )} /> { showEstimatedTime - ? + ? ( + + ) : null } { this.renderPrimaryCurrency() } { this.renderSecondaryCurrency() }
-
+
{ showTransactionDetails && (
diff --git a/ui/app/components/app/transaction-view-balance/tests/token-view-balance.component.test.js b/ui/app/components/app/transaction-view-balance/tests/token-view-balance.component.test.js index 0e2882e9c..d948355fc 100644 --- a/ui/app/components/app/transaction-view-balance/tests/token-view-balance.component.test.js +++ b/ui/app/components/app/transaction-view-balance/tests/token-view-balance.component.test.js @@ -25,14 +25,16 @@ describe('TransactionViewBalance Component', () => { }) it('should render ETH balance properly', () => { - const wrapper = shallow(, { context: { t, metricsEvent } }) + const wrapper = shallow(( + + ), { context: { t, metricsEvent } }) assert.equal(wrapper.find('.transaction-view-balance').length, 1) assert.equal(wrapper.find('.transaction-view-balance__button').length, 2) @@ -55,15 +57,17 @@ describe('TransactionViewBalance Component', () => { symbol: 'ABC', } - const wrapper = shallow(, { context: { t } }) + const wrapper = shallow(( + + ), { context: { t } }) assert.equal(wrapper.find('.transaction-view-balance').length, 1) assert.equal(wrapper.find('.transaction-view-balance__button').length, 1) diff --git a/ui/app/components/app/wallet-view/wallet-view.component.js b/ui/app/components/app/wallet-view/wallet-view.component.js index bf3c97650..ceccfea51 100644 --- a/ui/app/components/app/wallet-view/wallet-view.component.js +++ b/ui/app/components/app/wallet-view/wallet-view.component.js @@ -44,9 +44,11 @@ export default class WalletView extends Component { } = this.props return ( -
+
{ diff --git a/ui/app/components/ui/button-group/button-group.stories.js b/ui/app/components/ui/button-group/button-group.stories.js index c58c628b3..1596680c1 100644 --- a/ui/app/components/ui/button-group/button-group.stories.js +++ b/ui/app/components/ui/button-group/button-group.stories.js @@ -6,7 +6,7 @@ import Button from '../button' import { text, boolean } from '@storybook/addon-knobs/react' storiesOf('ButtonGroup', module) - .add('with Buttons', () => + .add('with Buttons', () => ( - ) - .add('with a disabled Button', () => + )) + .add('with a disabled Button', () => ( - ) + )) diff --git a/ui/app/components/ui/button-group/tests/button-group-component.test.js b/ui/app/components/ui/button-group/tests/button-group-component.test.js index 663d86c74..b07b16cc9 100644 --- a/ui/app/components/ui/button-group/tests/button-group-component.test.js +++ b/ui/app/components/ui/button-group/tests/button-group-component.test.js @@ -21,12 +21,16 @@ describe('ButtonGroup Component', function () { let wrapper beforeEach(() => { - wrapper = shallow({mockButtons}) + wrapper = shallow(( + + {mockButtons} + + )) }) afterEach(() => { diff --git a/ui/app/components/ui/button/button.stories.js b/ui/app/components/ui/button/button.stories.js index 9df53439d..6540d5aa1 100644 --- a/ui/app/components/ui/button/button.stories.js +++ b/ui/app/components/ui/button/button.stories.js @@ -6,7 +6,7 @@ import { text, boolean } from '@storybook/addon-knobs/react' // ', 'secondary', 'default', 'warning', 'danger', 'danger-primary', 'link'], 'primary')} storiesOf('Button', module) - .add('Button - Primary', () => + .add('Button - Primary', () => ( - ) - .add('Button - Secondary', () => + )) + .add('Button - Secondary', () => ( - ) - .add('Button - Default', () => + )) + .add('Button - Default', () => ( - ) - .add('Button - Warning', () => + )) + .add('Button - Warning', () => ( - ) - .add('Button - Danger', () => + )) + .add('Button - Danger', () => ( - ) - .add('Button - Danger Primary', () => + )) + .add('Button - Danger Primary', () => ( - ) - .add('Button - Link', () => + )) + .add('Button - Link', () => ( - ) + )) diff --git a/ui/app/components/ui/currency-display/tests/currency-display.component.test.js b/ui/app/components/ui/currency-display/tests/currency-display.component.test.js index d9ef052f1..387493da6 100644 --- a/ui/app/components/ui/currency-display/tests/currency-display.component.test.js +++ b/ui/app/components/ui/currency-display/tests/currency-display.component.test.js @@ -5,21 +5,25 @@ import CurrencyDisplay from '../currency-display.component' describe('CurrencyDisplay Component', () => { it('should render text with a className', () => { - const wrapper = shallow() + const wrapper = shallow(( + + )) assert.ok(wrapper.hasClass('currency-display')) assert.equal(wrapper.text(), '$123.45') }) it('should render text with a prefix', () => { - const wrapper = shallow() + const wrapper = shallow(( + + )) assert.ok(wrapper.hasClass('currency-display')) assert.equal(wrapper.text(), '-$123.45') diff --git a/ui/app/components/ui/eth-balance/eth-balance.component.js b/ui/app/components/ui/eth-balance/eth-balance.component.js index fedbcc192..925395602 100644 --- a/ui/app/components/ui/eth-balance/eth-balance.component.js +++ b/ui/app/components/ui/eth-balance/eth-balance.component.js @@ -67,29 +67,36 @@ export default class EthBalance extends Component { return (
-
-
+
+
{ incoming ? `+${balanceToRender}` : balanceToRender }
-
+
{label}
@@ -120,7 +127,8 @@ export default class EthBalance extends Component {
+ }} + > {this.renderBalance(formattedValue)}
diff --git a/ui/app/components/ui/hex-to-decimal/tests/hex-to-decimal.component.test.js b/ui/app/components/ui/hex-to-decimal/tests/hex-to-decimal.component.test.js index c98da9ad4..848ef2c4f 100644 --- a/ui/app/components/ui/hex-to-decimal/tests/hex-to-decimal.component.test.js +++ b/ui/app/components/ui/hex-to-decimal/tests/hex-to-decimal.component.test.js @@ -5,20 +5,24 @@ import HexToDecimal from '../hex-to-decimal.component' describe('HexToDecimal Component', () => { it('should render a prefixed hex as a decimal with a className', () => { - const wrapper = shallow() + const wrapper = shallow(( + + )) assert.ok(wrapper.hasClass('hex-to-decimal')) assert.equal(wrapper.text(), '12345') }) it('should render an unprefixed hex as a decimal with a className', () => { - const wrapper = shallow() + const wrapper = shallow(( + + )) assert.ok(wrapper.hasClass('hex-to-decimal')) assert.equal(wrapper.text(), '6789') diff --git a/ui/app/components/ui/identicon/tests/identicon.component.test.js b/ui/app/components/ui/identicon/tests/identicon.component.test.js index 2944818f5..b1efb158c 100644 --- a/ui/app/components/ui/identicon/tests/identicon.component.test.js +++ b/ui/app/components/ui/identicon/tests/identicon.component.test.js @@ -18,7 +18,7 @@ describe('Identicon', () => { it('renders default eth_logo identicon with no props', () => { const wrapper = mount( - + ) assert.equal(wrapper.find('img.balance-icon').prop('src'), './images/eth_logo.svg') diff --git a/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js b/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js index a2cf0100b..da8da45d1 100644 --- a/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js +++ b/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js @@ -37,14 +37,16 @@ export default class PageContainerFooter extends Component {
- {!hideCancel && } + {!hideCancel && ( + + )} + > + {this.context.t('cancel')} + + > + {this.context.t('create')} +
) diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js index 1fae5351c..53d4614ad 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js @@ -283,7 +283,8 @@ export default class ImportWithSeedPhrase extends PureComponent { {termsChecked ? : null}
- I have read and agree to the
: null}
- I have read and agree to the ) diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js b/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js index ad1ffbf42..14c85b923 100644 --- a/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js +++ b/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js @@ -142,7 +142,8 @@ export default class MetaMetricsOptIn extends Component { disabled={false} /> diff --git a/ui/app/pages/home/home.component.js b/ui/app/pages/home/home.component.js index e51c82177..64526fe31 100644 --- a/ui/app/pages/home/home.component.js +++ b/ui/app/pages/home/home.component.js @@ -124,56 +124,62 @@ export default class Home extends PureComponent { { showPrivacyModeNotification - ? { - unsetMigratedPrivacyMode() - window.open('https://medium.com/metamask/42549d4870fa', '_blank', 'noopener') - }} - ignoreText={t('dismiss')} - onIgnore={() => { - unsetMigratedPrivacyMode() - }} - key="home-privacyModeDefault" - /> + ? ( + { + unsetMigratedPrivacyMode() + window.open('https://medium.com/metamask/42549d4870fa', '_blank', 'noopener') + }} + ignoreText={t('dismiss')} + onIgnore={() => { + unsetMigratedPrivacyMode() + }} + key="home-privacyModeDefault" + /> + ) : null } { shouldShowSeedPhraseReminder - ? { - if (isPopup) { - global.platform.openExtensionInBrowser(INITIALIZE_BACKUP_SEED_PHRASE_ROUTE) - } else { - history.push(INITIALIZE_BACKUP_SEED_PHRASE_ROUTE) - } - }} - infoText={t('backupApprovalInfo')} - key="home-backupApprovalNotice" - /> + ? ( + { + if (isPopup) { + global.platform.openExtensionInBrowser(INITIALIZE_BACKUP_SEED_PHRASE_ROUTE) + } else { + history.push(INITIALIZE_BACKUP_SEED_PHRASE_ROUTE) + } + }} + infoText={t('backupApprovalInfo')} + key="home-backupApprovalNotice" + /> + ) : null } { threeBoxLastUpdated && showRestorePrompt - ? { - restoreFromThreeBox(selectedAddress) - .then(() => { - turnThreeBoxSyncingOn() - }) - }} - onIgnore={() => { - setShowRestorePromptToFalse() - }} - key="home-privacyModeDefault" - /> + ? ( + { + restoreFromThreeBox(selectedAddress) + .then(() => { + turnThreeBoxSyncingOn() + }) + }} + onIgnore={() => { + setShowRestorePromptToFalse() + }} + key="home-privacyModeDefault" + /> + ) : null } { diff --git a/ui/app/pages/send/account-list-item/account-list-item.component.js b/ui/app/pages/send/account-list-item/account-list-item.component.js index 20ced2f09..8c676f419 100644 --- a/ui/app/pages/send/account-list-item/account-list-item.component.js +++ b/ui/app/pages/send/account-list-item/account-list-item.component.js @@ -44,30 +44,32 @@ export default class AccountListItem extends Component { const { name, address, balance } = account || {} - return (
handleClick && handleClick({ name, address, balance })} - > + return ( +
handleClick && handleClick({ name, address, balance })} + > -
- +
+ -
{ name || address }
+
{ name || address }
- {icon &&
{ icon }
} + {icon &&
{ icon }
} -
+
- {displayAddress && name &&
- { checksumAddress(address) } -
} + {displayAddress && name && ( +
+ { checksumAddress(address) } +
+ )} - { - displayBalance && ( + {displayBalance && ( -
+
{ - balanceIsCached ? * : null + balanceIsCached + ? * + : null }
- { - showFiat && ( - - ) - } + {showFiat && ( + + )}
- ) - } + )} -
) +
+ ) } } diff --git a/ui/app/pages/send/account-list-item/tests/account-list-item-component.test.js b/ui/app/pages/send/account-list-item/tests/account-list-item-component.test.js index 5a2bd5638..e54a8c493 100644 --- a/ui/app/pages/send/account-list-item/tests/account-list-item-component.test.js +++ b/ui/app/pages/send/account-list-item/tests/account-list-item-component.test.js @@ -23,17 +23,19 @@ describe('AccountListItem Component', function () { let wrapper beforeEach(() => { - wrapper = shallow(} - />, { context: { t: str => str + '_t' } }) + wrapper = shallow(( + } + /> + ), { context: { t: str => str + '_t' } }) }) afterEach(() => { diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js b/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js index bad912c0a..a2e6b49db 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js +++ b/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js @@ -155,7 +155,7 @@ export default class AddRecipient extends Component { className="send__select-recipient-wrapper__list__link" onClick={() => this.setState({ isShowingTransfer: false })} > -
+
{ t('backToAll') }
{ - wrapper = shallow(, { context: { t: str => str + '_t' } }) + wrapper = shallow(( + + ), { context: { t: str => str + '_t' } }) instance = wrapper.instance() }) diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js index 30ef4c678..48bc32d3a 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js @@ -18,15 +18,17 @@ describe('AmountMaxButton Component', function () { let instance beforeEach(() => { - wrapper = shallow(, { + wrapper = shallow(( + + ), { context: { t: str => str + '_t', metricsEvent: () => {}, diff --git a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js index bfc0f7e64..fe648d4d8 100644 --- a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js @@ -25,23 +25,25 @@ describe('SendAmountRow Component', function () { let instance beforeEach(() => { - wrapper = shallow(, { context: { t: str => str + '_t' } }) + wrapper = shallow(( + + ), { context: { t: str => str + '_t' } }) instance = wrapper.instance() }) diff --git a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js index 1dcd0bd2c..c0b604505 100644 --- a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js +++ b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js @@ -128,7 +128,8 @@ export default class SendAssetRow extends Component { return (
this.selectToken(address)} >
diff --git a/ui/app/pages/send/send-content/send-dropdown-list/send-dropdown-list.component.js b/ui/app/pages/send/send-content/send-dropdown-list/send-dropdown-list.component.js index 5f5d26231..42b19397b 100644 --- a/ui/app/pages/send/send-content/send-dropdown-list/send-dropdown-list.component.js +++ b/ui/app/pages/send/send-content/send-dropdown-list/send-dropdown-list.component.js @@ -17,7 +17,7 @@ export default class SendDropdownList extends Component { getListItemIcon (accountAddress, activeAddress) { return accountAddress === activeAddress - ? + ? : null } @@ -29,24 +29,28 @@ export default class SendDropdownList extends Component { activeAddress, } = this.props - return (
-
closeDropdown()} - /> -
- {accounts.map((account, index) => { - onSelect(account) - closeDropdown() - }} - icon={this.getListItemIcon(account.address, activeAddress)} - key={`send-dropdown-account-#${index}`} - />)} + return ( +
+
closeDropdown()} + /> +
+ {accounts.map((account, index) => ( + { + onSelect(account) + closeDropdown() + }} + icon={this.getListItemIcon(account.address, activeAddress)} + key={`send-dropdown-account-#${index}`} + /> + ))} +
-
) + ) } } diff --git a/ui/app/pages/send/send-content/send-dropdown-list/tests/send-dropdown-list-component.test.js b/ui/app/pages/send/send-content/send-dropdown-list/tests/send-dropdown-list-component.test.js index bc6c97586..77efddfd4 100644 --- a/ui/app/pages/send/send-content/send-dropdown-list/tests/send-dropdown-list-component.test.js +++ b/ui/app/pages/send/send-content/send-dropdown-list/tests/send-dropdown-list-component.test.js @@ -17,16 +17,18 @@ describe('SendDropdownList Component', function () { let wrapper beforeEach(() => { - wrapper = shallow(, { context: { t: str => str + '_t' } }) + wrapper = shallow(( + + ), { context: { t: str => str + '_t' } }) }) afterEach(() => { @@ -39,7 +41,7 @@ describe('SendDropdownList Component', function () { it('should return check icon if the passed addresses are the same', () => { assert.deepEqual( wrapper.instance().getListItemIcon('mockAccount0', 'mockAccount0'), - + ) }) diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js index 37af59e29..473dbb0b1 100644 --- a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js +++ b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js @@ -38,12 +38,16 @@ export default class GasFeeDisplay extends Component {
) : gasLoadingError - ?
- {this.context.t('setGasPrice')} -
- :
- {this.context.t('loading')} -
+ ? ( +
+ {this.context.t('setGasPrice')} +
+ ) + : ( +
+ {this.context.t('loading')} +
+ ) } -
+ ? ( +
+ +
+ ) : null }
diff --git a/ui/app/pages/settings/settings.component.js b/ui/app/pages/settings/settings.component.js index 975ab4e35..b0ee55dc7 100644 --- a/ui/app/pages/settings/settings.component.js +++ b/ui/app/pages/settings/settings.component.js @@ -135,13 +135,19 @@ class SettingsPage extends PureComponent {
initialBreadCrumbRoute && history.push(initialBreadCrumbRoute)} - >{subheaderText}
- {breadCrumbTextKey &&
{' > '}{t(breadCrumbTextKey)}
} - {isAddressEntryPage &&
{' > '}{addressName}
} + > + {subheaderText} +
+ {breadCrumbTextKey && ( +
+ {' > '}{t(breadCrumbTextKey)} +
+ )} + {isAddressEntryPage && ( +
+ {' > '}{addressName} +
+ )}
) } From 1e4f8e68e05887ac8d9d58321b15f6e38c007c28 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 26 Nov 2019 10:10:15 -0330 Subject: [PATCH 007/689] eslint: Enable no-confusing-arrow rule --- .eslintrc | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc b/.eslintrc index 74b30dcbe..7dd494ddc 100644 --- a/.eslintrc +++ b/.eslintrc @@ -72,6 +72,7 @@ "no-caller": 2, "no-class-assign": 2, "no-cond-assign": 2, + "no-confusing-arrow": 2, "no-const-assign": 2, "no-control-regex": 2, "no-debugger": 2, From 16e6103a685eed50a5556c935411d01abe95f0cd Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 3 Dec 2019 13:23:13 -0330 Subject: [PATCH 008/689] yarn lint --fix --- app/scripts/controllers/transactions/lib/util.js | 4 ++-- .../app/controllers/network/pending-middleware-test.js | 2 +- .../tests/gas-modal-page-container-component.test.js | 2 +- .../tests/transaction-activity-log.component.test.js | 6 +++--- .../tests/transaction-breakdown.component.test.js | 2 +- .../tests/transaction-breakdown-row.component.test.js | 4 ++-- .../tests/transaction-list-item-details.component.test.js | 8 ++++---- .../tests/token-view-balance.component.test.js | 2 +- ui/app/ducks/gas/gas.duck.js | 2 +- .../confirm-transaction-base.container.js | 4 ++-- .../send/send-header/tests/send-header-component.test.js | 2 +- ui/app/pages/send/send.utils.js | 2 +- ui/lib/shallow-with-context.js | 2 +- 13 files changed, 21 insertions(+), 21 deletions(-) diff --git a/app/scripts/controllers/transactions/lib/util.js b/app/scripts/controllers/transactions/lib/util.js index 86924e7fa..6e0b5bd42 100644 --- a/app/scripts/controllers/transactions/lib/util.js +++ b/app/scripts/controllers/transactions/lib/util.js @@ -17,8 +17,8 @@ module.exports = { // functions that handle normalizing of that key in txParams const normalizers = { - from: (from, LowerCase = true) => LowerCase ? addHexPrefix(from).toLowerCase() : addHexPrefix(from), - to: (to, LowerCase = true) => LowerCase ? addHexPrefix(to).toLowerCase() : addHexPrefix(to), + from: (from, LowerCase = true) => (LowerCase ? addHexPrefix(from).toLowerCase() : addHexPrefix(from)), + to: (to, LowerCase = true) => (LowerCase ? addHexPrefix(to).toLowerCase() : addHexPrefix(to)), nonce: nonce => addHexPrefix(nonce), value: value => addHexPrefix(value), data: data => addHexPrefix(data), diff --git a/test/unit/app/controllers/network/pending-middleware-test.js b/test/unit/app/controllers/network/pending-middleware-test.js index ac6f8ad9a..d33ea49f0 100644 --- a/test/unit/app/controllers/network/pending-middleware-test.js +++ b/test/unit/app/controllers/network/pending-middleware-test.js @@ -30,7 +30,7 @@ describe('#createPendingNonceMiddleware', function () { describe('#createPendingTxMiddleware', function () { let returnUndefined = true - const getPendingTransactionByHash = () => returnUndefined ? undefined : txMetaStub + const getPendingTransactionByHash = () => (returnUndefined ? undefined : txMetaStub) const address = '0xF231D46dD78806E1DD93442cf33C7671f8538748' const pendingTxMiddleware = createPendingTxMiddleware({ getPendingTransactionByHash }) const spec = { diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js index 50efb46f0..32f144692 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js @@ -141,7 +141,7 @@ describe('GasModalPageContainer Component', function () { fetchBasicGasAndTimeEstimates={propsMethodSpies.fetchBasicGasAndTimeEstimates} fetchGasEstimates={propsMethodSpies.fetchGasEstimates} /> - ), { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } }) + ), { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }) const { tabsComponent } = renderTabsWrapperTester.find(PageContainer).props() assert.equal(tabsComponent, 'mockTabs') GasModalPageContainer.prototype.renderTabs.restore() diff --git a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js index 6625a46a9..b497a4f1b 100644 --- a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js +++ b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js @@ -44,7 +44,7 @@ describe('TransactionActivityLog Component', () => { onRetry={() => {}} primaryTransactionStatus="confirmed" />, - { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } } + { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } ) assert.ok(wrapper.hasClass('transaction-activity-log')) @@ -92,7 +92,7 @@ describe('TransactionActivityLog Component', () => { primaryTransactionStatus="pending" isEarliestNonce />, - { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } } + { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } ) assert.ok(wrapper.hasClass('transaction-activity-log')) @@ -141,7 +141,7 @@ describe('TransactionActivityLog Component', () => { primaryTransactionStatus="pending" isEarliestNonce={false} />, - { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } } + { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } ) assert.ok(wrapper.hasClass('transaction-activity-log')) diff --git a/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js b/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js index 4512b84f0..b34a4e9ce 100644 --- a/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js +++ b/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js @@ -24,7 +24,7 @@ describe('TransactionBreakdown Component', () => { transaction={transaction} className="test-class" />, - { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } } + { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } ) assert.ok(wrapper.hasClass('transaction-breakdown')) diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js index 82e40fce2..c17fcc940 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js @@ -13,7 +13,7 @@ describe('TransactionBreakdownRow Component', () => { > Test , - { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } } + { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } ) assert.ok(wrapper.hasClass('transaction-breakdown-row')) @@ -29,7 +29,7 @@ describe('TransactionBreakdownRow Component', () => { > , - { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } } + { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } ) assert.ok(wrapper.hasClass('transaction-breakdown-row')) diff --git a/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js b/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js index 69360fec6..67e625b0d 100644 --- a/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js +++ b/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js @@ -33,7 +33,7 @@ describe('TransactionListItemDetails Component', () => { , - { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } } + { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } ) assert.ok(wrapper.hasClass('transaction-list-item-details')) @@ -72,7 +72,7 @@ describe('TransactionListItemDetails Component', () => { transactionGroup={transactionGroup} showSpeedUp />, - { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } } + { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } ) assert.ok(wrapper.hasClass('transaction-list-item-details')) @@ -104,7 +104,7 @@ describe('TransactionListItemDetails Component', () => { , - { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } } + { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } ) assert.ok(wrapper.hasClass('transaction-list-item-details')) @@ -139,7 +139,7 @@ describe('TransactionListItemDetails Component', () => { , - { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } } + { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } ) assert.ok(wrapper.hasClass('transaction-list-item-details')) diff --git a/ui/app/components/app/transaction-view-balance/tests/token-view-balance.component.test.js b/ui/app/components/app/transaction-view-balance/tests/token-view-balance.component.test.js index d948355fc..3d8167968 100644 --- a/ui/app/components/app/transaction-view-balance/tests/token-view-balance.component.test.js +++ b/ui/app/components/app/transaction-view-balance/tests/token-view-balance.component.test.js @@ -15,7 +15,7 @@ const historySpies = { push: sinon.spy(), } -const t = (str1, str2) => str2 ? str1 + str2 : str1 +const t = (str1, str2) => (str2 ? str1 + str2 : str1) const metricsEvent = () => ({}) describe('TransactionViewBalance Component', () => { diff --git a/ui/app/ducks/gas/gas.duck.js b/ui/app/ducks/gas/gas.duck.js index 700fec6b0..4443995de 100644 --- a/ui/app/ducks/gas/gas.duck.js +++ b/ui/app/ducks/gas/gas.duck.js @@ -353,7 +353,7 @@ function quartiles (data) { } function inliersByIQR (data, prop) { - const { lowerQuartile, upperQuartile } = quartiles(data.map(d => prop ? d[prop] : d)) + const { lowerQuartile, upperQuartile } = quartiles(data.map(d => (prop ? d[prop] : d))) const IQR = upperQuartile - lowerQuartile const lowerBound = lowerQuartile - 1.5 * IQR const upperBound = upperQuartile + 1.5 * IQR diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js index 9a238e780..f393212d1 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js @@ -40,10 +40,10 @@ const casedContractMap = Object.keys(contractMap).reduce((acc, base) => { }, {}) let customNonceValue = '' -const customNonceMerge = txData => customNonceValue ? ({ +const customNonceMerge = txData => (customNonceValue ? ({ ...txData, customNonceValue, -}) : txData +}) : txData) const mapStateToProps = (state, ownProps) => { const { toAddress: propsToAddress, customTxParamsData, match: { params = {} } } = ownProps diff --git a/ui/app/pages/send/send-header/tests/send-header-component.test.js b/ui/app/pages/send/send-header/tests/send-header-component.test.js index d4cfd441b..166d12487 100644 --- a/ui/app/pages/send/send-header/tests/send-header-component.test.js +++ b/ui/app/pages/send/send-header/tests/send-header-component.test.js @@ -26,7 +26,7 @@ describe('SendHeader Component', function () { history={historySpies} titleKey="mockTitleKey" /> - ), { context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } }) + ), { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }) }) afterEach(() => { diff --git a/ui/app/pages/send/send.utils.js b/ui/app/pages/send/send.utils.js index aef9c7e78..b93540147 100644 --- a/ui/app/pages/send/send.utils.js +++ b/ui/app/pages/send/send.utils.js @@ -331,7 +331,7 @@ function estimateGasPriceFromRecentBlocks (recentBlocks) { return parseInt(next, 16) < parseInt(currentLowest, 16) ? next : currentLowest }) }) - .sort((a, b) => parseInt(a, 16) > parseInt(b, 16) ? 1 : -1) + .sort((a, b) => (parseInt(a, 16) > parseInt(b, 16) ? 1 : -1)) return lowestPrices[Math.floor(lowestPrices.length / 2)] } diff --git a/ui/lib/shallow-with-context.js b/ui/lib/shallow-with-context.js index cf83dd76e..515281928 100644 --- a/ui/lib/shallow-with-context.js +++ b/ui/lib/shallow-with-context.js @@ -2,6 +2,6 @@ import { shallow } from 'enzyme' export default function (jsxComponent) { return shallow(jsxComponent, { - context: { t: (str1, str2) => str2 ? str1 + str2 : str1 }, + context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) }, }) } From f519fa1ed3839bf0f4024517271902fd21c76596 Mon Sep 17 00:00:00 2001 From: Dan Finlay <542863+danfinlay@users.noreply.github.com> Date: Tue, 3 Dec 2019 09:35:56 -0800 Subject: [PATCH 009/689] Connect distinct accounts per site (#7004) * add PermissionsController remove provider approval controller integrate rpc-cap create PermissionsController move provider approval functionality to permissions controller add permissions approval ui, settings page add permissions activity and history move some functionality to metamask-inpage-provider rename siteMetadata -> domainMetadata add accountsChange notification to inpage provider move functionality to inpage provider update inpage provider Remove 'Connections' settings page (#7369) add hooks for exposing accounts in settings rename unused messages in non-English locales Add external extension id to metadata (#7396) update inpage provider, rpc-cap add eth_requestAccounts handling to background prevent notifying connections if extension is locked update inpage provider Fix lint errors add migration review fixes transaction controller review updates removed unused messages * Login Per Site UI (#7368) * LoginPerSite original UI changes to keep * First commit * Get necessary connected tab info for redirect and icon display for permissioned sites * Fix up designs and add missing features * Some lint fixes * More lint fixes * Ensures the tx controller + tx-state-manager orders transactions in the order they are received * Code cleanup for LoginPerSite-ui * Update e2e tests to use new connection flow * Fix display of connect screen and app header after login when connect request present * Update metamask-responsive-ui.spec for new item in accounts dropdown * Fix approve container by replacing approvedOrigins with domainMetaData * Adds test/e2e/permissions.spec.js * Correctly handle cancellation of a permissions request * Redirect to home after disconnecting all sites / cancelling all permissions * Fix display of site icons in menu * Fix height of permissions page container * Remove unused locale messages * Set default values for openExternalTabs and tabIdOrigins in account-menu.container * More code cleanup for LoginPerSite-ui * Use extensions api to close tab in permissions-connect * Remove unnecessary change in domIsReady() in contentscript * Remove unnecessary private function markers and class methods (for background tab info) in metamask-controller. * Adds getOriginOfCurrentTab selector * Adds IconWithFallback component and substitutes for appropriate cases * Add and utilize font mixins * Remove unused method in disconnect-all.container.js * Simplify buttonSizeLarge code in page-container-footer.component.js * Add and utilize getAccountsWithLabels selector * Remove console.log in ui/app/store/actions.js * Change last connected time format to yyyy-M-d * Fix css associated with IconWithFallback change * Ensure tracked openNonMetamaskTabsIDs are correctly set to inactive on tab changes * Code cleanup for LoginPerSite-ui * Use reusable function for modifying openNonMetamaskTabsIDs in background.js * Enables automatic switching to connected account when connected domain is open * Prevent exploit of tabIdOriginMap in background.js * Remove unneeded code from contentscript.js * Simplify current tab origin and window opener logic using remotePort listener tabs.queryTabs * Design and styling fixes for LoginPerSite-ui * Fix permissionHistory and permission logging for eth_requestAccounts and eth_accounts * Front end changes to support display of lastConnected time in connected and permissions screens * Fix lint errors * Refactor structure of permissionsHistory * Fix default values and object modifications for domain and permissionsHistory related data * Fix connecting to new accounts from modal * Replace retweet.svg with connect-white.svg * Fix signature-request.spec * Update metamask-inpage-provider version * Fix permissions e2e tests * Remove unneeded delay from test/e2e/signature-request.spec.js * Add delay before attempting to retrieve network id in dapp in ethereum-on=.spec * Use requestAccountTabIds strategy for determining tab id that opened a given window * Improve default values for permissions requests * Add some message descriptions to app/_locales/en/messages.json * Code clean up in permission controller * Stopped deep cloning object in mapObjectValues * Bump metamask-inpage-provider version * Add missing description in app/_locales/en/messages.json * Return promises from queryTabs and switchToTab of extension.js * Remove unused getAllPermissions function * Use default props in icon-with-fallback.component.js * Stop passing to permissions controller * Delete no longer used clear-approved-origins modal code * Remove duplicate imports in ui/app/components/app/index.scss * Use URL instead of regex in getOriginFromUrl() * Add runtime error checking to platform, promise based extension.tab methods * Support permission requests from external extensions * Improve font size and colour of the domain origin on the permission confirmation screen * Add support for toggling permissions * Ensure getRenderablePermissionsDomains only returns domains with exposedAccount caveat permissions * Remove unused code from LoginPerSite-ui branch * Ensure modal closes on Enter press for new-account-modal.component.js * Lint fix * fixup! Login Per Site UI (#7368) * Some code cleanup for LoginPerSite * Adds UX for connecting to dapps via the connected sites screen (#7593) * Adds UX for connecting to dapps via the connected sites screen * Use openMetaMaskTabIds from background.js to determine if current active tab is MetaMask * Delete unused permissions controller methods * Fixes two small bugs in the LoginPerSite ui (#7595) * Restore `providerRequest` message translations (#7600) This message was removed, but it was replaced with a very similar message called `likeToConnect`. The only difference is that the new message has "MetaMask" in it. Preserving these messages without "MetaMask" is probably better than deleting them, so these messages have all been restored and renamed to `likeToConnect`. * Login per site no sitemetadata fix (#7610) * Support connected sites for which we have no site metadata. * Change property containing subtitle info often populated by origin to a more accurate of purpose name * Lint fix * Improve disconnection modal messages (#7612) * Improve disconnectAccountModalDescription and disconnectAllModalDescription messages * Update disconnectAccountModalDescription app/_locales/en/messages.json Co-Authored-By: Mark Stacey * Improve disconnectAccount modal message clarity * Adds cancel button to the account selection screen of the permissions request flow (#7613) * Fix eth_accounts permission language & selectability (#7614) * fix eth_accounts language & selectability * fix MetaMask capitalization in all messages * Close sidebar when opening connected sites (#7611) The 'Connected Sites' button in the accounts details now closes the sidebar, if it is open. This was accomplished by pulling the click handler for that button up to the wallet view component, where another button already followed a similar pattern of closing the sidebar. It seemed confusing to me that one handler was in the `AccountsDetails` container component, and one was handed down from above, so I added PropTypes to the container component. I'm not sure that the WalletView component is the best place for this logic, but I've put it there for now to be consistent with the add token button. * Reject permissions request upon tab close (#7618) Permissions requests are now rejected when the page is closed. This only applies to the full-screen view, as that is the view permission requests should be handled in. The case where the user deals with the request through a different view is handled in #7617 * Handle tab update failure (#7619) `extension.tabs.update` can sometimes fail if the user interacts with the tabs directly around the same time. The redirect flow has been updated to ensure that the permissions tab is still closed in that case. The user is on their own to find the dapp tab again in that case. * Login per site tab popup fixes (#7617) * Handle redirect in response to state update in permissions-connect * Ensure origin is available to permissions-connect subcomponents during redirect * Hide app bar whenever on redirect route * Improvements to handling of redirects in permissions-connect * Ensure permission request id change handling only happens when page is not null * Lint fix * Decouple confirm transaction screen from the selected address (#7622) * Avoid race condtion that could prevent contextual account switching (#7623) There was a race condition in the logic responsible for switching the selected account based upon the active tab. It was asynchronously querying the active tab, then assuming it had been retrieved later. The active tab info itself was already in the redux store in another spot, one that is guaranteed to be set before the UI renders. The race condition was avoided by deleting the duplicate state, and using the other active tab state. * Only redirect back to dapp if current tab is active (#7621) The "redirect back to dapp" behaviour can be disruptive when the permissions connect tab is not active. The purpose of the redirect was to maintain context between the dapp and the permissions request, but if the user has already moved to another tab, that no longer applies. * Fix JSX style lint errors * Remove unused state --- app/_locales/am/messages.json | 20 +- app/_locales/ar/messages.json | 20 +- app/_locales/bg/messages.json | 20 +- app/_locales/bn/messages.json | 20 +- app/_locales/ca/messages.json | 22 +- app/_locales/cs/messages.json | 9 - app/_locales/da/messages.json | 20 +- app/_locales/de/messages.json | 20 +- app/_locales/el/messages.json | 20 +- app/_locales/en/messages.json | 109 +++-- app/_locales/es/messages.json | 20 +- app/_locales/es_419/messages.json | 20 +- app/_locales/et/messages.json | 24 +- app/_locales/fa/messages.json | 20 +- app/_locales/fi/messages.json | 20 +- app/_locales/fil/messages.json | 17 +- app/_locales/fr/messages.json | 20 +- app/_locales/gu/messages.json | 3 - app/_locales/he/messages.json | 20 +- app/_locales/hi/messages.json | 20 +- app/_locales/hn/messages.json | 9 - app/_locales/hr/messages.json | 20 +- app/_locales/ht/messages.json | 9 - app/_locales/hu/messages.json | 20 +- app/_locales/id/messages.json | 20 +- app/_locales/it/messages.json | 38 +- app/_locales/ja/messages.json | 16 +- app/_locales/kn/messages.json | 20 +- app/_locales/ko/messages.json | 20 +- app/_locales/lt/messages.json | 20 +- app/_locales/lv/messages.json | 20 +- app/_locales/ml/messages.json | 3 - app/_locales/mr/messages.json | 3 - app/_locales/ms/messages.json | 20 +- app/_locales/nl/messages.json | 9 - app/_locales/no/messages.json | 20 +- app/_locales/ph/messages.json | 9 - app/_locales/pl/messages.json | 20 +- app/_locales/pt/messages.json | 9 - app/_locales/pt_BR/messages.json | 20 +- app/_locales/pt_PT/messages.json | 3 - app/_locales/ro/messages.json | 20 +- app/_locales/ru/messages.json | 20 +- app/_locales/sk/messages.json | 20 +- app/_locales/sl/messages.json | 20 +- app/_locales/sr/messages.json | 20 +- app/_locales/sv/messages.json | 20 +- app/_locales/sw/messages.json | 20 +- app/_locales/ta/messages.json | 12 - app/_locales/te/messages.json | 3 - app/_locales/th/messages.json | 14 +- app/_locales/tr/messages.json | 9 - app/_locales/uk/messages.json | 20 +- app/_locales/vi/messages.json | 9 - app/_locales/zh_CN/messages.json | 22 +- app/_locales/zh_TW/messages.json | 20 +- app/images/broken-line.svg | 3 + app/images/connect-white.svg | 3 + ...proval-check.svg => permissions-check.svg} | 0 app/scripts/background.js | 25 +- app/scripts/contentscript.js | 96 +---- app/scripts/controllers/permissions/index.js | 377 ++++++++++++++++++ .../permissions/loggerMiddleware.js | 169 ++++++++ .../permissions/methodMiddleware.js | 90 +++++ .../permissions/permissions-safe-methods.json | 49 +++ .../permissions/restrictedMethods.js | 20 + app/scripts/controllers/preferences.js | 14 +- app/scripts/controllers/provider-approval.js | 177 -------- app/scripts/controllers/transactions/index.js | 83 ++-- app/scripts/createStandardProvider.js | 73 ---- app/scripts/inpage.js | 132 +----- app/scripts/lib/auto-reload.js | 5 +- app/scripts/lib/createOriginMiddleware.js | 1 + app/scripts/lib/local-store.js | 19 +- app/scripts/lib/message-manager.js | 4 +- app/scripts/lib/personal-message-manager.js | 4 +- app/scripts/lib/typed-message-manager.js | 4 +- app/scripts/lib/util.js | 29 ++ app/scripts/metamask-controller.js | 282 +++++++------ app/scripts/migrations/029.js | 1 - app/scripts/migrations/040.js | 23 ++ app/scripts/platforms/extension.js | 54 ++- docs/porting_to_new_environment.md | 13 +- package.json | 8 +- test/e2e/contract-test/contract.js | 12 + test/e2e/contract-test/index.html | 5 + test/e2e/ethereum-on.spec.js | 19 +- test/e2e/metamask-responsive-ui.spec.js | 2 +- test/e2e/metamask-ui.spec.js | 19 +- test/e2e/permissions.spec.js | 201 ++++++++++ test/e2e/run-all.sh | 8 + test/e2e/signature-request.spec.js | 24 +- .../preferences-controller-test.js | 3 +- .../app/controllers/provider-approval-test.js | 330 --------------- .../transactions/tx-controller-test.js | 5 +- .../account-details.component.js | 18 +- .../account-details.container.js | 17 +- .../components/app/account-details/index.scss | 6 + .../account-menu/account-menu.component.js | 15 + .../account-menu/account-menu.container.js | 9 +- ui/app/components/app/account-menu/index.scss | 4 + .../connected-sites-list.component.js | 157 ++++++++ .../connected-sites-list.container.js | 57 +++ .../app/connected-sites-list/index.js | 1 + .../app/connected-sites-list/index.scss | 125 ++++++ .../app/dropdowns/account-details-dropdown.js | 23 +- ui/app/components/app/index.scss | 12 +- .../components/app/modal/modal.component.js | 41 +- .../clear-approved-origins.component.js | 39 -- .../modals/clear-approved-origins/index.js | 1 - .../disconnect-account.component.js | 52 +++ .../disconnect-account.container.js | 44 ++ .../app/modals/disconnect-account/index.js | 1 + .../app/modals/disconnect-account/index.scss | 25 ++ .../disconnect-all.component.js | 54 +++ .../disconnect-all.container.js} | 12 +- .../app/modals/disconnect-all/index.js | 1 + .../app/modals/disconnect-all/index.scss | 38 ++ ui/app/components/app/modals/index.scss | 6 + ui/app/components/app/modals/modal.js | 98 ++++- .../app/modals/new-account-modal/index.js | 1 + .../app/modals/new-account-modal/index.scss | 37 ++ .../new-account-modal.component.js | 78 ++++ .../new-account-modal.container.js | 44 ++ .../app/permission-page-container/index.js | 3 + .../app/permission-page-container/index.scss | 281 +++++++++++++ .../index.js | 1 + ...ission-page-container-content.component.js | 163 ++++++++ .../permission-page-container-header/index.js | 1 + ...ission-page-container-header.component.js} | 4 +- .../permission-page-container.component.js | 151 +++++++ .../permission-page-container.container.js | 28 ++ .../app/provider-page-container/index.js | 3 - .../app/provider-page-container/index.scss | 121 ------ .../provider-page-container-content/index.js | 1 - ...ovider-page-container-content.component.js | 87 ---- ...ovider-page-container-content.container.js | 11 - .../provider-page-container-header/index.js | 1 - .../provider-page-container.component.js | 107 ----- .../app/wallet-view/wallet-view.component.js | 15 +- .../icon-with-fallback.component.js | 42 ++ .../components/ui/icon-with-fallback/index.js | 1 + .../ui/icon-with-fallback/index.scss | 30 ++ .../page-container-footer.component.js | 6 +- ui/app/css/itcss/components/pages/index.scss | 2 +- ...approval.scss => permission-approval.scss} | 4 +- ui/app/css/itcss/settings/variables.scss | 29 ++ ui/app/ducks/app/app.js | 18 + ui/app/helpers/constants/routes.js | 4 + ui/app/helpers/utils/util.js | 7 + .../confirm-approve.container.js | 4 +- .../confirm-transaction-base.container.js | 8 +- .../connected-sites.component.js | 36 ++ ui/app/pages/connected-sites/index.js | 1 + ui/app/pages/connected-sites/index.scss | 37 ++ ui/app/pages/home/home.component.js | 39 +- ui/app/pages/home/home.container.js | 12 +- ui/app/pages/index.scss | 4 + .../choose-account.component.js | 108 +++++ .../choose-account/index.js | 1 + .../choose-account/index.scss | 97 +++++ ui/app/pages/permissions-connect/index.js | 1 + ui/app/pages/permissions-connect/index.scss | 11 + .../permissions-connect-footer/index.js | 1 + .../permissions-connect-footer/index.scss | 27 ++ .../permissions-connect-footer.component.js | 27 ++ .../permissions-connect-header/index.js | 1 + .../permissions-connect-header/index.scss | 15 + .../permissions-connect-header.component.js | 25 ++ .../permissions-connect.component.js | 208 ++++++++++ .../permissions-connect.container.js | 66 +++ ui/app/pages/provider-approval/index.js | 1 - .../provider-approval.component.js | 36 -- .../provider-approval.container.js | 12 - ui/app/pages/routes/index.js | 60 ++- .../connected-site-row.component.js | 31 -- .../connected-site-row/index.js | 1 - .../connected-site-row/index.scss | 14 - .../connections-tab.component.js | 133 ------ .../connections-tab.container.js | 39 -- .../pages/settings/connections-tab/index.js | 1 - .../pages/settings/connections-tab/index.scss | 1 - ui/app/pages/settings/index.scss | 2 - ui/app/pages/settings/settings.component.js | 8 - ui/app/selectors/selectors.js | 189 +++++++++ ui/app/store/actions.js | 113 +++++- yarn.lock | 54 ++- 187 files changed, 4275 insertions(+), 2713 deletions(-) create mode 100644 app/images/broken-line.svg create mode 100644 app/images/connect-white.svg rename app/images/{provider-approval-check.svg => permissions-check.svg} (100%) create mode 100644 app/scripts/controllers/permissions/index.js create mode 100644 app/scripts/controllers/permissions/loggerMiddleware.js create mode 100644 app/scripts/controllers/permissions/methodMiddleware.js create mode 100644 app/scripts/controllers/permissions/permissions-safe-methods.json create mode 100644 app/scripts/controllers/permissions/restrictedMethods.js delete mode 100644 app/scripts/controllers/provider-approval.js delete mode 100644 app/scripts/createStandardProvider.js create mode 100644 app/scripts/migrations/040.js create mode 100644 test/e2e/permissions.spec.js delete mode 100644 test/unit/app/controllers/provider-approval-test.js create mode 100644 ui/app/components/app/connected-sites-list/connected-sites-list.component.js create mode 100644 ui/app/components/app/connected-sites-list/connected-sites-list.container.js create mode 100644 ui/app/components/app/connected-sites-list/index.js create mode 100644 ui/app/components/app/connected-sites-list/index.scss delete mode 100644 ui/app/components/app/modals/clear-approved-origins/clear-approved-origins.component.js delete mode 100644 ui/app/components/app/modals/clear-approved-origins/index.js create mode 100644 ui/app/components/app/modals/disconnect-account/disconnect-account.component.js create mode 100644 ui/app/components/app/modals/disconnect-account/disconnect-account.container.js create mode 100644 ui/app/components/app/modals/disconnect-account/index.js create mode 100644 ui/app/components/app/modals/disconnect-account/index.scss create mode 100644 ui/app/components/app/modals/disconnect-all/disconnect-all.component.js rename ui/app/components/app/modals/{clear-approved-origins/clear-approved-origins.container.js => disconnect-all/disconnect-all.container.js} (53%) create mode 100644 ui/app/components/app/modals/disconnect-all/index.js create mode 100644 ui/app/components/app/modals/disconnect-all/index.scss create mode 100644 ui/app/components/app/modals/new-account-modal/index.js create mode 100644 ui/app/components/app/modals/new-account-modal/index.scss create mode 100644 ui/app/components/app/modals/new-account-modal/new-account-modal.component.js create mode 100644 ui/app/components/app/modals/new-account-modal/new-account-modal.container.js create mode 100644 ui/app/components/app/permission-page-container/index.js create mode 100644 ui/app/components/app/permission-page-container/index.scss create mode 100644 ui/app/components/app/permission-page-container/permission-page-container-content/index.js create mode 100644 ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js create mode 100644 ui/app/components/app/permission-page-container/permission-page-container-header/index.js rename ui/app/components/app/{provider-page-container/provider-page-container-header/provider-page-container-header.component.js => permission-page-container/permission-page-container-header/permission-page-container-header.component.js} (58%) create mode 100644 ui/app/components/app/permission-page-container/permission-page-container.component.js create mode 100644 ui/app/components/app/permission-page-container/permission-page-container.container.js delete mode 100644 ui/app/components/app/provider-page-container/index.js delete mode 100644 ui/app/components/app/provider-page-container/index.scss delete mode 100644 ui/app/components/app/provider-page-container/provider-page-container-content/index.js delete mode 100644 ui/app/components/app/provider-page-container/provider-page-container-content/provider-page-container-content.component.js delete mode 100644 ui/app/components/app/provider-page-container/provider-page-container-content/provider-page-container-content.container.js delete mode 100644 ui/app/components/app/provider-page-container/provider-page-container-header/index.js delete mode 100644 ui/app/components/app/provider-page-container/provider-page-container.component.js create mode 100644 ui/app/components/ui/icon-with-fallback/icon-with-fallback.component.js create mode 100644 ui/app/components/ui/icon-with-fallback/index.js create mode 100644 ui/app/components/ui/icon-with-fallback/index.scss rename ui/app/css/itcss/components/pages/{provider-approval.scss => permission-approval.scss} (66%) create mode 100644 ui/app/pages/connected-sites/connected-sites.component.js create mode 100644 ui/app/pages/connected-sites/index.js create mode 100644 ui/app/pages/connected-sites/index.scss create mode 100644 ui/app/pages/permissions-connect/choose-account/choose-account.component.js create mode 100644 ui/app/pages/permissions-connect/choose-account/index.js create mode 100644 ui/app/pages/permissions-connect/choose-account/index.scss create mode 100644 ui/app/pages/permissions-connect/index.js create mode 100644 ui/app/pages/permissions-connect/index.scss create mode 100644 ui/app/pages/permissions-connect/permissions-connect-footer/index.js create mode 100644 ui/app/pages/permissions-connect/permissions-connect-footer/index.scss create mode 100644 ui/app/pages/permissions-connect/permissions-connect-footer/permissions-connect-footer.component.js create mode 100644 ui/app/pages/permissions-connect/permissions-connect-header/index.js create mode 100644 ui/app/pages/permissions-connect/permissions-connect-header/index.scss create mode 100644 ui/app/pages/permissions-connect/permissions-connect-header/permissions-connect-header.component.js create mode 100644 ui/app/pages/permissions-connect/permissions-connect.component.js create mode 100644 ui/app/pages/permissions-connect/permissions-connect.container.js delete mode 100644 ui/app/pages/provider-approval/index.js delete mode 100644 ui/app/pages/provider-approval/provider-approval.component.js delete mode 100644 ui/app/pages/provider-approval/provider-approval.container.js delete mode 100644 ui/app/pages/settings/connections-tab/connected-site-row/connected-site-row.component.js delete mode 100644 ui/app/pages/settings/connections-tab/connected-site-row/index.js delete mode 100644 ui/app/pages/settings/connections-tab/connected-site-row/index.scss delete mode 100644 ui/app/pages/settings/connections-tab/connections-tab.component.js delete mode 100644 ui/app/pages/settings/connections-tab/connections-tab.container.js delete mode 100644 ui/app/pages/settings/connections-tab/index.js delete mode 100644 ui/app/pages/settings/connections-tab/index.scss diff --git a/app/_locales/am/messages.json b/app/_locales/am/messages.json index bbb076896..1b9026d4c 100644 --- a/app/_locales/am/messages.json +++ b/app/_locales/am/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "የግላዊነት ኩነት አሁን በንቡር ነቅቷል" - }, "chartOnlyAvailableEth": { "message": "ቻርት የሚገኘው በ Ethereum አውታረ መረቦች ላይ ብቻ ነው።" }, - "confirmClear": { - "message": "የተፈቀዱ ድረ ገጾችን ለማጥራት እንደሚፈልጉ እርግጠኛ ነዎት?" - }, "contractInteraction": { "message": "የግንኙነት ተግባቦት" }, - "clearApprovalData": { - "message": "የግላዊነት ውሂብን አጥራ" - }, "reject": { "message": "አይቀበሉ" }, - "providerRequest": { + "likeToConnect": { "message": "$1ከመለያዎ ጋር ለመገናኘት ይፈልጋል" }, - "providerRequestInfo": { - "message": "ይህ ድረ ገጽ የእርስዎን መለያ ወቅታዊ አድራሻ ለማየት እየጠየቀ ነው። ምንጊዜም ግንኙነት የሚያደርጉባቸውን ድረ ገጾች የሚያምኗቸው መሆኑን ያረጋግጡ።" - }, "about": { "message": "ስለ" }, @@ -248,9 +236,6 @@ "connect": { "message": "ይገናኙ" }, - "connectRequest": { - "message": "የግንኙነት ጥያቄ" - }, "connectingTo": { "message": "ከ $1ጋር መገናኘት" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "ቀደም ሲል የተወሰነ Ether ካለዎት፣ በአዲሱ ቋትዎ Ether ለማግኘት ፈጣኑ መንገድ ቀጥተኛ ተቀማጭ ነው።" }, - "dismiss": { - "message": "አሰናብት" - }, "done": { "message": "ተጠናቅቋል" }, diff --git a/app/_locales/ar/messages.json b/app/_locales/ar/messages.json index 2a9451d61..e686d498c 100644 --- a/app/_locales/ar/messages.json +++ b/app/_locales/ar/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "يتم تمكين وضع الخصوصية الآن بشكل افتراضي" - }, "chartOnlyAvailableEth": { "message": "الرسم البياني متاح فقط على شبكات إيثيريوم." }, - "confirmClear": { - "message": "هل أنت متأكد من أنك تريد مسح المواقع المعتمدة؟" - }, "contractInteraction": { "message": "التفاعل على العقد" }, - "clearApprovalData": { - "message": "مسح بيانات الخصوصية" - }, "reject": { "message": "رفض" }, - "providerRequest": { + "likeToConnect": { "message": "يرغب $1 في الاتصال بحسابك" }, - "providerRequestInfo": { - "message": "يطلب هذا الموقع حق الوصول لعرض عنوان حسابك الحالي. تأكد دائماً من ثقتك في المواقع التي تتفاعل معها." - }, "about": { "message": "حول" }, @@ -248,9 +236,6 @@ "connect": { "message": "اتصال" }, - "connectRequest": { - "message": "طلب اتصال" - }, "connectingTo": { "message": "جارِ الاتصال بـ $1" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "إذا كان لديك بالفعل بعض الأثير، فإن أسرع طريقة للحصول على الأثير في محفظتك الجديدة عن طريق الإيداع المباشر." }, - "dismiss": { - "message": "رفض" - }, "done": { "message": "تم" }, diff --git a/app/_locales/bg/messages.json b/app/_locales/bg/messages.json index bd66c78c7..249e1c779 100644 --- a/app/_locales/bg/messages.json +++ b/app/_locales/bg/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Режимът на поверителност вече е активиран по подразбиране" - }, "chartOnlyAvailableEth": { "message": "Диаграмата е достъпна само в мрежи на Ethereum." }, - "confirmClear": { - "message": "Сигурни ли сте, че искате да изчистите одобрените уебсайтове?" - }, "contractInteraction": { "message": "Взаимодействие с договор" }, - "clearApprovalData": { - "message": "Изчистване на данните за поверителност" - }, "reject": { "message": "Отхвърляне" }, - "providerRequest": { + "likeToConnect": { "message": "$1 би искал да се свърже с вашия акаунт" }, - "providerRequestInfo": { - "message": "Този сайт иска достъп за преглед на адреса на текущия ви акаунт. Винаги се уверявайте, че се доверявате на сайтовете, с които взаимодействате." - }, "about": { "message": "Информация" }, @@ -248,9 +236,6 @@ "connect": { "message": "Свързване" }, - "connectRequest": { - "message": "Свържете заявка" - }, "connectingTo": { "message": "Свързване с $1" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "Ако вече имате някакъв етер, най-бързият начин да получите етер в новия си портфейл е чрез директен депозит." }, - "dismiss": { - "message": "Отхвърляне" - }, "done": { "message": "Готово" }, diff --git a/app/_locales/bn/messages.json b/app/_locales/bn/messages.json index 7580e8e53..ae36440da 100644 --- a/app/_locales/bn/messages.json +++ b/app/_locales/bn/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "গোপনীয়তার মোড এখন ডিফল্ট হিসাবে সক্রিয় করা আছে" - }, "chartOnlyAvailableEth": { "message": "শুধুমাত্র Ethereum নেটওয়ার্কগুলিতে চার্ট উপলভ্য। " }, - "confirmClear": { - "message": "আপনি কি অনুমোদিত ওয়েবসাইটগুলি মুছে পরিস্কার করার বিষয়ে নিশ্চিত?" - }, "contractInteraction": { "message": "কন্ট্র্যাক্ট বাক্যালাপ" }, - "clearApprovalData": { - "message": "গোপনীয়তার ডেটা মুছে পরিস্কার করুন" - }, "reject": { "message": "প্রত্যাখ্যান" }, - "providerRequest": { + "likeToConnect": { "message": "$1 আপনার অ্যাকাউন্টের সাথে সংযোগ করতে চায়" }, - "providerRequestInfo": { - "message": "এই সাইটটি আপনার বর্তমান অ্যাকাউন্টের ঠিকানা দেখার অ্যাক্সেসের জন্য অনুরোধ জানাচ্ছে। সবসময় নিশ্চিত হয়ে নেবেন যে আপনি যে সাইটের সাথে যোগাযোগ করছেন সেটি বিশ্বাসযোগ্য কিনা।" - }, "about": { "message": "সম্পর্কে" }, @@ -248,9 +236,6 @@ "connect": { "message": "সংযুক্ত করুন" }, - "connectRequest": { - "message": "সংযোগের অনুরোধ" - }, "connectingTo": { "message": " $1 এর সাথে সংযোগ করছে" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "আপনার ইতিমধ্যে কিছু ইথার থেকে থাকলে আপনার নতুন ওয়ালেটে ইথার পাওয়ার দ্রুততম উপায় হল সরাসরি জমা করা।" }, - "dismiss": { - "message": "খারিজ" - }, "done": { "message": "সম্পন্ন " }, diff --git a/app/_locales/ca/messages.json b/app/_locales/ca/messages.json index 07ec4c914..4c131ef09 100644 --- a/app/_locales/ca/messages.json +++ b/app/_locales/ca/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "El mode de privacitat ara està activat per defecte" - }, "chartOnlyAvailableEth": { "message": "Mostra només els disponibles a les xarxes Ethereum." }, - "confirmClear": { - "message": "Estàs segur que vols eliminar totes les pàgines web aprovades?" - }, "contractInteraction": { "message": "Contractar Interacció" }, - "clearApprovalData": { - "message": "Elimina les dades de privacitat" - }, "reject": { "message": "Rebutja" }, - "providerRequest": { + "likeToConnect": { "message": "a $1 li agradaria connectar-se al teu compte" }, - "providerRequestInfo": { - "message": "Aquesta pàgina està demanant accès a la teva adreça" - }, "about": { "message": "Informació" }, @@ -245,9 +233,6 @@ "connect": { "message": "Connecta" }, - "connectRequest": { - "message": "Sol·licitud de connexió" - }, "connectingTo": { "message": "Connectant a $1 " }, @@ -365,9 +350,6 @@ "directDepositEtherExplainer": { "message": "Si ja tens una mica d'Ether, la manera més ràpida de posar Ether al teu nou moneder és per dipòsit directe." }, - "dismiss": { - "message": "Omet" - }, "done": { "message": "Fet" }, @@ -687,7 +669,7 @@ "message": "Conectant-te a Ethereum i la web descentralitzada." }, "metamaskSeedWords": { - "message": "Frase de recuperació de Metamask" + "message": "Frase de recuperació de MetaMask" }, "metamaskVersion": { "message": "Versió MetaMask" diff --git a/app/_locales/cs/messages.json b/app/_locales/cs/messages.json index 452e5fb5e..9d04ae048 100644 --- a/app/_locales/cs/messages.json +++ b/app/_locales/cs/messages.json @@ -1,16 +1,7 @@ { - "confirmClear": { - "message": "Naozaj chcete vymazať schválené webové stránky?" - }, - "clearApprovalData": { - "message": "Jasné údaje o schválení" - }, "reject": { "message": "Odmítnout" }, - "providerRequestInfo": { - "message": "Níže uvedená doména se pokouší požádat o přístup k API Ethereum, aby mohla komunikovat s blokádou Ethereum. Před schválením přístupu Ethereum vždy zkontrolujte, zda jste na správném místě." - }, "account": { "message": "Účet" }, diff --git a/app/_locales/da/messages.json b/app/_locales/da/messages.json index d47cc3046..1c5fa4edb 100644 --- a/app/_locales/da/messages.json +++ b/app/_locales/da/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Privatlivstilstand er nu som udgangspunkt aktiveret" - }, "chartOnlyAvailableEth": { "message": "Skema kun tilgængeligt på Ethereum-netværk." }, - "confirmClear": { - "message": "Er du sikker på, at du vil rydde godkendte hjemmesider?" - }, "contractInteraction": { "message": "Kontraktinteraktion" }, - "clearApprovalData": { - "message": "Ryd fortrolighedsdata" - }, "reject": { "message": "Afvis" }, - "providerRequest": { + "likeToConnect": { "message": "$1 ønsker at forbinde til din konto" }, - "providerRequestInfo": { - "message": "Denne side anmoder om at se din nuværende kontoadresse. Sørg altid for, at du stoler på de sider du interagerer med." - }, "about": { "message": "Om" }, @@ -248,9 +236,6 @@ "connect": { "message": "Få forbindelse" }, - "connectRequest": { - "message": "Tilslutningsanmodning" - }, "connectingTo": { "message": "Forbinder til $1" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "Hvis du allerede har Ether, er den hurtigste måde at få Ether i din nye tegnebog ved direkte indbetaling." }, - "dismiss": { - "message": "Luk" - }, "done": { "message": "Færdig" }, diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index 5ea773ba3..f964d0c2d 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Der Datenschutzmodus ist jetzt standardmäßig aktiviert" - }, "chartOnlyAvailableEth": { "message": "Die Grafik ist nur in Ethereum-Netzwerken verfügbar." }, - "confirmClear": { - "message": "Möchten Sie die genehmigten Websites wirklich löschen?" - }, "contractInteraction": { "message": "Vertragsinteraktion" }, - "clearApprovalData": { - "message": "Genehmigungsdaten löschen" - }, "reject": { "message": "Ablehnen" }, - "providerRequest": { + "likeToConnect": { "message": "$1 möchte sich mit deinem Account verbinden" }, - "providerRequestInfo": { - "message": "Diese Website fordert Zugriff auf Ihre aktuelle Kontoadresse. Stellen Sie immer sicher, dass Sie den Websites vertrauen, mit denen Sie interagieren." - }, "about": { "message": "Über" }, @@ -236,9 +224,6 @@ "connect": { "message": "Verbinden" }, - "connectRequest": { - "message": "Verbindungsanfrage" - }, "connectingTo": { "message": "Verbindung mit $1 wird hergestellt" }, @@ -353,9 +338,6 @@ "directDepositEtherExplainer": { "message": "Wenn du bereits Ether besitzt, ist die sofortige Einzahlung die schnellste Methode Ether in deine neue Wallet zu bekommen." }, - "dismiss": { - "message": "Schließen" - }, "done": { "message": "Fertig" }, diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index 9d6725632..6f35b1447 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Η Λειτουργία Απορρήτου είναι πλέον ενεργοποιημένη από προεπιλογή" - }, "chartOnlyAvailableEth": { "message": "Το διάγραμμα είναι διαθέσιμο μόνο σε δίκτυα Ethereum." }, - "confirmClear": { - "message": "Είστε βέβαιοι ότι θέλετε να διαγράψετε τους εγκεκριμένους ιστότοπους;" - }, "contractInteraction": { "message": "Αλληλεπίδραση Σύμβασης" }, - "clearApprovalData": { - "message": "Εκκαθάριση Δεδομένων Απορρήτου" - }, "reject": { "message": "Απόρριψη" }, - "providerRequest": { + "likeToConnect": { "message": "Αίτημα σύνδεσης στον λογαριασμό σας από $1" }, - "providerRequestInfo": { - "message": "Ο ιστότοπος ζητά πρόσβαση για προβολή της τρέχουσας διεύθυνσης του λογαριασμού σας. Να σιγουρεύεστε πάντα ότι εμπιστεύεστε τους ιστότοπους με τους οποίους αλληλεπιδράτε." - }, "about": { "message": "Σχετικά με" }, @@ -245,9 +233,6 @@ "connect": { "message": "Σύνδεση" }, - "connectRequest": { - "message": "Αίτημα Σύνδεσης" - }, "connectingTo": { "message": "Σύνδεση με $1" }, @@ -365,9 +350,6 @@ "directDepositEtherExplainer": { "message": "Αν έχετε ήδη κάποια Ether, ο πιο γρήγορος τρόπος για να πάρετε τα Ether στο νέο σας πορτοφόλι με άμεση κατάθεση." }, - "dismiss": { - "message": "Παράβλεψη" - }, "done": { "message": "Τέλος" }, diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 2afe8e0c3..b61349894 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -14,47 +14,33 @@ "showIncomingTransactionsDescription": { "message": "Select this to use Etherscan to show incoming transactions in the transactions list" }, + "cancelledConnectionWithMetaMask": { + "message": "Cancelled Connection With MetaMask" + }, "chartOnlyAvailableEth": { "message": "Chart only available on Ethereum networks." }, - "confirmClear": { - "message": "Are you sure you want to clear approved websites?" - }, - "connections": { - "message": "Connections" - }, - "connectionsSettingsDescription": { - "message": "Sites allowed to read your accounts" - }, - "addSite": { - "message": "Add Site" + "connectedSites": { + "message": "Connected Sites" }, - "addSiteDescription": { - "message": "Manually add a site to allow it access to your accounts, useful for older dapps" + "connectingWithMetaMask": { + "message": "Connecting With MetaMask..." }, - "connected": { - "message": "Connected" + "connectTo": { + "message": "Connect to $1", + "description": "$1 is the name/origin of a site/dapp that the user can connect to metamask" }, - "connectedDescription": { - "message": "The list of sites allowed access to your addresses" - }, - "privacyModeDefault": { - "message": "Privacy Mode is now enabled by default" + "chooseAnAcount": { + "message": "Choose an account" }, "contractInteraction": { "message": "Contract Interaction" }, - "clearApprovalData": { - "message": "Remove all sites" - }, "reject": { "message": "Reject" }, - "providerRequest": { - "message": "$1 would like to connect to your account" - }, - "providerRequestInfo": { - "message": "This site is requesting access to view your current account address. Always make sure you trust the sites you interact with." + "redirectingBackToDapp": { + "message": "Redirecting back to dapp..." }, "about": { "message": "About" @@ -305,9 +291,6 @@ "connect": { "message": "Connect" }, - "connectRequest": { - "message": "Connect Request" - }, "connectingTo": { "message": "Connecting to $1" }, @@ -431,14 +414,36 @@ "details": { "message": "Details" }, + "disconnectAccount": { + "message": "Disconnect account" + }, + "disconnectAll": { + "message": "Disconnect All" + }, + "disconnectAllModalDescription": { + "message": "Are you sure? You will be disconnected from all sites on all accounts." + }, + "disconnectAccountModalDescription": { + "message": "Are you sure? Your account (\"$1\") will be disconnected from this site." + }, + "disconnectAccountQuestion": { + "message": "Disconnect account?" + }, + "disconnectFromThisAccount": { + "message": "Disconnect from this account?" + }, + "disconnectAllAccountsQuestion": { + "message": "Disconnect all accounts?" + }, "directDepositEther": { "message": "Directly Deposit Ether" }, "directDepositEtherExplainer": { "message": "If you already have some Ether, the quickest way to get Ether in your new wallet by direct deposit." }, - "dismiss": { - "message": "Dismiss" + "domainLastConnect": { + "message": "Last Connected: $1", + "description": "$1 is the date at which the user was last connected to a given domain" }, "done": { "message": "Done" @@ -500,6 +505,13 @@ "endOfFlowMessage10": { "message": "All Done" }, + "extensionId": { + "message": "Extension ID: $1", + "description": "$1 is a string of random letters that are the id of another extension connecting to MetaMask" + }, + "externalExtension": { + "message": "External Extension" + }, "onboardingReturnNotice": { "message": "\"$1\" will close this tab and direct back to $2", "description": "Return the user to the site that initiated onboarding" @@ -733,9 +745,15 @@ "max": { "message": "Max" }, + "lastConnected": { + "message": "Last Connected" + }, "learnMore": { "message": "Learn more" }, + "learnAboutRisks": { + "message": "Learn about the risks here." + }, "ledgerAccountRestriction": { "message": "You need to make use your last account before you can add a new one." }, @@ -745,6 +763,10 @@ "likeToAddTokens": { "message": "Would you like to add these tokens?" }, + "likeToConnect": { + "message": "$1 would like to connect to your MetaMask account", + "description": "$1 is the name/url of a site/dapp asking to connect to MetaMask" + }, "links": { "message": "Links" }, @@ -876,6 +898,9 @@ "rpcUrl": { "message": "New RPC URL" }, + "onlyConnectTrust": { + "message": "Only connect with sites you trust." + }, "optionalChainId": { "message": "ChainID (optional)" }, @@ -1078,6 +1103,9 @@ "readyToConnect": { "message": "Ready to Connect?" }, + "revokeInPermissions": { + "message": "* You can view and revoke permissions in MetaMask settings." + }, "rinkeby": { "message": "Rinkeby Test Network" }, @@ -1283,6 +1311,9 @@ "storePhrase": { "message": "Store this phrase in a password manager like 1Password." }, + "submit": { + "message": "Submit" + }, "submitted": { "message": "Submitted" }, @@ -1331,6 +1362,14 @@ "testFaucet": { "message": "Test Faucet" }, + "thisWillAllow": { + "message": "This will allow $1 to:", + "description": "$1 is the name or domain of a site/dapp that is requesting permissions" + }, + "thisWillAllowExternalExtension": { + "message": "This will allow an external extension with id $1 to:", + "description": "$1 is a string of random letters that are the id of another extension connecting to MetaMask" + }, "thisWillCreate": { "message": "This will create a new wallet and seed phrase" }, @@ -1343,6 +1382,10 @@ "toWithColon": { "message": "To:" }, + "toConnectWith": { + "message": "To connect with $1", + "description": "$1 is the name or domain of a site/dapp that asking to connect with MetaMask" + }, "toETHviaShapeShift": { "message": "$1 to ETH via ShapeShift", "description": "system will fill in deposit type in start of message" diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index 5aeb4ebe0..f64105f26 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Modo Privado está activado ahora por defecto" - }, "chartOnlyAvailableEth": { "message": "Tabla solo disponible en redes Ethereum." }, - "confirmClear": { - "message": "¿Seguro que quieres borrar los sitios web aprobados?" - }, "contractInteraction": { "message": "Interacción con contrato" }, - "clearApprovalData": { - "message": "Borrar datos de aprobación" - }, "reject": { "message": "Rechazar" }, - "providerRequest": { + "likeToConnect": { "message": "$1 quisiera conectar con tu cuenta" }, - "providerRequestInfo": { - "message": "El dominio que se muestra a continuación intenta solicitar acceso a la API Ethereum para que pueda interactuar con la blockchain de Ethereum. Siempre verifique que esté en el sitio correcto antes de aprobar el acceso Ethereum." - }, "about": { "message": "Acerca" }, @@ -205,9 +193,6 @@ "connect": { "message": "Conectar" }, - "connectRequest": { - "message": "Petición para conectar" - }, "connectingTo": { "message": "Conectánodse a $1" }, @@ -325,9 +310,6 @@ "directDepositEtherExplainer": { "message": "Si posees Ether, la forma más rápida de transferirlo a tu nueva billetera es depositándolo directamente" }, - "dismiss": { - "message": "Descartar" - }, "done": { "message": "Completo" }, diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index e75b4c27b..0645b0eaf 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "El modo de privacidad está habilitado de manera predeterminada" - }, "chartOnlyAvailableEth": { "message": "Chart está disponible únicamente en las redes de Ethereum." }, - "confirmClear": { - "message": "¿Estás seguro de que deseas borrar los sitios web aprobados?" - }, "contractInteraction": { "message": "Interacción contractual" }, - "clearApprovalData": { - "message": "Borrar datos de privacidad" - }, "reject": { "message": "Rechazar" }, - "providerRequest": { + "likeToConnect": { "message": "$1 desea conectarse a tu cuenta" }, - "providerRequestInfo": { - "message": "Este sitio está solicitando acceso para ver la dirección de tu cuenta corriente. Asegúrate siempre de que confías en los sitios con los que interactúas." - }, "about": { "message": "Acerca de" }, @@ -245,9 +233,6 @@ "connect": { "message": "Conectar" }, - "connectRequest": { - "message": "Solicitud de conexión" - }, "connectingTo": { "message": "Conexión con $1" }, @@ -365,9 +350,6 @@ "directDepositEtherExplainer": { "message": "Si ya tienes algunos Ethers, la forma más rápida de ingresarlos en tu nueva billetera es a través de un depósito directo." }, - "dismiss": { - "message": "Rechazar" - }, "done": { "message": "Listo" }, diff --git a/app/_locales/et/messages.json b/app/_locales/et/messages.json index 3b5f4ced8..ad64a32cb 100644 --- a/app/_locales/et/messages.json +++ b/app/_locales/et/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Privaatsusrežiim on nüüd vaikimisi lubatud" - }, "chartOnlyAvailableEth": { "message": "Tabel on saadaval vaid Ethereumi võrkudes." }, - "confirmClear": { - "message": "Kas soovite kindlasti kinnitatud veebisaidid kustutada?" - }, "contractInteraction": { "message": "Lepingu suhtlus" }, - "clearApprovalData": { - "message": "Tühjenda privaatsusandmed" - }, "reject": { "message": "Lükka tagasi" }, - "providerRequest": { + "likeToConnect": { "message": "$1 soovib teie kontoga ühenduse luua" }, - "providerRequestInfo": { - "message": "See sait taotleb juurdepääsu teie praeguse konto aadressi vaatamiseks. Veenduge alati, et usaldate saite, millega suhtlete." - }, "about": { "message": "Teave" }, @@ -248,9 +236,6 @@ "connect": { "message": "Ühendamine" }, - "connectRequest": { - "message": "Ühenduse taotlus" - }, "connectingTo": { "message": "Ühenduse loomine $1" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "Kui teil on juba veidi eetrit, on kiirem viis eetri rahakotti saamiseks otsene sissemakse." }, - "dismiss": { - "message": "Loobu" - }, "done": { "message": "Valmis" }, @@ -420,7 +402,7 @@ "message": "Kui teil on küsimusi või näete midagi kahtlast, kirjutage meile support@metamask.io." }, "endOfFlowMessage8": { - "message": "Metamask ei saa teie seemnefraasi taastada. Lisateave." + "message": "MetaMask ei saa teie seemnefraasi taastada. Lisateave." }, "endOfFlowMessage9": { "message": "Lisateave." @@ -1180,7 +1162,7 @@ "message": "Saate sünkroonida oma kontod ja teabe oma mobiiliseadmega. Avage MetaMaski mobiilirakendus, avage \"Settings\" (Seaded) ja puudutage valikut \"Sync from Browser Extension\" (Sünkroonimine lehitseja laiendusest)" }, "syncWithMobileDescNewUsers": { - "message": "Järgige Metamaski mobiilirakenduse esmakordsel avamisel telefonis esitatud samme." + "message": "Järgige MetaMaski mobiilirakenduse esmakordsel avamisel telefonis esitatud samme." }, "syncWithMobileScanThisCode": { "message": "Skanneerige see kood MetaMaski mobiilirakendusega" diff --git a/app/_locales/fa/messages.json b/app/_locales/fa/messages.json index 6d9741344..5be054e7c 100644 --- a/app/_locales/fa/messages.json +++ b/app/_locales/fa/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "وضعیت محرمیت حالا بصورت خودکار فعال است" - }, "chartOnlyAvailableEth": { "message": "تنها قابل دسترس را در شبکه های ایتریوم جدول بندی نمایید" }, - "confirmClear": { - "message": "آیا مطمئن هستید تا وب سایت های تصدیق شده را حذف کنید؟" - }, "contractInteraction": { "message": "تعامل قرارداد" }, - "clearApprovalData": { - "message": "حذف اطلاعات حریم خصوصی" - }, "reject": { "message": "عدم پذیرش" }, - "providerRequest": { + "likeToConnect": { "message": "1$1 میخواهید تا با حساب تان وصل شوید" }, - "providerRequestInfo": { - "message": "این سایت در حال درخواست دسترسی است تا آدرس فعلی حساب تان را مشاهده نماید. همیشه متوجه باشید که بالای سایتی که با آن معامله میکنید، اعتماد دارید یا خیر." - }, "about": { "message": "درباره" }, @@ -248,9 +236,6 @@ "connect": { "message": "اتصال" }, - "connectRequest": { - "message": "درخواست اتصال" - }, "connectingTo": { "message": "در حال اتصال به 1$1" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "در صورتیکه شما کدام ایتر داشته باشید، سریعترین روش برای گرفتن ایتر در کیف جدید تان توسط پرداخت مستقیم." }, - "dismiss": { - "message": "لغو کردن" - }, "done": { "message": "تمام" }, diff --git a/app/_locales/fi/messages.json b/app/_locales/fi/messages.json index 352600b26..56f48a6fd 100644 --- a/app/_locales/fi/messages.json +++ b/app/_locales/fi/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Yksityisyystila on nyt oletusarvoisesti käytössä" - }, "chartOnlyAvailableEth": { "message": "Kaavio saatavilla vain Ethereum-verkoissa." }, - "confirmClear": { - "message": "Haluatko varmasti tyhjentää hyväksytyt verkkosivustot?" - }, "contractInteraction": { "message": "Sopimustoiminta" }, - "clearApprovalData": { - "message": "Tyhjennä yksityisyystiedot" - }, "reject": { "message": "Hylkää" }, - "providerRequest": { + "likeToConnect": { "message": "$1 haluaisi yhdistää tiliisi" }, - "providerRequestInfo": { - "message": "Tämä sivusto pyytää oikeuksia nähdä nykyisen tiliosoitteesi. Varmista aina, että luotat sivustoihin, joiden kanssa toimit." - }, "about": { "message": "Tietoja asetuksista" }, @@ -245,9 +233,6 @@ "connect": { "message": "Muodosta yhteys" }, - "connectRequest": { - "message": "Yhdistämispyyntö" - }, "connectingTo": { "message": "Yhdistetään summaan $1 " }, @@ -365,9 +350,6 @@ "directDepositEtherExplainer": { "message": "Jos sinulla on jo etheriä, nopein tapa hankkia etheriä uuteen lompakkoosi on suoratalletus." }, - "dismiss": { - "message": "Piilota" - }, "done": { "message": "Valmis" }, diff --git a/app/_locales/fil/messages.json b/app/_locales/fil/messages.json index 8c453bca5..cd9b31234 100644 --- a/app/_locales/fil/messages.json +++ b/app/_locales/fil/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Naka-enable ang Privacy Mode bilang default" - }, "chartOnlyAvailableEth": { "message": "Available lang ang chart sa mga Ethereum network." }, - "confirmClear": { - "message": "Sigurado ka bang gusto mong i-clear ang mga inaprubahang website?" - }, "contractInteraction": { "message": "Paggamit sa Contract" }, - "clearApprovalData": { - "message": "I-clear ang Privacy Data" - }, "reject": { "message": "Tanggihan" }, - "providerRequest": { + "likeToConnect": { "message": "Gusto ng $1 na kumonekta sa iyong account" }, - "providerRequestInfo": { - "message": "Humihiling ng access ang site na ito na tingnan ang kasalukuyan mong account address. Palaging tiyaking pinagkakatiwalaan mo ang mga site na pinupuntahan mo." - }, "about": { "message": "Tungkol sa" }, @@ -338,9 +326,6 @@ "directDepositEtherExplainer": { "message": "Kung mayroon ka nang Ether, ang pinakamabilis na paraan para magkaroon ng Ether sa iyong bagong wallet ay sa pamamagitan ng direkang deposito." }, - "dismiss": { - "message": "Balewalain" - }, "done": { "message": "Tapos na" }, diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index ddcddb6be..1fc2a600d 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Le mode conversation privée est maintenant activé par défaut" - }, "chartOnlyAvailableEth": { "message": "Tableau disponible uniquement sur les réseaux Ethereum." }, - "confirmClear": { - "message": "Êtes-vous sûr de vouloir supprimer les sites Web approuvés?" - }, "contractInteraction": { "message": "Interaction avec un contrat" }, - "clearApprovalData": { - "message": "Effacer les données d'approbation" - }, "reject": { "message": "Rejeter" }, - "providerRequest": { + "likeToConnect": { "message": "$1 voudrait se connecter à votre compte" }, - "providerRequestInfo": { - "message": "Le domaine répertorié ci-dessous tente de demander l'accès à l'API Ethereum pour pouvoir interagir avec la chaîne de blocs Ethereum. Vérifiez toujours que vous êtes sur le bon site avant d'autoriser l'accès à Ethereum." - }, "about": { "message": "À propos" }, @@ -236,9 +224,6 @@ "connect": { "message": "Connecter" }, - "connectRequest": { - "message": "Demande de connexion" - }, "connectingTo": { "message": "Connexion à $1" }, @@ -356,9 +341,6 @@ "directDepositEtherExplainer": { "message": "Si vous avez déjà de l'Ether, le moyen le plus rapide d'obtenir des Ether dans votre nouveau portefeuille est par dépôt direct." }, - "dismiss": { - "message": "Ignorer" - }, "done": { "message": "Terminé" }, diff --git a/app/_locales/gu/messages.json b/app/_locales/gu/messages.json index 39f5ab26c..d04514fd9 100644 --- a/app/_locales/gu/messages.json +++ b/app/_locales/gu/messages.json @@ -54,9 +54,6 @@ "details": { "message": "વિગતો" }, - "dismiss": { - "message": "કાઢી નાખો" - }, "done": { "message": "થઈ ગયું" }, diff --git a/app/_locales/he/messages.json b/app/_locales/he/messages.json index 62e69e1d5..d0f92848c 100644 --- a/app/_locales/he/messages.json +++ b/app/_locales/he/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "מצב פרטיות זמין עכשיו כברירת מחדל" - }, "chartOnlyAvailableEth": { "message": "טבלה זמינה רק ברשתות אתריום." }, - "confirmClear": { - "message": "הנך בטוח/ה כי ברצונך למחוק אתרים שאושרו?" - }, "contractInteraction": { "message": "אינטראקציית חוזה" }, - "clearApprovalData": { - "message": "נקה נתוני פרטיות" - }, "reject": { "message": "דחה" }, - "providerRequest": { + "likeToConnect": { "message": "$1 מבקש להתחבר לחשבון שלך" }, - "providerRequestInfo": { - "message": "אתר זה מבקש גישה לצפייה בכתובת החשבון הנוכחית שלך. יש לוודא תמיד כי הנך בוטח/ת באתרים עמם הנך מתקשר/ת." - }, "about": { "message": "מידע כללי" }, @@ -248,9 +236,6 @@ "connect": { "message": "התחברות" }, - "connectRequest": { - "message": "חבר/י בקשה" - }, "connectingTo": { "message": "מתחבר ל- $1 " }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "אם כבר יש ברשותך את'ר (Ether) , הדרך המהירה ביותר להכניס את'ר לארנק החדש שלך היא באמצעות הפקדה ישירה." }, - "dismiss": { - "message": "סגור" - }, "done": { "message": "סיום" }, diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index 92fa40af6..51aa21b84 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "गोपनीय मोड अब डिफ़ॉल्ट रूप से सक्षम है" - }, "chartOnlyAvailableEth": { "message": "केवल ईथरअम नेटवर्क पर उपलब्ध चार्ट।" }, - "confirmClear": { - "message": "क्या आप वाकई स्वीकृत वेबसाइटों को क्लियर करना चाहते हैं?" - }, "contractInteraction": { "message": "कॉन्ट्रैक्ट की बातचीत" }, - "clearApprovalData": { - "message": "गोपनीयता डेटा रिक्त करें" - }, "reject": { "message": "अस्‍वीकार करें" }, - "providerRequest": { + "likeToConnect": { "message": "$1 आपके खाते से कनेक्ट होता चाहता हैं" }, - "providerRequestInfo": { - "message": "यह साइट आपके वर्तमान खाते का पता देखने के लिए एक्सेस का अनुरोध कर रही है। हमेशा सुनिश्चित करें कि आप जिन साइटों पर जाते हैं वे विश्वसनीय हैं।" - }, "about": { "message": "इसके बारे में" }, @@ -248,9 +236,6 @@ "connect": { "message": "कनेक्ट करें" }, - "connectRequest": { - "message": "संपर्क अनुरोध" - }, "connectingTo": { "message": "$1 से कनेक्ट हो रहा है" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "यदि आपके पास पहले से ही कुछ Ether हैं, तो अपने नए वॉलेट में Ether पाने का सबसे तेज़ तरीका सीधे जमा करना है।" }, - "dismiss": { - "message": "खारिज करें" - }, "done": { "message": "पूर्ण" }, diff --git a/app/_locales/hn/messages.json b/app/_locales/hn/messages.json index 1dd4fd117..800907798 100644 --- a/app/_locales/hn/messages.json +++ b/app/_locales/hn/messages.json @@ -1,19 +1,10 @@ { - "confirmClear": { - "message": "क्या आप वाकई अनुमोदित वेबसाइटों को साफ़ करना चाहते हैं?" - }, - "clearApprovalData": { - "message": "अनुमोदन डेटा साफ़ करें" - }, "approve": { "message": "मंजूर" }, "reject": { "message": "अस्वीकार" }, - "providerRequestInfo": { - "message": "नीचे सूचीबद्ध डोमेन वेब 3 एपीआई तक पहुंच का अनुरोध करने का प्रयास कर रहा है ताकि यह एथेरियम ब्लॉकचेन से बातचीत कर सके। वेब 3 एक्सेस को मंजूरी देने से पहले हमेशा सही जांच करें कि आप सही साइट पर हैं।" - }, "account": { "message": "खाता" }, diff --git a/app/_locales/hr/messages.json b/app/_locales/hr/messages.json index 2e224f36f..57b4b0d4c 100644 --- a/app/_locales/hr/messages.json +++ b/app/_locales/hr/messages.json @@ -1,19 +1,10 @@ { - "privacyModeDefault": { - "message": "Način se Privatnost sada zadano omogućava" - }, "chartOnlyAvailableEth": { "message": "Grafikon je dostupan samo na mrežama Ethereum." }, - "confirmClear": { - "message": "Sigurno želite očistiti odobrena mrežna mjesta?" - }, "contractInteraction": { "message": "Ugovorna interakcija" }, - "clearApprovalData": { - "message": "Očisti podatke o privatnosti" - }, "appName": { "message": "MetaMask", "description": "The name of the application" @@ -21,12 +12,9 @@ "reject": { "message": "Odbaci" }, - "providerRequest": { + "likeToConnect": { "message": "Korisnik $1 želi se povezati na vaš račun" }, - "providerRequestInfo": { - "message": "Na ovom se mjestu zahtijeva pristup za pregledavanje vaše trenutačne adrese računa. Uvijek pazite da vjerujete mrežnim mjestima s kojima rukujete." - }, "about": { "message": "O opcijama" }, @@ -248,9 +236,6 @@ "connect": { "message": "Povežite se" }, - "connectRequest": { - "message": "Zahtjev za povezivanjem" - }, "connectingTo": { "message": "Povezivanje na $1" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "Ako imate nešto Ethera, najbrži je način prebacivanja Ethera u vaš novi novčanik izravan polog." }, - "dismiss": { - "message": "Odbaci" - }, "done": { "message": "Gotovo" }, diff --git a/app/_locales/ht/messages.json b/app/_locales/ht/messages.json index 472409017..dd63dce0c 100644 --- a/app/_locales/ht/messages.json +++ b/app/_locales/ht/messages.json @@ -1,13 +1,4 @@ { - "confirmClear": { - "message": "Èske ou sèten ou vle klè sitwèb apwouve?" - }, - "clearApprovalData": { - "message": "Klè Done sou vi prive" - }, - "providerRequestInfo": { - "message": "Domèn ki nan lis anba a ap mande pou jwenn aksè a blòkchou Ethereum ak pou wè kont ou ye kounye a. Toujou double tcheke ke ou sou sit ki kòrèk la anvan apwouve aksè." - }, "accessingYourCamera": { "message": "Aksè a Kamera" }, diff --git a/app/_locales/hu/messages.json b/app/_locales/hu/messages.json index f1554299b..33b8dac32 100644 --- a/app/_locales/hu/messages.json +++ b/app/_locales/hu/messages.json @@ -1,19 +1,10 @@ { - "privacyModeDefault": { - "message": "Az adatvédelmi mód mostantól alapbeállításként engedélyezve van" - }, "chartOnlyAvailableEth": { "message": "A diagram csak Ethereum hálózatokon érhető el" }, - "confirmClear": { - "message": "Biztosan törölni szeretnéd a jóváhagyott weboldalakat?" - }, "contractInteraction": { "message": "Szerződéses interakció" }, - "clearApprovalData": { - "message": "Adatvédelmi adatok törlése" - }, "appName": { "message": "MetaMask", "description": "The name of the application" @@ -21,12 +12,9 @@ "reject": { "message": "Elutasítás" }, - "providerRequest": { + "likeToConnect": { "message": "$1 szeretne kapcsolódni az ön fiókjához" }, - "providerRequestInfo": { - "message": "A webhely hozzáférést kér az ön jelenlegi fiókcímének megtekintéséhez. Mindig győződjön meg arról, hogy megbízható webhellyel létesít kapcsolatot." - }, "about": { "message": "Névjegy" }, @@ -248,9 +236,6 @@ "connect": { "message": "Csatlakozás" }, - "connectRequest": { - "message": "Csatlakozási kérelem" - }, "connectingTo": { "message": "Kapcsolódás: $1" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "Amennyiben már rendelkezik némi Ether-rel, a közvetlen letéttel gyorsan elhelyezheti azt új pénztárcájában." }, - "dismiss": { - "message": "Elvetés" - }, "done": { "message": "Kész" }, diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index eaddf42eb..874ca4576 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -1,19 +1,10 @@ { - "privacyModeDefault": { - "message": "Modus Privasi kini aktif secara default" - }, "chartOnlyAvailableEth": { "message": "Grafik hanya tersedia pada jaringan Ethereum." }, - "confirmClear": { - "message": "Yakin ingin mengosongkan website yang disetujui?" - }, "contractInteraction": { "message": "Interaksi Kontrak" }, - "clearApprovalData": { - "message": "Bersihkan Data Privasi" - }, "appName": { "message": "MetaMask", "description": "The name of the application" @@ -21,12 +12,9 @@ "reject": { "message": "Tolak" }, - "providerRequest": { + "likeToConnect": { "message": "$1 ingin menghubungkan ke akun Anda" }, - "providerRequestInfo": { - "message": "Situs ini meminta akses untuk melihat alamat akun Anda saat ini. Selalu pastikan bahwa Anda bisa mempercayai situs yang berinteraksi dengan Anda." - }, "about": { "message": "Tentang" }, @@ -248,9 +236,6 @@ "connect": { "message": "Sambungkan" }, - "connectRequest": { - "message": "Permintaan Sambungan" - }, "connectingTo": { "message": "Menghubungkan ke $1" }, @@ -362,9 +347,6 @@ "directDepositEtherExplainer": { "message": "Jika Anda sudah memiliki Ether, cara tercepat mendapatkan Ether di dompet baru lewat deposit langsung." }, - "dismiss": { - "message": "Tutup" - }, "done": { "message": "Selesai" }, diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index e51b5a477..213407a3b 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "La modalità privacy è ora abilitata per impostazione predefinita" - }, "chartOnlyAvailableEth": { "message": "Grafico disponibile solo per le reti Ethereum." }, - "confirmClear": { - "message": "Sei sicuro di voler cancellare i siti Web approvati?" - }, "contractInteraction": { "message": "Interazione Contratto" }, - "clearApprovalData": { - "message": "Cancella i dati di approvazione" - }, "reject": { "message": "Annulla" }, - "providerRequest": { + "likeToConnect": { "message": "$1 vorrebbe connettersi al tuo account" }, - "providerRequestInfo": { - "message": "Il dominio elencato di seguito sta tentando di richiedere l'accesso all'API Ethereum in modo che possa interagire con la blockchain di Ethereum. Controlla sempre di essere sul sito corretto prima di approvare l'accesso a Ethereum." - }, "about": { "message": "Informazioni" }, @@ -227,9 +215,6 @@ "connect": { "message": "Connetti" }, - "connectRequest": { - "message": "Richiesta Connessione" - }, "connectingTo": { "message": "Connessione in corso a $1" }, @@ -347,9 +332,6 @@ "directDepositEtherExplainer": { "message": "Se possiedi già degli Ether, questa è la via più veloce per aggiungere Ether al tuo portafoglio con un deposito diretto." }, - "dismiss": { - "message": "Ignora" - }, "done": { "message": "Finito" }, @@ -1343,24 +1325,6 @@ "zeroGasPriceOnSpeedUpError": { "message": "Prezzo del gas maggiore di zero" }, - "connections": { - "message": "Connessioni" - }, - "connectionsSettingsDescription": { - "message": "Siti autorizzati ad accedere ai tuoi accounts" - }, - "addSite": { - "message": "Aggiungi Sito" - }, - "addSiteDescription": { - "message": "Aggiungi un sito autorizzato ad accedere ai tuoi accounts, utile per dapps obsolete" - }, - "connected": { - "message": "Connesso" - }, - "connectedDescription": { - "message": "La lista di siti web autorizzati ad accedere ai tuoi indirizzi" - }, "contacts": { "message": "Contatti" }, diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index 4967db8a6..18dfb068e 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "プライバシーモードがデフォルトで有効になりました" - }, "chartOnlyAvailableEth": { "message": "チャートはEthereumネットワークでのみ利用可能です。" }, - "confirmClear": { - "message": "承認されたウェブサイトをクリアしてもよろしいですか?" - }, "contractInteraction": { "message": "コントラクトへのアクセス" }, - "clearApprovalData": { - "message": "承認データのクリア" - }, "reject": { "message": "拒否" }, - "providerRequest": { + "likeToConnect": { "message": "$1 はあなたのアカウントにアクセスしようとしています。" }, - "providerRequestInfo": { - "message": "下記のドメインは、Ethereumブロックチェーンとやり取りできるようにEthereum APIへのアクセスをリクエストしようとしています。 Web3アクセスを承認する前に、正しいサイトにいることを常に確認してください。" - }, "aboutSettingsDescription": { "message": "バージョンやサポート、問合せ先など" }, @@ -84,7 +72,7 @@ "message": "推奨トークンを追加" }, "addAcquiredTokens": { - "message": "Metamaskで獲得したトークンを追加する" + "message": "MetaMaskで獲得したトークンを追加する" }, "amount": { "message": "金額" diff --git a/app/_locales/kn/messages.json b/app/_locales/kn/messages.json index e4c8b38fe..7f3dd0f17 100644 --- a/app/_locales/kn/messages.json +++ b/app/_locales/kn/messages.json @@ -1,19 +1,10 @@ { - "privacyModeDefault": { - "message": "ಗೌಪ್ಯತೆ ಮೋಡ್ ಅನ್ನು ಡೀಫಾಲ್ಟ್‌ ಆಗಿ ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ" - }, "chartOnlyAvailableEth": { "message": "ಎಥೆರಿಯಮ್ ನೆಟ್‌ವರ್ಕ್‌ಗಳಲ್ಲಿ ಮಾತ್ರವೇ ಚಾರ್ಟ್‌ಗಳು ಲಭ್ಯವಿರುತ್ತವೆ." }, - "confirmClear": { - "message": "ನೀವು ಅನುಮೋದಿಸಿದ ವೆಬ್‌‌ಸೈಟ್‌ಗಳನ್ನು ತೆರವುಗೊಳಿಸಲು ಬಯಸುವಿರಾ?" - }, "contractInteraction": { "message": "ಒಪ್ಪಂದದ ಸಂವಹನ" }, - "clearApprovalData": { - "message": "ಗೌಪ್ಯತೆ ಡೇಟಾವನ್ನು ತೆರವುಗೊಳಿಸಿ" - }, "appName": { "message": "MetaMask", "description": "The name of the application" @@ -21,12 +12,9 @@ "reject": { "message": "ತಿರಸ್ಕರಿಸಿ" }, - "providerRequest": { + "likeToConnect": { "message": "$1 ನಿಮ್ಮ ಖಾತೆಗೆ ಸಂಪರ್ಕಿಸಲು ಬಯಸುತ್ತಿದೆ" }, - "providerRequestInfo": { - "message": "ಈ ಸೈಟ್ ನಿಮ್ಮ ಪ್ರಸ್ತುತ ಖಾತೆ ವಿಳಾಸವನ್ನು ವೀಕ್ಷಿಸಲು ಪ್ರವೇಶವನ್ನು ವಿನಂತಿಸುತ್ತಿದೆ. ನೀವು ಸಂವಹನ ನಡೆಸುವ ಸೈಟ್‌ಗಳನ್ನು ನೀವು ನಂಬಿರುವಿರಿ ಎಂಬುದನ್ನು ಯಾವಾಗಲೂ ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ." - }, "about": { "message": "ಕುರಿತು" }, @@ -248,9 +236,6 @@ "connect": { "message": "ಸಂಪರ್ಕಿಸು" }, - "connectRequest": { - "message": "ವಿನಂತಿಯನ್ನು ಸಂಪರ್ಕಪಡಿಸಿ" - }, "connectingTo": { "message": "$1 ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗುತ್ತಿದೆ" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "ನೀವು ಈಗಾಗಲೇ ಕೆಲವು ಎಥರ್ ಹೊಂದಿದ್ದರೆ, ನೇರ ಠೇವಣಿ ಮೂಲಕ ನಿಮ್ಮ ಹೊಸ ವ್ಯಾಲೆಟ್‌ನಲ್ಲಿ ಎಥರ್ ಅನ್ನು ಪಡೆಯುವ ತ್ವರಿತ ಮಾರ್ಗ." }, - "dismiss": { - "message": "ವಜಾಗೊಳಿಸಿ" - }, "done": { "message": "ಮುಗಿದಿದೆ" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index 39c68a85e..bd412c75c 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "이제 프라이버시 모드가 기본 설정으로 활성화됐습니다" - }, "chartOnlyAvailableEth": { "message": "이더리움 네트워크에서만 사용 가능한 차트." }, - "confirmClear": { - "message": "승인 된 웹 사이트를 삭제 하시겠습니까?" - }, "contractInteraction": { "message": "계약 상호 작용" }, - "clearApprovalData": { - "message": "승인 데이터 삭제" - }, "reject": { "message": "거부" }, - "providerRequest": { + "likeToConnect": { "message": "$1이 당신의 계정에 연결하길 원합니다." }, - "providerRequestInfo": { - "message": "아래 나열된 도메인은 Web3 API에 대한 액세스를 요청하여 Ethereum 블록 체인과 상호 작용할 수 있습니다. Ethereum 액세스를 승인하기 전에 항상 올바른 사이트에 있는지 다시 확인하십시오." - }, "about": { "message": "정보" }, @@ -245,9 +233,6 @@ "connect": { "message": "연결" }, - "connectRequest": { - "message": "연결 요청" - }, "connectingTo": { "message": "$1에 연결" }, @@ -365,9 +350,6 @@ "directDepositEtherExplainer": { "message": "약간의 이더를 이미 보유하고 있다면, 새로 만든 지갑에 직접 입금하여 이더를 보유할 수 있습니다." }, - "dismiss": { - "message": "숨기기" - }, "done": { "message": "완료" }, diff --git a/app/_locales/lt/messages.json b/app/_locales/lt/messages.json index 961eedc91..c2a56ec54 100644 --- a/app/_locales/lt/messages.json +++ b/app/_locales/lt/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Dabar privatumo režimas suaktyvintas pagal numatytąją nuostatą" - }, "chartOnlyAvailableEth": { "message": "Diagramos yra tik „Ethereum“ tinkluose." }, - "confirmClear": { - "message": "Ar tikrai norite panaikinti patvirtintas svetaines?" - }, "contractInteraction": { "message": "Sutartinė sąveika" }, - "clearApprovalData": { - "message": "Išvalyti asmeninius duomenis" - }, "reject": { "message": "Atmesti" }, - "providerRequest": { + "likeToConnect": { "message": "$1 norėtų prisijungti prie jūsų paskyros" }, - "providerRequestInfo": { - "message": "Ši svetainė prašo prieigos peržiūrėti jūsų dabartinės paskyros adresą. Visada patikrinkite, ar pasitikite svetainėmis, su kuriomis sąveikaujate." - }, "about": { "message": "Apie" }, @@ -248,9 +236,6 @@ "connect": { "message": "Prisijungti" }, - "connectRequest": { - "message": "Prijungimo užklausa" - }, "connectingTo": { "message": "Jungiamasi prie $1" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "Jeigu jau turite šiek tiek eterių, sparčiausias būdas gauti eterių į naują piniginę yra tiesioginis įnašas." }, - "dismiss": { - "message": "Atsisakyti" - }, "done": { "message": "Atlikta" }, diff --git a/app/_locales/lv/messages.json b/app/_locales/lv/messages.json index 18d80c900..0b5af9c4e 100644 --- a/app/_locales/lv/messages.json +++ b/app/_locales/lv/messages.json @@ -1,19 +1,10 @@ { - "privacyModeDefault": { - "message": "Privātais režīms tagad ieslēgts pēc noklusējuma" - }, "chartOnlyAvailableEth": { "message": "Grafiks pieejams vienīgi Ethereum tīklos." }, - "confirmClear": { - "message": "Vai tiešām vēlaties dzēst apstiprinātās vietnes?" - }, "contractInteraction": { "message": "Līguma mijiedarbības" }, - "clearApprovalData": { - "message": "Notīrīt konfidencialitātes datus" - }, "appName": { "message": "MetaMask", "description": "The name of the application" @@ -21,12 +12,9 @@ "reject": { "message": "Noraidīt" }, - "providerRequest": { + "likeToConnect": { "message": "$1 vēlas izveidot savienojumu ar jūsu kontu" }, - "providerRequestInfo": { - "message": "Šī lapa pieprasa piekļuvi jūsu pašreizēja konta adreses informācijai. Vienmēr pārliecinieties, ka uzticaties lapām, kuras apmeklējat." - }, "about": { "message": "Par" }, @@ -248,9 +236,6 @@ "connect": { "message": "Pievienošana" }, - "connectRequest": { - "message": "Savienojuma pieprasījums" - }, "connectingTo": { "message": "Pieslēdzas $1" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "Ja jums jau ir Ether, tad visātrāk Ether savā makā varat saņemt ar tiešo iemaksu." }, - "dismiss": { - "message": "Noraidīt" - }, "done": { "message": "Pabeigts" }, diff --git a/app/_locales/ml/messages.json b/app/_locales/ml/messages.json index cd9736e8c..c898d1dc2 100644 --- a/app/_locales/ml/messages.json +++ b/app/_locales/ml/messages.json @@ -54,9 +54,6 @@ "details": { "message": "വിശദാംശങ്ങൾ‌" }, - "dismiss": { - "message": "ബഹിഷ്‌ക്കരിക്കുക" - }, "done": { "message": "പൂർത്തിയാക്കി" }, diff --git a/app/_locales/mr/messages.json b/app/_locales/mr/messages.json index fa8635a39..ef341f40c 100644 --- a/app/_locales/mr/messages.json +++ b/app/_locales/mr/messages.json @@ -54,9 +54,6 @@ "details": { "message": "तपशील" }, - "dismiss": { - "message": "डिसमिस करा" - }, "done": { "message": "पूर्ण झाले" }, diff --git a/app/_locales/ms/messages.json b/app/_locales/ms/messages.json index e573eabc4..7c591b606 100644 --- a/app/_locales/ms/messages.json +++ b/app/_locales/ms/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Mod Privasi kini diaktifkan secara lalai" - }, "chartOnlyAvailableEth": { "message": "Carta hanya tersedia di rangkaian Ethereum." }, - "confirmClear": { - "message": "Adakah anda pasti mahu mengosongkan tapak web diluluskan?" - }, "contractInteraction": { "message": "Interaksi Kontrak" }, - "clearApprovalData": { - "message": "Kosongkan Data Privasi" - }, "reject": { "message": "Tolak" }, - "providerRequest": { + "likeToConnect": { "message": "$1 ingin menyambung kepada akaun anda" }, - "providerRequestInfo": { - "message": "Tapak ini meminta akses untuk melihat alamat akaun semasa anda. Sentiasa pastikan anda mempercayai tapak web yang anda berinteraksi." - }, "about": { "message": "Mengenai" }, @@ -245,9 +233,6 @@ "connect": { "message": "Sambung" }, - "connectRequest": { - "message": "Sambungkan Permintaan" - }, "connectingTo": { "message": "Menyambungkan kepada $1" }, @@ -359,9 +344,6 @@ "directDepositEtherExplainer": { "message": "Jika anda sudah mempunyai Ether, cara paling cepat untuk mendapatkan Ether di dompet baru anda ialah dengan deposit langsung." }, - "dismiss": { - "message": "Singkirkan" - }, "done": { "message": "Selesai" }, diff --git a/app/_locales/nl/messages.json b/app/_locales/nl/messages.json index 265542aed..7ba285208 100644 --- a/app/_locales/nl/messages.json +++ b/app/_locales/nl/messages.json @@ -1,16 +1,7 @@ { - "confirmClear": { - "message": "Weet je zeker dat je goedgekeurde websites wilt wissen?" - }, - "clearApprovalData": { - "message": "Gegevens over goedkeuring wissen" - }, "reject": { "message": "Afwijzen" }, - "providerRequestInfo": { - "message": "Het onderstaande domein probeert toegang tot de Ethereum API te vragen zodat deze kan communiceren met de Ethereum-blockchain. Controleer altijd eerst of u op de juiste site bent voordat u Ethereum-toegang goedkeurt." - }, "accountDetails": { "message": "Accountgegevens" }, diff --git a/app/_locales/no/messages.json b/app/_locales/no/messages.json index b0bf0d6de..6617284b7 100644 --- a/app/_locales/no/messages.json +++ b/app/_locales/no/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Personvernmodus er nå aktivert som standard" - }, "chartOnlyAvailableEth": { "message": "Diagram kun tilgjengelig på Ethereum-nettverk." }, - "confirmClear": { - "message": "Er du sikker på at du vil tømme godkjente nettsteder?" - }, "contractInteraction": { "message": "Kontraktssamhandling" }, - "clearApprovalData": { - "message": "Tøm personvernsdata" - }, "reject": { "message": "Avslå" }, - "providerRequest": { + "likeToConnect": { "message": "$1 ønsker å forbindes med kontoen din " }, - "providerRequestInfo": { - "message": "Dette nettstedet ber om tilgang til å vise din nåværende kontoadresse. Alltid kontroller at du stoler på nettstedene du samhandler med." - }, "about": { "message": "Info" }, @@ -245,9 +233,6 @@ "connect": { "message": "Koble til" }, - "connectRequest": { - "message": "Kontaktforespørsel " - }, "connectingTo": { "message": "Forbinder til $1 " }, @@ -365,9 +350,6 @@ "directDepositEtherExplainer": { "message": "Hvis du allerede har noe Ether, er den raskeste måten å få Ether i den nye lommeboken din på ved hjelp av direkte innskudd." }, - "dismiss": { - "message": "Lukk" - }, "done": { "message": "Ferdig" }, diff --git a/app/_locales/ph/messages.json b/app/_locales/ph/messages.json index 6b66773f6..1a3807ad5 100644 --- a/app/_locales/ph/messages.json +++ b/app/_locales/ph/messages.json @@ -1,10 +1,4 @@ { - "confirmClear": { - "message": "Sigurado ka bang gusto mong i-clear ang mga naaprubahang website?" - }, - "clearApprovalData": { - "message": "Tanggalin ang data ng pag-apruba" - }, "appName": { "message": "MetaMask", "description": "The name of the application" @@ -15,9 +9,6 @@ "reject": { "message": "Tanggihan" }, - "providerRequestInfo": { - "message": "Ang domain na nakalista sa ibaba ay sinusubukang humiling ng access sa Ethereum API upang maaari itong makipag-ugnayan sa Ethereum blockchain. Laging i-double check na ikaw ay nasa tamang site bago aprubahan ang Ethereum access." - }, "accountDetails": { "message": "Detalye ng Account" }, diff --git a/app/_locales/pl/messages.json b/app/_locales/pl/messages.json index 3fa36bd39..2441408f6 100644 --- a/app/_locales/pl/messages.json +++ b/app/_locales/pl/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Tryb prywatny jest domyślnie włączony" - }, "chartOnlyAvailableEth": { "message": "Wykres dostępny tylko w sieciach Ethereum" }, - "confirmClear": { - "message": "Czy na pewno chcesz usunąć zatwierdzone strony internetowe?" - }, "contractInteraction": { "message": "Interakcja z kontraktem" }, - "clearApprovalData": { - "message": "Usuń dane poufne" - }, "reject": { "message": "Odrzuć" }, - "providerRequest": { + "likeToConnect": { "message": "$1 chce połączyć się z Twoim kontem" }, - "providerRequestInfo": { - "message": "Ta strona prosi o dostęp, aby zobaczyć adres Twojego aktualnego konta. Zawsze upewnij się, że ufasz stronom, z którymi wchodzisz w interakcję." - }, "about": { "message": "Informacje" }, @@ -245,9 +233,6 @@ "connect": { "message": "Połącz" }, - "connectRequest": { - "message": "Potwierdź żądanie" - }, "connectingTo": { "message": "Łączenie z $1" }, @@ -365,9 +350,6 @@ "directDepositEtherExplainer": { "message": "Jeśli już masz Eter, najszybciej umieścisz go w swoim nowym portfelu przy pomocy bezpośredniego depozytu." }, - "dismiss": { - "message": "Zamknij" - }, "done": { "message": "Gotowe" }, diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index 519369349..9d9ed0450 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -1,16 +1,7 @@ { - "confirmClear": { - "message": "Tem certeza de que deseja limpar sites aprovados?" - }, - "clearApprovalData": { - "message": "Limpar dados de aprovação" - }, "reject": { "message": "Rejeitar" }, - "providerRequestInfo": { - "message": "O domínio listado abaixo está tentando solicitar acesso à API Ethereum para que ele possa interagir com o blockchain Ethereum. Sempre verifique se você está no site correto antes de aprovar o acesso à Ethereum." - }, "account": { "message": "Conta" }, diff --git a/app/_locales/pt_BR/messages.json b/app/_locales/pt_BR/messages.json index 44ed790ef..e2de06a19 100644 --- a/app/_locales/pt_BR/messages.json +++ b/app/_locales/pt_BR/messages.json @@ -1,19 +1,10 @@ { - "privacyModeDefault": { - "message": "O Modo de Privacidade está ativado por padrão" - }, "chartOnlyAvailableEth": { "message": "Tabela disponível apenas em redes de Ethereum." }, - "confirmClear": { - "message": "Tem certeza de que deseja limpar os sites aprovados?" - }, "contractInteraction": { "message": "Interação do Contrato" }, - "clearApprovalData": { - "message": "Limpar Dados de Privacidade" - }, "appName": { "message": "MetaMask", "description": "The name of the application" @@ -21,12 +12,9 @@ "reject": { "message": "Rejeitar" }, - "providerRequest": { + "likeToConnect": { "message": "$1 gostaria de se conectar à sua conta" }, - "providerRequestInfo": { - "message": "Este site está solicitando acesso para visualizar o seu endereço de conta atual. Certifique-se sempre de confiar nos sites com os quais você interage." - }, "about": { "message": "Sobre" }, @@ -242,9 +230,6 @@ "connect": { "message": "Conectar-se" }, - "connectRequest": { - "message": "Solicitação de Conexão" - }, "connectingTo": { "message": "Conectando a $1" }, @@ -362,9 +347,6 @@ "directDepositEtherExplainer": { "message": "Se você já tem Ether, a forma mais rápida de colocá-lo em sua nova carteira é o depósito direto." }, - "dismiss": { - "message": "Dispensar" - }, "done": { "message": "Concluído" }, diff --git a/app/_locales/pt_PT/messages.json b/app/_locales/pt_PT/messages.json index b2f844fdd..ae85eb26c 100644 --- a/app/_locales/pt_PT/messages.json +++ b/app/_locales/pt_PT/messages.json @@ -63,9 +63,6 @@ "details": { "message": "Detalhes" }, - "dismiss": { - "message": "Ignorar" - }, "done": { "message": "Concluído" }, diff --git a/app/_locales/ro/messages.json b/app/_locales/ro/messages.json index f891a40df..3ed11cb86 100644 --- a/app/_locales/ro/messages.json +++ b/app/_locales/ro/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Modul de confidențialitate este activat acum în mod implicit" - }, "chartOnlyAvailableEth": { "message": "Grafic disponibil numai pe rețelele Ethereum." }, - "confirmClear": { - "message": "Sunteți sigur că doriți să ștergeți site-urile aprobate?" - }, "contractInteraction": { "message": "Interacțiune contract" }, - "clearApprovalData": { - "message": "Ștergeți datele confidențiale" - }, "reject": { "message": "Respingeți" }, - "providerRequest": { + "likeToConnect": { "message": "$1 ar dori să se conecteze la contul dvs." }, - "providerRequestInfo": { - "message": "Acest site solicită acces pentru a vedea adresa curentă a contului dvs. Asigurați-vă întotdeauna că aveți încredere în site-urile cu care interacționați." - }, "about": { "message": "Despre" }, @@ -248,9 +236,6 @@ "connect": { "message": "Conectează-te" }, - "connectRequest": { - "message": "Solicitare de conectare" - }, "connectingTo": { "message": "Se conectează la $1" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "Dacă deja aveți Ether, cel mai rapid mod de a avea Ether în portofelul nou prin depunere directă." }, - "dismiss": { - "message": "Închide" - }, "done": { "message": "Efectuat" }, diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index 660b2799e..43249d6bc 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -1,16 +1,7 @@ { - "confirmClear": { - "message": "Вы уверены, что хотите очистить утвержденные веб-сайты?Tem certeza de que deseja limpar sites aprovados?" - }, - "clearApprovalData": { - "message": "Четкие данные об утверждении" - }, "reject": { "message": "Отклонить" }, - "providerRequestInfo": { - "message": "Домен, указанный ниже, пытается запросить доступ к API-интерфейсу Ethereum, чтобы он мог взаимодействовать с блокчейном Ethereum. Всегда проверяйте, что вы находитесь на правильном сайте, прежде чем одобрять доступ к веб-сайту." - }, "account": { "message": "Счет" }, @@ -545,16 +536,13 @@ "youSign": { "message": "Вы подписываете" }, - "privacyModeDefault": { - "message": "Режим конфиденциальности теперь включен по умолчанию" - }, "chartOnlyAvailableEth": { "message": "Диаграмма доступна только в сетях Ethereum." }, "contractInteraction": { "message": "Взаимодействие с контрактом" }, - "providerRequest": { + "likeToConnect": { "message": "$1 запрашивает доступ к вашему аккаунту" }, "about": { @@ -707,9 +695,6 @@ "connect": { "message": "Подключиться" }, - "connectRequest": { - "message": "Запрос на подключение" - }, "connectingTo": { "message": "Подключение к $1" }, @@ -752,9 +737,6 @@ "deleteAccount": { "message": "Удалить аккаунт" }, - "dismiss": { - "message": "Отклюнить" - }, "downloadGoogleChrome": { "message": "Скачать Google Chrome" }, diff --git a/app/_locales/sk/messages.json b/app/_locales/sk/messages.json index 5238e076d..d975048d8 100644 --- a/app/_locales/sk/messages.json +++ b/app/_locales/sk/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Režim súkromia je povolený. Je prednastavený automaticky" - }, "chartOnlyAvailableEth": { "message": "Graf je k dispozícii iba v sieťach Ethereum." }, - "confirmClear": { - "message": "Naozaj chcete vymazať schválené webové stránky?" - }, "contractInteraction": { "message": "Zmluvná interakcia" }, - "clearApprovalData": { - "message": "Jasné údaje o schválení" - }, "reject": { "message": "Odmítnout" }, - "providerRequest": { + "likeToConnect": { "message": "$1 sa chce pripojiť k vášmu účtu" }, - "providerRequestInfo": { - "message": "Níže uvedená doména se pokouší požádat o přístup k API Ethereum, aby mohla komunikovat s blokádou Ethereum. Před schválením přístupu Ethereum vždy zkontrolujte, zda jste na správném místě." - }, "about": { "message": "Informácie" }, @@ -239,9 +227,6 @@ "connect": { "message": "Pripojenie" }, - "connectRequest": { - "message": "Požiadavka na pripojenie" - }, "connectingTo": { "message": "Pripája sa k $1" }, @@ -359,9 +344,6 @@ "directDepositEtherExplainer": { "message": "Pokud už vlastníte nějaký Ether, nejrychleji ho dostanete do peněženky přímým vkladem." }, - "dismiss": { - "message": "Zatvoriť" - }, "done": { "message": "Hotovo" }, diff --git a/app/_locales/sl/messages.json b/app/_locales/sl/messages.json index 8530dd43d..312bcecfb 100644 --- a/app/_locales/sl/messages.json +++ b/app/_locales/sl/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Zasebnostni način je zdaj privzeto omogočen" - }, "chartOnlyAvailableEth": { "message": "Grafikon na voljo le v glavnih omrežjih." }, - "confirmClear": { - "message": "Ste prepričani da želite počistiti odobrene spletne strani?" - }, "contractInteraction": { "message": "Interakcija s pogodbo" }, - "clearApprovalData": { - "message": "Počisti podatke o odobritvi" - }, "reject": { "message": "Zavrni" }, - "providerRequest": { + "likeToConnect": { "message": "$1 se želi povezati z vašim računom." }, - "providerRequestInfo": { - "message": "Domena zahteva dostop do verige blokov in ogled vašega računa. Pred potrditvjo vedno preverite ali ste na želeni spletni strani." - }, "about": { "message": "O možnostih" }, @@ -248,9 +236,6 @@ "connect": { "message": "Poveži" }, - "connectRequest": { - "message": "Zahteva za povezavo" - }, "connectingTo": { "message": "Povezovanje na $1" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "Če že imate Ether, ga lahko najhitreje dobite v MetaMask z neposrednim vplačilom." }, - "dismiss": { - "message": "Opusti" - }, "done": { "message": "Končano" }, diff --git a/app/_locales/sr/messages.json b/app/_locales/sr/messages.json index d3fd1cbd4..f4084996f 100644 --- a/app/_locales/sr/messages.json +++ b/app/_locales/sr/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Režim privatnosti je podrazumevano omogućen" - }, "chartOnlyAvailableEth": { "message": "Grafikon dostupan jedino na mrežama Ethereum." }, - "confirmClear": { - "message": "Da li ste sigurni da želite da obrišete odobrene veb lokacije?" - }, "contractInteraction": { "message": "Ugovorna interakcija" }, - "clearApprovalData": { - "message": "Obrišite privatne podatke" - }, "reject": { "message": "Одбиј" }, - "providerRequest": { + "likeToConnect": { "message": "$1 bi hteo da se poveže sa vašim nalogom" }, - "providerRequestInfo": { - "message": "Ovaj sajt traži pristup kako bi video vašu trenutnu adresu naloga. Uvek budite sigurni da verujete sajtovima s kojima komunicirate." - }, "about": { "message": "Основни подаци" }, @@ -245,9 +233,6 @@ "connect": { "message": "Повезивање" }, - "connectRequest": { - "message": "Zahtev za povezivanjem" - }, "connectingTo": { "message": "Povezuje se na $1" }, @@ -365,9 +350,6 @@ "directDepositEtherExplainer": { "message": "Ako već imate neki Ether, najbrži način da preuzmete Ether u svoj novi novčanik jeste direktnim deponovanjem." }, - "dismiss": { - "message": "Одбаци" - }, "done": { "message": "Gotovo" }, diff --git a/app/_locales/sv/messages.json b/app/_locales/sv/messages.json index 1b7ecc06e..750357045 100644 --- a/app/_locales/sv/messages.json +++ b/app/_locales/sv/messages.json @@ -1,19 +1,10 @@ { - "privacyModeDefault": { - "message": "Integritetsläge är nu aktiverat som standard" - }, "chartOnlyAvailableEth": { "message": "Tabellen är endast tillgänglig på Ethereum-nätverk." }, - "confirmClear": { - "message": "Är du säker på att du vill rensa godkända webbplatser?" - }, "contractInteraction": { "message": "Kontraktinteraktion" }, - "clearApprovalData": { - "message": "Rensa personlig data" - }, "appName": { "message": "MetaMask", "description": "The name of the application" @@ -21,12 +12,9 @@ "reject": { "message": "Avvisa" }, - "providerRequest": { + "likeToConnect": { "message": "$1 vill ansluta till ditt konto" }, - "providerRequestInfo": { - "message": "Den här sidan begär åtkomst till din aktuella kontoadress. Se till att du kan lita på de sidor du använder dig av." - }, "about": { "message": "Om" }, @@ -242,9 +230,6 @@ "connect": { "message": "Ansluta" }, - "connectRequest": { - "message": "Anslutningsförfrågan" - }, "connectingTo": { "message": "Ansluter till $1" }, @@ -362,9 +347,6 @@ "directDepositEtherExplainer": { "message": "Om du redan har Ether är det snabbaste sättet att få Ether i din nya plånbok att göra en direktinsättning." }, - "dismiss": { - "message": "Ta bort permanent" - }, "done": { "message": "Klart" }, diff --git a/app/_locales/sw/messages.json b/app/_locales/sw/messages.json index c8c2e36ee..38c89aca8 100644 --- a/app/_locales/sw/messages.json +++ b/app/_locales/sw/messages.json @@ -1,19 +1,10 @@ { - "privacyModeDefault": { - "message": "Hali ya Faragha sasa imewezeshwa kwa chaguomsingi" - }, "chartOnlyAvailableEth": { "message": "Zogoa inapatikana kwenye mitandao ya Ethereum pekee." }, - "confirmClear": { - "message": "Una uhakika unataka kufuta tovuti zilizodihinishwa?" - }, "contractInteraction": { "message": "Mwingiliono wa Mkataba" }, - "clearApprovalData": { - "message": "Futa Data za Faragha" - }, "appName": { "message": "MetaMask", "description": "The name of the application" @@ -21,12 +12,9 @@ "reject": { "message": "Kataa" }, - "providerRequest": { + "likeToConnect": { "message": "$1 ingependa kuunganishwa kwenye akaunti yako" }, - "providerRequestInfo": { - "message": "Tovuti hii inaomba idhini ya kuangalia anwani yako ya akaunti ya sasa. Daima hakikisha unaziamami tovuti ambazo unaingiliana nazo." - }, "about": { "message": "Kuhusu" }, @@ -242,9 +230,6 @@ "connect": { "message": "Unganisha" }, - "connectRequest": { - "message": "Unganisha Ombi" - }, "connectingTo": { "message": "Inaunganisha kwenye $1" }, @@ -362,9 +347,6 @@ "directDepositEtherExplainer": { "message": "Ikiwa tayari una sarafu kadhaa za Ether, njia rahisi ya kupata Ether kwenye waleti yako mpya kupitia kuweka moja kwa moja." }, - "dismiss": { - "message": "Ondoa" - }, "done": { "message": "Imekamilika" }, diff --git a/app/_locales/ta/messages.json b/app/_locales/ta/messages.json index 698349c24..dc48abb02 100644 --- a/app/_locales/ta/messages.json +++ b/app/_locales/ta/messages.json @@ -1,19 +1,10 @@ { - "confirmClear": { - "message": "அங்கீகரிக்கப்பட்ட வலைத்தளங்களை நிச்சயமாக நீக்க விரும்புகிறீர்களா?" - }, - "clearApprovalData": { - "message": "ஒப்புதல் தரவை அழி" - }, "approve": { "message": "ஒப்புதல்" }, "reject": { "message": "நிராகரி" }, - "providerRequestInfo": { - "message": "கீழே பட்டியலிடப்பட்டுள்ள டொமைன் Web3 ஏபிஐ அணுகலைக் கோருவதற்கு முயற்சிக்கிறது, எனவே இது Ethereum blockchain உடன் தொடர்பு கொள்ள முடியும். Web3 அணுகுமுறையை அங்கீகரிப்பதற்கு முன் சரியான தளத்தில் இருப்பதை எப்போதும் இருமுறை சரிபார்க்கவும்." - }, "account": { "message": "கணக்கு" }, @@ -578,9 +569,6 @@ "delete": { "message": "நீக்கு" }, - "dismiss": { - "message": "நிராகரி" - }, "fast": { "message": "வேகமான" }, diff --git a/app/_locales/te/messages.json b/app/_locales/te/messages.json index 6de4b0464..2df11217d 100644 --- a/app/_locales/te/messages.json +++ b/app/_locales/te/messages.json @@ -54,9 +54,6 @@ "details": { "message": "వివరాలు" }, - "dismiss": { - "message": "తొలగించు" - }, "done": { "message": "పూర్తయింది" }, diff --git a/app/_locales/th/messages.json b/app/_locales/th/messages.json index f07f3421e..6b3686f45 100644 --- a/app/_locales/th/messages.json +++ b/app/_locales/th/messages.json @@ -1,19 +1,10 @@ { - "confirmClear": { - "message": "คุณแน่ใจหรือไม่ว่าต้องการล้างเว็บไซต์ที่ผ่านการอนุมัติ" - }, - "clearApprovalData": { - "message": "ล้างข้อมูลการอนุมัติ" - }, "reject": { "message": "ปฏิเสธ" }, - "providerRequest": { + "likeToConnect": { "message": "$1 ต้องการเชื่อมต่อกับบัญชีของคุณ" }, - "providerRequestInfo": { - "message": "โดเมนที่แสดงด้านล่างกำลังพยายามขอเข้าถึง API ของ Ethereum เพื่อให้สามารถโต้ตอบกับบล็อค Ethereum ได้ ตรวจสอบว่าคุณอยู่ในไซต์ที่ถูกต้องก่อนที่จะอนุมัติการเข้าถึง Ethereum เสมอ" - }, "about": { "message": "เกี่ยวกับ" }, @@ -184,9 +175,6 @@ "directDepositEtherExplainer": { "message": "ถ้าคุณมีอีเธอร์อยู่แล้ววิธีการที่เร็วที่สุดในการเอาเงินเข้ากระเป๋าใหม่ก็คือการโอนตรงๆ" }, - "dismiss": { - "message": "ปิด" - }, "done": { "message": "เสร็จสิ้น" }, diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index c6027a42d..fdb1ae927 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -1,16 +1,7 @@ { - "confirmClear": { - "message": "Onaylanmış web sitelerini silmek istediğinizden emin misiniz?" - }, - "clearApprovalData": { - "message": "Onay verilerini temizle" - }, "reject": { "message": "Reddetmek" }, - "providerRequestInfo": { - "message": "Aşağıda listelenen etki alanı, Ethereum API'sine erişim talep etmeye çalışmaktadır, böylece Ethereum blockchain ile etkileşime girebilir. Web3 erişimini onaylamadan önce her zaman doğru sitede olduğunuzu kontrol edin." - }, "account": { "message": "Hesap" }, diff --git a/app/_locales/uk/messages.json b/app/_locales/uk/messages.json index 49d04a096..cec516b6c 100644 --- a/app/_locales/uk/messages.json +++ b/app/_locales/uk/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "Режим конфіденційності тепер увімкнено за замовчуванням" - }, "chartOnlyAvailableEth": { "message": "Таблиця доступна тільки в мережах Ethereum." }, - "confirmClear": { - "message": "Ви впевнені, що хочете очистити затверджені веб-сайти?" - }, "contractInteraction": { "message": "Контрактна взаємодія" }, - "clearApprovalData": { - "message": "Очистити приватні дані" - }, "reject": { "message": "Відхилити" }, - "providerRequest": { + "likeToConnect": { "message": "$1 бажає підключитися до вашого облікового запису" }, - "providerRequestInfo": { - "message": "Цей сайт запитує доступ на перегляд вашої поточної адреси облікового запису. Завжди взаємодійте лише з веб-сайтами, яким довіряєте." - }, "about": { "message": "Про Google Chrome" }, @@ -248,9 +236,6 @@ "connect": { "message": "Під’єднатися" }, - "connectRequest": { - "message": "Запит на з'єднання" - }, "connectingTo": { "message": "Під'єднуємось до $1" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "Якщо ви вже маєте ефір, пряме переведення – найшвидший спосіб передати ефір у свій гаманець." }, - "dismiss": { - "message": "Відхилити" - }, "done": { "message": "Готово" }, diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index bc017c947..6136403ba 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -1,16 +1,7 @@ { - "confirmClear": { - "message": "Bạn có chắc chắn muốn xóa các trang web được phê duyệt không?" - }, - "clearApprovalData": { - "message": "Xóa dữ liệu phê duyệt" - }, "reject": { "message": "Từ chối" }, - "providerRequestInfo": { - "message": "Miền được liệt kê bên dưới đang cố gắng yêu cầu quyền truy cập vào API Ethereum để nó có thể tương tác với chuỗi khối Ethereum. Luôn kiểm tra kỹ xem bạn có đang ở đúng trang web trước khi phê duyệt quyền truy cập Ethereum hay không." - }, "account": { "message": "Tài khoản" }, diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index cade6ee71..e92813a9a 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "现已默认启用隐私模式" - }, "chartOnlyAvailableEth": { "message": "聊天功能仅对以太坊网络开放。" }, - "confirmClear": { - "message": "您确定要清除已批准的网站吗?" - }, "contractInteraction": { "message": "合约交互" }, - "clearApprovalData": { - "message": "清除批准数据" - }, "reject": { "message": "拒绝" }, - "providerRequest": { + "likeToConnect": { "message": "$1 希望关联您的账户" }, - "providerRequestInfo": { - "message": "下面列出的域正在尝试请求访问Ethereum API,以便它可以与以太坊区块链进行交互。在批准Ethereum访问之前,请务必仔细检查您是否在正确的站点上。" - }, "about": { "message": "关于" }, @@ -87,7 +75,7 @@ "message": "添加推荐代币" }, "addAcquiredTokens": { - "message": "在Metamask上添加已用的代币" + "message": "在MetaMask上添加已用的代币" }, "amount": { "message": "数量" @@ -248,9 +236,6 @@ "connect": { "message": "连接" }, - "connectRequest": { - "message": "关联请求" - }, "connectingTo": { "message": "正在连接 $1" }, @@ -368,9 +353,6 @@ "directDepositEtherExplainer": { "message": "如果你已经有了一些 Ether,通过直接转入是你的新钱包获取 Ether 的最快捷方式。" }, - "dismiss": { - "message": "关闭" - }, "done": { "message": "完成" }, diff --git a/app/_locales/zh_TW/messages.json b/app/_locales/zh_TW/messages.json index 3d0e299a6..2859e8fd4 100644 --- a/app/_locales/zh_TW/messages.json +++ b/app/_locales/zh_TW/messages.json @@ -1,28 +1,16 @@ { - "privacyModeDefault": { - "message": "隱私模式現已根據預設開啟" - }, "chartOnlyAvailableEth": { "message": "圖表僅適用於以太坊網路。" }, - "confirmClear": { - "message": "您確定要清除已批准的網站紀錄?" - }, "contractInteraction": { "message": "合約互動" }, - "clearApprovalData": { - "message": "清除批准數據" - }, "reject": { "message": "拒絕" }, - "providerRequest": { + "likeToConnect": { "message": "$1 請求訪問帳戶權限" }, - "providerRequestInfo": { - "message": "此網站希望能讀取您的帳戶資訊。請務必確認您信任這個網站、並了解後續可能的交易行為。" - }, "about": { "message": "關於" }, @@ -245,9 +233,6 @@ "connect": { "message": "連線" }, - "connectRequest": { - "message": "連線請求" - }, "connectingTo": { "message": "連線到$1" }, @@ -365,9 +350,6 @@ "directDepositEtherExplainer": { "message": "如果您已經擁有乙太幣,直接存入功能是讓新錢包最快取得乙太幣的方式。" }, - "dismiss": { - "message": "關閉" - }, "done": { "message": "完成" }, diff --git a/app/images/broken-line.svg b/app/images/broken-line.svg new file mode 100644 index 000000000..ec4ed0d9c --- /dev/null +++ b/app/images/broken-line.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/images/connect-white.svg b/app/images/connect-white.svg new file mode 100644 index 000000000..e9063ae46 --- /dev/null +++ b/app/images/connect-white.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/images/provider-approval-check.svg b/app/images/permissions-check.svg similarity index 100% rename from app/images/provider-approval-check.svg rename to app/images/permissions-check.svg diff --git a/app/scripts/background.js b/app/scripts/background.js index 18bdfdfb9..e5c9ea665 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -64,6 +64,7 @@ const isEdge = !isIE && !!window.StyleMedia let popupIsOpen = false let notificationIsOpen = false const openMetamaskTabsIDs = {} +const requestAccountTabIds = {} // state persistence const localStore = new LocalStore() @@ -75,7 +76,6 @@ initialize().catch(log.error) // setup metamask mesh testing container const { submitMeshMetricsEntry } = setupMetamaskMeshMetrics() - /** * An object representing a transaction, in whatever state it is in. * @typedef TransactionMeta @@ -248,6 +248,12 @@ function setupController (initState, initLangCode) { // platform specific api platform, encryptor: isEdge ? new EdgeEncryptor() : undefined, + getRequestAccountTabIds: () => { + return requestAccountTabIds + }, + getOpenMetamaskTabsIds: () => { + return openMetamaskTabsIDs + }, }) const provider = controller.provider @@ -387,6 +393,17 @@ function setupController (initState, initLangCode) { }) } } else { + if (remotePort.sender && remotePort.sender.tab && remotePort.sender.url) { + const tabId = remotePort.sender.tab.id + const url = new URL(remotePort.sender.url) + const origin = url.hostname + + remotePort.onMessage.addListener(msg => { + if (msg.data && msg.data.method === 'eth_requestAccounts') { + requestAccountTabIds[origin] = tabId + } + }) + } connectExternal(remotePort) } } @@ -411,7 +428,7 @@ function setupController (initState, initLangCode) { controller.messageManager.on('updateBadge', updateBadge) controller.personalMessageManager.on('updateBadge', updateBadge) controller.typedMessageManager.on('updateBadge', updateBadge) - controller.providerApprovalController.memStore.on('update', updateBadge) + controller.permissionsController.permissions.subscribe(updateBadge) /** * Updates the Web Extension's "badge" number, on the little fox in the toolbar. @@ -423,8 +440,8 @@ function setupController (initState, initLangCode) { const unapprovedMsgCount = controller.messageManager.unapprovedMsgCount const unapprovedPersonalMsgs = controller.personalMessageManager.unapprovedPersonalMsgCount const unapprovedTypedMsgs = controller.typedMessageManager.unapprovedTypedMessagesCount - const pendingProviderRequests = controller.providerApprovalController.memStore.getState().providerRequests.length - const count = unapprovedTxCount + unapprovedMsgCount + unapprovedPersonalMsgs + unapprovedTypedMsgs + pendingProviderRequests + const pendingPermissionRequests = Object.keys(controller.permissionsController.permissions.state.permissionsRequests).length + const count = unapprovedTxCount + unapprovedMsgCount + unapprovedPersonalMsgs + unapprovedTypedMsgs + pendingPermissionRequests if (count) { label = String(count) } diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 6ea2db740..d583399ae 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -2,7 +2,6 @@ const fs = require('fs') const path = require('path') const pump = require('pump') const log = require('loglevel') -const Dnode = require('dnode') const querystring = require('querystring') const { Writable } = require('readable-stream') const LocalMessageDuplexStream = require('post-message-stream') @@ -21,7 +20,7 @@ const inpageBundle = inpageContent + inpageSuffix // If we create a FireFox-only code path using that API, // MetaMask will be much faster loading and performant on Firefox. -if (shouldInjectWeb3()) { +if (shouldInjectProvider()) { injectScript(inpageBundle) start() } @@ -40,7 +39,7 @@ function injectScript (content) { container.insertBefore(scriptTag, container.children[0]) container.removeChild(scriptTag) } catch (e) { - console.error('MetaMask script injection failed', e) + console.error('MetaMask provider injection failed.', e) } } @@ -132,12 +131,6 @@ async function setupStreams () { // connect "phishing" channel to warning system const phishingStream = extensionMux.createStream('phishing') phishingStream.once('data', redirectToPhishingWarning) - - // connect "publicApi" channel to submit page metadata - const publicApiStream = extensionMux.createStream('publicApi') - const background = await setupPublicApi(publicApiStream) - - return { background } } function forwardTrafficBetweenMuxers (channelName, muxA, muxB) { @@ -151,39 +144,6 @@ function forwardTrafficBetweenMuxers (channelName, muxA, muxB) { ) } -async function setupPublicApi (outStream) { - const api = { - getSiteMetadata: (cb) => cb(null, getSiteMetadata()), - } - const dnode = Dnode(api) - pump( - outStream, - dnode, - outStream, - (err) => { - // report any error - if (err) { - log.error(err) - } - } - ) - const background = await new Promise(resolve => dnode.once('remote', resolve)) - return background -} - -/** - * Gets site metadata and returns it - * - */ -function getSiteMetadata () { - // get metadata - const metadata = { - name: getSiteName(window), - icon: getSiteIcon(window), - } - return metadata -} - /** * Error handler for page to extension stream disconnections * @@ -199,11 +159,11 @@ function logStreamDisconnectWarning (remoteLabel, err) { } /** - * Determines if Web3 should be injected + * Determines if the provider should be injected * - * @returns {boolean} {@code true} if Web3 should be injected + * @returns {boolean} {@code true} if the provider should be injected */ -function shouldInjectWeb3 () { +function shouldInjectProvider () { return doctypeCheck() && suffixCheck() && documentElementCheck() && !blacklistedDomainCheck() } @@ -226,8 +186,8 @@ function doctypeCheck () { * Returns whether or not the extension (suffix) of the current document is prohibited * * This checks {@code window.location.pathname} against a set of file extensions - * that should not have web3 injected into them. This check is indifferent of query parameters - * in the location. + * that we should not inject the provider into. This check is indifferent of + * query parameters in the location. * * @returns {boolean} whether or not the extension of the current document is prohibited */ @@ -300,46 +260,6 @@ function redirectToPhishingWarning () { })}` } - -/** - * Extracts a name for the site from the DOM - */ -function getSiteName (window) { - const document = window.document - const siteName = document.querySelector('head > meta[property="og:site_name"]') - if (siteName) { - return siteName.content - } - - const metaTitle = document.querySelector('head > meta[name="title"]') - if (metaTitle) { - return metaTitle.content - } - - return document.title -} - -/** - * Extracts an icon for the site from the DOM - */ -function getSiteIcon (window) { - const document = window.document - - // Use the site's favicon if it exists - const shortcutIcon = document.querySelector('head > link[rel="shortcut icon"]') - if (shortcutIcon) { - return shortcutIcon.href - } - - // Search through available icons in no particular order - const icon = Array.from(document.querySelectorAll('head > link[rel="icon"]')).find((icon) => Boolean(icon.href)) - if (icon) { - return icon.href - } - - return null -} - /** * Returns a promise that resolves when the DOM is loaded (does not wait for images to load) */ @@ -349,5 +269,5 @@ async function domIsReady () { return } // wait for load - await new Promise(resolve => window.addEventListener('DOMContentLoaded', resolve, { once: true })) + return new Promise(resolve => window.addEventListener('DOMContentLoaded', resolve, { once: true })) } diff --git a/app/scripts/controllers/permissions/index.js b/app/scripts/controllers/permissions/index.js new file mode 100644 index 000000000..899044b13 --- /dev/null +++ b/app/scripts/controllers/permissions/index.js @@ -0,0 +1,377 @@ +const JsonRpcEngine = require('json-rpc-engine') +const asMiddleware = require('json-rpc-engine/src/asMiddleware') +const ObservableStore = require('obs-store') +const RpcCap = require('rpc-cap').CapabilitiesController +const { ethErrors } = require('eth-json-rpc-errors') + +const getRestrictedMethods = require('./restrictedMethods') +const createMethodMiddleware = require('./methodMiddleware') +const createLoggerMiddleware = require('./loggerMiddleware') + +// Methods that do not require any permissions to use: +const SAFE_METHODS = require('./permissions-safe-methods.json') + +// some constants +const METADATA_STORE_KEY = 'domainMetadata' +const LOG_STORE_KEY = 'permissionsLog' +const HISTORY_STORE_KEY = 'permissionsHistory' +const WALLET_METHOD_PREFIX = 'wallet_' +const CAVEAT_NAMES = { + exposedAccounts: 'exposedAccounts', +} +const ACCOUNTS_CHANGED_NOTIFICATION = 'wallet_accountsChanged' + +class PermissionsController { + + constructor ( + { + platform, notifyDomain, notifyAllDomains, keyringController, + } = {}, + restoredPermissions = {}, + restoredState = {}) { + this.store = new ObservableStore({ + [METADATA_STORE_KEY]: restoredState[METADATA_STORE_KEY] || {}, + [LOG_STORE_KEY]: restoredState[LOG_STORE_KEY] || [], + [HISTORY_STORE_KEY]: restoredState[HISTORY_STORE_KEY] || {}, + }) + this.notifyDomain = notifyDomain + this.notifyAllDomains = notifyAllDomains + this.keyringController = keyringController + this._platform = platform + this._restrictedMethods = getRestrictedMethods(this) + this._initializePermissions(restoredPermissions) + } + + createMiddleware ({ origin, extensionId }) { + + if (extensionId) { + this.store.updateState({ + [METADATA_STORE_KEY]: { + ...this.store.getState()[METADATA_STORE_KEY], + [origin]: { extensionId }, + }, + }) + } + + const engine = new JsonRpcEngine() + + engine.push(createLoggerMiddleware({ + walletPrefix: WALLET_METHOD_PREFIX, + restrictedMethods: Object.keys(this._restrictedMethods), + ignoreMethods: [ 'wallet_sendDomainMetadata' ], + store: this.store, + logStoreKey: LOG_STORE_KEY, + historyStoreKey: HISTORY_STORE_KEY, + })) + + engine.push(createMethodMiddleware({ + store: this.store, + storeKey: METADATA_STORE_KEY, + getAccounts: this.getAccounts.bind(this, origin), + requestAccountsPermission: this._requestPermissions.bind( + this, origin, { eth_accounts: {} } + ), + })) + + engine.push(this.permissions.providerMiddlewareFunction.bind( + this.permissions, { origin } + )) + return asMiddleware(engine) + } + + /** + * Returns the accounts that should be exposed for the given origin domain, + * if any. This method exists for when a trusted context needs to know + * which accounts are exposed to a given domain. + * + * @param {string} origin - The origin string. + */ + getAccounts (origin) { + return new Promise((resolve, _) => { + + const req = { method: 'eth_accounts' } + const res = {} + this.permissions.providerMiddlewareFunction( + { origin }, req, res, () => {}, _end + ) + + function _end () { + if (res.error || !Array.isArray(res.result)) { + resolve([]) + } else { + resolve(res.result) + } + } + }) + } + + /** + * Submits a permissions request to rpc-cap. Internal use only. + * + * @param {string} origin - The origin string. + * @param {IRequestedPermissions} permissions - The requested permissions. + */ + _requestPermissions (origin, permissions) { + return new Promise((resolve, reject) => { + + const req = { method: 'wallet_requestPermissions', params: [permissions] } + const res = {} + this.permissions.providerMiddlewareFunction( + { origin }, req, res, () => {}, _end + ) + + function _end (err) { + if (err || res.error) { + reject(err || res.error) + } else { + resolve(res.result) + } + } + }) + } + + /** + * User approval callback. The request can fail if the request is invalid. + * + * @param {object} approved the approved request object + */ + async approvePermissionsRequest (approved, accounts) { + + const { id } = approved.metadata + const approval = this.pendingApprovals[id] + + try { + + // attempt to finalize the request and resolve it + await this.finalizePermissionsRequest(approved.permissions, accounts) + approval.resolve(approved.permissions) + + } catch (err) { + + // if finalization fails, reject the request + approval.reject(ethErrors.rpc.invalidRequest({ + message: err.message, data: err, + })) + } + + delete this.pendingApprovals[id] + } + + /** + * User rejection callback. + * + * @param {string} id the id of the rejected request + */ + async rejectPermissionsRequest (id) { + const approval = this.pendingApprovals[id] + approval.reject(ethErrors.provider.userRejectedRequest()) + delete this.pendingApprovals[id] + } + + /** + * Grants the given origin the eth_accounts permission for the given account(s). + * This method should ONLY be called as a result of direct user action in the UI, + * with the intention of supporting legacy dapps that don't support EIP 1102. + * + * @param {string} origin - The origin to expose the account(s) to. + * @param {Array} accounts - The account(s) to expose. + */ + async legacyExposeAccounts (origin, accounts) { + + const permissions = { + eth_accounts: {}, + } + + await this.finalizePermissionsRequest(permissions, accounts) + + let error + try { + await new Promise((resolve, reject) => { + this.permissions.grantNewPermissions(origin, permissions, {}, err => err ? resolve() : reject(err)) + }) + } catch (err) { + error = err + } + + if (error) { + if (error.code === 4001) { + throw error + } else { + throw ethErrors.rpc.internal({ + message: `Failed to add 'eth_accounts' to '${origin}'.`, + data: { + originalError: error, + accounts, + }, + }) + } + } + } + + /** + * Update the accounts exposed to the given origin. + * Throws error if the update fails. + * + * @param {string} origin - The origin to change the exposed accounts for. + * @param {string[]} accounts - The new account(s) to expose. + */ + async updateExposedAccounts (origin, accounts) { + + await this.validateExposedAccounts(accounts) + + this.permissions.updateCaveatFor( + origin, 'eth_accounts', CAVEAT_NAMES.exposedAccounts, accounts + ) + + this.notifyDomain(origin, { + method: ACCOUNTS_CHANGED_NOTIFICATION, + result: accounts, + }) + } + + /** + * Finalizes a permissions request. + * Throws if request validation fails. + * + * @param {Object} requestedPermissions - The requested permissions. + * @param {string[]} accounts - The accounts to expose, if any. + */ + async finalizePermissionsRequest (requestedPermissions, accounts) { + + const { eth_accounts: ethAccounts } = requestedPermissions + + if (ethAccounts) { + + await this.validateExposedAccounts(accounts) + + if (!ethAccounts.caveats) { + ethAccounts.caveats = [] + } + + // caveat names are unique, and we will only construct this caveat here + ethAccounts.caveats = ethAccounts.caveats.filter(c => ( + c.name !== CAVEAT_NAMES.exposedAccounts + )) + + ethAccounts.caveats.push( + { + type: 'filterResponse', + value: accounts, + name: CAVEAT_NAMES.exposedAccounts, + }, + ) + } + } + + /** + * Validate an array of accounts representing accounts to be exposed + * to a domain. Throws error if validation fails. + * + * @param {string[]} accounts - An array of addresses. + */ + async validateExposedAccounts (accounts) { + + if (!Array.isArray(accounts) || accounts.length === 0) { + throw new Error('Must provide non-empty array of account(s).') + } + + // assert accounts exist + const allAccounts = await this.keyringController.getAccounts() + accounts.forEach(acc => { + if (!allAccounts.includes(acc)) { + throw new Error(`Unknown account: ${acc}`) + } + }) + } + + /** + * Removes the given permissions for the given domain. + * @param {object} domains { origin: [permissions] } + */ + removePermissionsFor (domains) { + + Object.entries(domains).forEach(([origin, perms]) => { + + this.permissions.removePermissionsFor( + origin, + perms.map(methodName => { + + if (methodName === 'eth_accounts') { + this.notifyDomain( + origin, + { method: ACCOUNTS_CHANGED_NOTIFICATION, result: [] } + ) + } + + return { parentCapability: methodName } + }) + ) + }) + } + + /** + * Removes all known domains and their related permissions. + */ + clearPermissions () { + this.permissions.clearDomains() + this.notifyAllDomains({ + method: ACCOUNTS_CHANGED_NOTIFICATION, + result: [], + }) + } + + /** + * A convenience method for retrieving a login object + * or creating a new one if needed. + * + * @param {string} origin = The origin string representing the domain. + */ + _initializePermissions (restoredState) { + + // these permission requests are almost certainly stale + const initState = { ...restoredState, permissionsRequests: [] } + + this.pendingApprovals = {} + + this.permissions = new RpcCap({ + + // Supports passthrough methods: + safeMethods: SAFE_METHODS, + + // optional prefix for internal methods + methodPrefix: WALLET_METHOD_PREFIX, + + restrictedMethods: this._restrictedMethods, + + /** + * A promise-returning callback used to determine whether to approve + * permissions requests or not. + * + * Currently only returns a boolean, but eventually should return any + * specific parameters or amendments to the permissions. + * + * @param {string} req - The internal rpc-cap user request object. + */ + requestUserApproval: async (req) => { + const { metadata: { id } } = req + + this._platform.openExtensionInBrowser('connect') + + return new Promise((resolve, reject) => { + this.pendingApprovals[id] = { resolve, reject } + }) + }, + }, initState) + } +} + +module.exports = { + PermissionsController, + addInternalMethodPrefix: prefix, + CAVEAT_NAMES, +} + + +function prefix (method) { + return WALLET_METHOD_PREFIX + method +} diff --git a/app/scripts/controllers/permissions/loggerMiddleware.js b/app/scripts/controllers/permissions/loggerMiddleware.js new file mode 100644 index 000000000..0e3c7f393 --- /dev/null +++ b/app/scripts/controllers/permissions/loggerMiddleware.js @@ -0,0 +1,169 @@ + +const clone = require('clone') +const { isValidAddress } = require('ethereumjs-util') + +const LOG_LIMIT = 100 + +/** + * Create middleware for logging requests and responses to restricted and + * permissions-related methods. + */ +module.exports = function createLoggerMiddleware ({ + walletPrefix, restrictedMethods, store, logStoreKey, historyStoreKey, ignoreMethods, +}) { + return (req, res, next, _end) => { + let activityEntry, requestedMethods + const { origin, method } = req + const isInternal = method.startsWith(walletPrefix) + if ((isInternal || restrictedMethods.includes(method)) && !ignoreMethods.includes(method)) { + activityEntry = logActivity(req, isInternal) + if (method === `${walletPrefix}requestPermissions`) { + requestedMethods = getRequestedMethods(req) + } + } else if (method === 'eth_requestAccounts') { + activityEntry = logActivity(req, isInternal) + requestedMethods = [ 'eth_accounts' ] + } else { + return next() + } + + next(cb => { + const time = Date.now() + addResponse(activityEntry, res, time) + if (!res.error && requestedMethods) { + logHistory(requestedMethods, origin, res.result, time, method === 'eth_requestAccounts') + } + cb() + }) + } + + function logActivity (request, isInternal) { + const activityEntry = { + id: request.id, + method: request.method, + methodType: isInternal ? 'internal' : 'restricted', + origin: request.origin, + request: cloneObj(request), + requestTime: Date.now(), + response: null, + responseTime: null, + success: null, + } + commitActivity(activityEntry) + return activityEntry + } + + function addResponse (activityEntry, response, time) { + if (!response) { + return + } + activityEntry.response = cloneObj(response) + activityEntry.responseTime = time + activityEntry.success = !response.error + } + + function commitActivity (entry) { + const logs = store.getState()[logStoreKey] + if (logs.length > LOG_LIMIT - 2) { + logs.pop() + } + logs.push(entry) + store.updateState({ [logStoreKey]: logs }) + } + + function getRequestedMethods (request) { + if ( + !request.params || + typeof request.params[0] !== 'object' || + Array.isArray(request.params[0]) + ) { + return null + } + return Object.keys(request.params[0]) + } + + function logHistory (requestedMethods, origin, result, time, isEthRequestAccounts) { + let accounts, entries + if (isEthRequestAccounts) { + accounts = result + const accountToTimeMap = accounts.reduce((acc, account) => ({ ...acc, [account]: time }), {}) + entries = { 'eth_accounts': { accounts: accountToTimeMap, lastApproved: time } } + } else { + entries = result + ? result + .map(perm => { + if (perm.parentCapability === 'eth_accounts') { + accounts = getAccountsFromPermission(perm) + } + return perm.parentCapability + }) + .reduce((acc, m) => { + if (requestedMethods.includes(m)) { + if (m === 'eth_accounts') { + const accountToTimeMap = accounts.reduce((acc, account) => ({ ...acc, [account]: time }), {}) + acc[m] = { lastApproved: time, accounts: accountToTimeMap } + } else { + acc[m] = { lastApproved: time } + } + } + return acc + }, {}) + : {} + } + + if (Object.keys(entries).length > 0) { + commitHistory(origin, entries) + } + } + + function commitHistory (origin, entries) { + const history = store.getState()[historyStoreKey] || {} + const newOriginHistory = { + ...history[origin], + ...entries, + } + + if (history[origin] && history[origin]['eth_accounts'] && entries['eth_accounts']) { + newOriginHistory['eth_accounts'] = { + lastApproved: entries['eth_accounts'].lastApproved, + accounts: { + ...history[origin]['eth_accounts'].accounts, + ...entries['eth_accounts'].accounts, + }, + } + } + + history[origin] = newOriginHistory + + store.updateState({ [historyStoreKey]: history }) + } +} + +// the call to clone is set to disallow circular references +// we attempt cloning at a depth of 3 and 2, then return a +// shallow copy of the object +function cloneObj (obj) { + for (let i = 3; i > 1; i--) { + try { + return clone(obj, false, i) + } catch (_) {} + } + return { ...obj } +} + +function getAccountsFromPermission (perm) { + if (perm.parentCapability !== 'eth_accounts' || !perm.caveats) { + return [] + } + const accounts = {} + for (const c of perm.caveats) { + if (c.type === 'filterResponse' && Array.isArray(c.value)) { + for (const v of c.value) { + if (isValidAddress(v)) { + accounts[v] = true + } + } + } + } + return Object.keys(accounts) +} diff --git a/app/scripts/controllers/permissions/methodMiddleware.js b/app/scripts/controllers/permissions/methodMiddleware.js new file mode 100644 index 000000000..e0b451c9f --- /dev/null +++ b/app/scripts/controllers/permissions/methodMiddleware.js @@ -0,0 +1,90 @@ + +const createAsyncMiddleware = require('json-rpc-engine/src/createAsyncMiddleware') +const { ethErrors } = require('eth-json-rpc-errors') + +/** + * Create middleware for handling certain methods and preprocessing permissions requests. + */ +module.exports = function createMethodMiddleware ({ + store, storeKey, getAccounts, requestAccountsPermission, +}) { + return createAsyncMiddleware(async (req, res, next) => { + + if (typeof req.method !== 'string') { + res.error = ethErrors.rpc.invalidRequest({ data: req}) + return + } + + switch (req.method) { + + // intercepting eth_accounts requests for backwards compatibility, + // i.e. return an empty array instead of an error + case 'eth_accounts': + + res.result = await getAccounts() + return + + case 'eth_requestAccounts': + + // first, just try to get accounts + let accounts = await getAccounts() + if (accounts.length > 0) { + res.result = accounts + return + } + + // if no accounts, request the accounts permission + try { + await requestAccountsPermission() + } catch (err) { + res.error = err + return + } + + // get the accounts again + accounts = await getAccounts() + if (accounts.length > 0) { + res.result = accounts + } else { + // this should never happen + res.error = ethErrors.rpc.internal( + 'Accounts unexpectedly unavailable. Please report this bug.' + ) + } + + return + + // custom method for getting metadata from the requesting domain + case 'wallet_sendDomainMetadata': + + const storeState = store.getState()[storeKey] + const extensionId = storeState[req.origin] + ? storeState[req.origin].extensionId + : undefined + + if ( + req.domainMetadata && + typeof req.domainMetadata.name === 'string' + ) { + + store.updateState({ + [storeKey]: { + ...storeState, + [req.origin]: { + extensionId, + ...req.domainMetadata, + }, + }, + }) + } + + res.result = true + return + + default: + break + } + + next() + }) +} diff --git a/app/scripts/controllers/permissions/permissions-safe-methods.json b/app/scripts/controllers/permissions/permissions-safe-methods.json new file mode 100644 index 000000000..17b46b531 --- /dev/null +++ b/app/scripts/controllers/permissions/permissions-safe-methods.json @@ -0,0 +1,49 @@ +[ + "web3_sha3", + "net_listening", + "net_peerCount", + "net_version", + "eth_blockNumber", + "eth_call", + "eth_chainId", + "eth_coinbase", + "eth_estimateGas", + "eth_gasPrice", + "eth_getBalance", + "eth_getBlockByHash", + "eth_getBlockByNumber", + "eth_getBlockTransactionCountByHash", + "eth_getBlockTransactionCountByNumber", + "eth_getCode", + "eth_getFilterChanges", + "eth_getFilterLogs", + "eth_getLogs", + "eth_getStorageAt", + "eth_getTransactionByBlockHashAndIndex", + "eth_getTransactionByBlockNumberAndIndex", + "eth_getTransactionByHash", + "eth_getTransactionCount", + "eth_getTransactionReceipt", + "eth_getUncleByBlockHashAndIndex", + "eth_getUncleByBlockNumberAndIndex", + "eth_getUncleCountByBlockHash", + "eth_getUncleCountByBlockNumber", + "eth_getWork", + "eth_hashrate", + "eth_mining", + "eth_newBlockFilter", + "eth_newFilter", + "eth_newPendingTransactionFilter", + "eth_protocolVersion", + "eth_sendRawTransaction", + "eth_sendTransaction", + "eth_sign", + "personal_sign", + "eth_signTypedData", + "eth_signTypedData_v1", + "eth_signTypedData_v3", + "eth_submitHashrate", + "eth_submitWork", + "eth_syncing", + "eth_uninstallFilter" +] \ No newline at end of file diff --git a/app/scripts/controllers/permissions/restrictedMethods.js b/app/scripts/controllers/permissions/restrictedMethods.js new file mode 100644 index 000000000..cd87b2d57 --- /dev/null +++ b/app/scripts/controllers/permissions/restrictedMethods.js @@ -0,0 +1,20 @@ + +module.exports = function getRestrictedMethods (permissionsController) { + return { + + 'eth_accounts': { + description: 'View the address of the selected account', + method: (_, res, __, end) => { + permissionsController.keyringController.getAccounts() + .then((accounts) => { + res.result = accounts + end() + }) + .catch((err) => { + res.error = err + end(err) + }) + }, + }, + } +} diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 22c6e999d..409ce6876 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -1,4 +1,5 @@ const ObservableStore = require('obs-store') +const { addInternalMethodPrefix } = require('./permissions') const normalizeAddress = require('eth-sig-util').normalize const { isValidAddress, sha3, bufferToHex } = require('ethereumjs-util') const extend = require('xtend') @@ -57,7 +58,6 @@ class PreferencesController { useNativeCurrencyAsPrimaryCurrency: true, }, completedOnboarding: false, - migratedPrivacyMode: false, metaMetricsId: null, metaMetricsSendCount: 0, }, opts.initState) @@ -187,7 +187,10 @@ class PreferencesController { * @param {Function} - end */ async requestWatchAsset (req, res, next, end) { - if (req.method === 'metamask_watchAsset' || req.method === 'wallet_watchAsset') { + if ( + req.method === 'metamask_watchAsset' || + req.method === addInternalMethodPrefix('watchAsset') + ) { const { type, options } = req.params switch (type) { case 'ERC20': @@ -644,13 +647,6 @@ class PreferencesController { return Promise.resolve(true) } - unsetMigratedPrivacyMode () { - this.store.updateState({ - migratedPrivacyMode: false, - }) - return Promise.resolve() - } - // // PRIVATE METHODS // diff --git a/app/scripts/controllers/provider-approval.js b/app/scripts/controllers/provider-approval.js deleted file mode 100644 index e54c7196f..000000000 --- a/app/scripts/controllers/provider-approval.js +++ /dev/null @@ -1,177 +0,0 @@ -const ObservableStore = require('obs-store') -const SafeEventEmitter = require('safe-event-emitter') -const createAsyncMiddleware = require('json-rpc-engine/src/createAsyncMiddleware') -const { errors: rpcErrors } = require('eth-json-rpc-errors') - -/** - * A controller that services user-approved requests for a full Ethereum provider API - */ -class ProviderApprovalController extends SafeEventEmitter { - /** - * Creates a ProviderApprovalController - * - * @param {Object} [config] - Options to configure controller - */ - constructor ({ closePopup, initState, keyringController, openPopup, preferencesController } = {}) { - super() - this.closePopup = closePopup - this.keyringController = keyringController - this.openPopup = openPopup - this.preferencesController = preferencesController - this.memStore = new ObservableStore({ - providerRequests: [], - }) - - const defaultState = { approvedOrigins: {} } - this.store = new ObservableStore(Object.assign(defaultState, initState)) - } - - /** - * Called when a user approves access to a full Ethereum provider API - * - * @param {object} opts - opts for the middleware contains the origin for the middleware - */ - createMiddleware ({ senderUrl, extensionId, getSiteMetadata }) { - return createAsyncMiddleware(async (req, res, next) => { - // only handle requestAccounts - if (req.method !== 'eth_requestAccounts') { - return next() - } - // if already approved or privacy mode disabled, return early - const isUnlocked = this.keyringController.memStore.getState().isUnlocked - const origin = senderUrl.hostname - if (this.shouldExposeAccounts(origin) && isUnlocked) { - res.result = [this.preferencesController.getSelectedAddress()] - return - } - // register the provider request - const metadata = { hostname: senderUrl.hostname, origin } - if (extensionId) { - metadata.extensionId = extensionId - } else { - const siteMetadata = await getSiteMetadata(origin) - Object.assign(metadata, { siteTitle: siteMetadata.name, siteImage: siteMetadata.icon}) - } - this._handleProviderRequest(metadata) - // wait for resolution of request - const approved = await new Promise(resolve => this.once(`resolvedRequest:${origin}`, ({ approved }) => resolve(approved))) - if (approved) { - res.result = [this.preferencesController.getSelectedAddress()] - } else { - throw rpcErrors.eth.userRejectedRequest('User denied account authorization') - } - }) - } - - /** - * @typedef {Object} SiteMetadata - * @param {string} hostname - The hostname of the site - * @param {string} origin - The origin of the site - * @param {string} [siteTitle] - The title of the site - * @param {string} [siteImage] - The icon for the site - * @param {string} [extensionId] - The extension ID of the extension - */ - /** - * Called when a tab requests access to a full Ethereum provider API - * - * @param {SiteMetadata} siteMetadata - The metadata for the site requesting full provider access - */ - _handleProviderRequest (siteMetadata) { - const { providerRequests } = this.memStore.getState() - const origin = siteMetadata.origin - this.memStore.updateState({ - providerRequests: [ - ...providerRequests, - siteMetadata, - ], - }) - const isUnlocked = this.keyringController.memStore.getState().isUnlocked - const { approvedOrigins } = this.store.getState() - const originAlreadyHandled = approvedOrigins[origin] - if (originAlreadyHandled && isUnlocked) { - return - } - this.openPopup && this.openPopup() - } - - /** - * Called when a user approves access to a full Ethereum provider API - * - * @param {string} origin - origin of the domain that had provider access approved - */ - approveProviderRequestByOrigin (origin) { - if (this.closePopup) { - this.closePopup() - } - - const { approvedOrigins } = this.store.getState() - const { providerRequests } = this.memStore.getState() - const providerRequest = providerRequests.find((request) => request.origin === origin) - const remainingProviderRequests = providerRequests.filter(request => request.origin !== origin) - this.store.updateState({ - approvedOrigins: { - ...approvedOrigins, - [origin]: { - siteTitle: providerRequest ? providerRequest.siteTitle : null, - siteImage: providerRequest ? providerRequest.siteImage : null, - hostname: providerRequest ? providerRequest.hostname : null, - }, - }, - }) - this.memStore.updateState({ providerRequests: remainingProviderRequests }) - this.emit(`resolvedRequest:${origin}`, { approved: true }) - } - - /** - * Called when a tab rejects access to a full Ethereum provider API - * - * @param {string} origin - origin of the domain that had provider access approved - */ - rejectProviderRequestByOrigin (origin) { - if (this.closePopup) { - this.closePopup() - } - - const { approvedOrigins } = this.store.getState() - const { providerRequests } = this.memStore.getState() - const remainingProviderRequests = providerRequests.filter(request => request.origin !== origin) - - // We're cloning and deleting keys here because we don't want to keep unneeded keys - const _approvedOrigins = Object.assign({}, approvedOrigins) - delete _approvedOrigins[origin] - - this.store.putState({ approvedOrigins: _approvedOrigins }) - this.memStore.putState({ providerRequests: remainingProviderRequests }) - this.emit(`resolvedRequest:${origin}`, { approved: false }) - } - - /** - * Clears any approvals for user-approved origins - */ - clearApprovedOrigins () { - this.store.updateState({ - approvedOrigins: {}, - }) - } - - /** - * Determines if a given origin should have accounts exposed - * - * @param {string} origin - Domain origin to check for approval status - * @returns {boolean} - True if the origin has been approved - */ - shouldExposeAccounts (origin) { - return Boolean(this.store.getState().approvedOrigins[origin]) - } - - /** - * Returns a merged state representation - * @return {object} - * @private - */ - _getMergedState () { - return Object.assign({}, this.memStore.getState(), this.store.getState()) - } -} - -module.exports = ProviderApprovalController diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index 31f8cc103..85733aa38 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -3,7 +3,7 @@ const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const Transaction = require('ethereumjs-tx') const EthQuery = require('ethjs-query') -const { errors: rpcErrors } = require('eth-json-rpc-errors') +const { ethErrors } = require('eth-json-rpc-errors') const abi = require('human-standard-token-abi') const abiDecoder = require('abi-decoder') abiDecoder.addABI(abi) @@ -54,6 +54,7 @@ const { hexToBn, bnToHex, BnMultiplyByFraction } = require('../../lib/util') @param {Object} opts.blockTracker - An instance of eth-blocktracker @param {Object} opts.provider - A network provider. @param {Function} opts.signTransaction - function the signs an ethereumjs-tx + @param {object} opts.getPermittedAccounts - get accounts that an origin has permissions for @param {Function} [opts.getGasPrice] - optional gas price calculator @param {Function} opts.signTransaction - ethTx signer that returns a rawTx @param {Number} [opts.txHistoryLimit] - number *optional* for limiting how many transactions are in state @@ -66,6 +67,7 @@ class TransactionController extends EventEmitter { this.networkStore = opts.networkStore || new ObservableStore({}) this.preferencesStore = opts.preferencesStore || new ObservableStore({}) this.provider = opts.provider + this.getPermittedAccounts = opts.getPermittedAccounts this.blockTracker = opts.blockTracker this.signEthTx = opts.signTransaction this.getGasPrice = opts.getGasPrice @@ -133,7 +135,7 @@ class TransactionController extends EventEmitter { /** Adds a tx to the txlist @emits ${txMeta.id}:unapproved -*/ + */ addTx (txMeta) { this.txStateManager.addTx(txMeta) this.emit(`${txMeta.id}:unapproved`, txMeta) @@ -148,18 +150,18 @@ class TransactionController extends EventEmitter { } /** - add a new unapproved transaction to the pipeline - - @returns {Promise} the hash of the transaction after being submitted to the network - @param txParams {object} - txParams for the transaction - @param opts {object} - with the key origin to put the origin on the txMeta + * Add a new unapproved transaction to the pipeline + * + * @returns {Promise} the hash of the transaction after being submitted to the network + * @param txParams {object} - txParams for the transaction + * @param opts {object} - with the key origin to put the origin on the txMeta */ - async newUnapprovedTransaction (txParams, opts = {}) { + log.debug(`MetaMaskController newUnapprovedTransaction ${JSON.stringify(txParams)}`) - const initialTxMeta = await this.addUnapprovedTransaction(txParams) - initialTxMeta.origin = opts.origin - this.txStateManager.updateTx(initialTxMeta, '#newUnapprovedTransaction - adding the origin') + + const initialTxMeta = await this.addUnapprovedTransaction(txParams, opts.origin) + // listen for tx completion (success, fail) return new Promise((resolve, reject) => { this.txStateManager.once(`${initialTxMeta.id}:finished`, (finishedTxMeta) => { @@ -167,30 +169,27 @@ class TransactionController extends EventEmitter { case 'submitted': return resolve(finishedTxMeta.hash) case 'rejected': - return reject(cleanErrorStack(rpcErrors.eth.userRejectedRequest('MetaMask Tx Signature: User denied transaction signature.'))) + return reject(cleanErrorStack(ethErrors.provider.userRejectedRequest('MetaMask Tx Signature: User denied transaction signature.'))) case 'failed': - return reject(cleanErrorStack(rpcErrors.internal(finishedTxMeta.err.message))) + return reject(cleanErrorStack(ethErrors.rpc.internal(finishedTxMeta.err.message))) default: - return reject(cleanErrorStack(rpcErrors.internal(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(finishedTxMeta.txParams)}`))) + return reject(cleanErrorStack(ethErrors.rpc.internal(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(finishedTxMeta.txParams)}`))) } }) }) } /** - Validates and generates a txMeta with defaults and puts it in txStateManager - store - - @returns {txMeta} - */ + * Validates and generates a txMeta with defaults and puts it in txStateManager + * store. + * + * @returns {txMeta} + */ + async addUnapprovedTransaction (txParams, origin) { - async addUnapprovedTransaction (txParams) { // validate const normalizedTxParams = txUtils.normalizeTxParams(txParams) - // Assert the from address is the selected address - if (normalizedTxParams.from !== this.getSelectedAddress()) { - throw new Error(`Transaction from address isn't valid for this account`) - } + txUtils.validateTxParams(normalizedTxParams) /** `generateTxMeta` adds the default txMeta properties to the passed object. @@ -202,6 +201,30 @@ class TransactionController extends EventEmitter { txParams: normalizedTxParams, type: TRANSACTION_TYPE_STANDARD, }) + + if (origin === 'metamask') { + // Assert the from address is the selected address + if (normalizedTxParams.from !== this.getSelectedAddress()) { + throw ethErrors.rpc.internal({ + message: `Internally initiated transaction is using invalid account.`, + data: { + origin, + fromAddress: normalizedTxParams.from, + selectedAddress: this.getSelectedAddress(), + }, + }) + } + } else { + // Assert that the origin has permissions to initiate transactions from + // the specified address + const permittedAddresses = await this.getPermittedAccounts(origin) + if (!permittedAddresses.includes(normalizedTxParams.from)) { + throw ethErrors.provider.unauthorized({ data: { origin }}) + } + } + + txMeta['origin'] = origin + const { transactionCategory, getCodeResponse } = await this._determineTransactionCategory(txParams) txMeta.transactionCategory = transactionCategory this.addTx(txMeta) @@ -222,15 +245,16 @@ class TransactionController extends EventEmitter { txMeta.loadingDefaults = false // save txMeta - this.txStateManager.updateTx(txMeta) + this.txStateManager.updateTx(txMeta, 'Added new unapproved transaction.') return txMeta } + /** - adds the tx gas defaults: gas && gasPrice - @param txMeta {Object} - the txMeta object - @returns {Promise} resolves with txMeta -*/ + * Adds the tx gas defaults: gas && gasPrice + * @param txMeta {Object} - the txMeta object + * @returns {Promise} resolves with txMeta + */ async addTxGasDefaults (txMeta, getCodeResponse) { const txParams = txMeta.txParams // ensure value @@ -416,6 +440,7 @@ class TransactionController extends EventEmitter { this.inProcessOfSigning.delete(txId) } } + /** adds the chain id and signs the transaction and set the status to signed @param txId {number} - the tx's Id diff --git a/app/scripts/createStandardProvider.js b/app/scripts/createStandardProvider.js deleted file mode 100644 index 2059b9b3a..000000000 --- a/app/scripts/createStandardProvider.js +++ /dev/null @@ -1,73 +0,0 @@ -class StandardProvider { - _isConnected - _provider - - constructor (provider) { - this._provider = provider - this._subscribe() - // indicate that we've connected, mostly just for standard compliance - setTimeout(() => { - this._onConnect() - }) - } - - _onClose () { - if (this._isConnected === undefined || this._isConnected) { - this._provider.emit('close', { - code: 1011, - reason: 'Network connection error', - }) - } - this._isConnected = false - } - - _onConnect () { - !this._isConnected && this._provider.emit('connect') - this._isConnected = true - } - - _subscribe () { - this._provider.on('data', (error, { method, params }) => { - if (!error && method === 'eth_subscription') { - this._provider.emit('notification', params.result) - } - }) - } - - /** - * Initiate an RPC method call - * - * @param {string} method - RPC method name to call - * @param {string[]} params - Array of RPC method parameters - * @returns {Promise<*>} Promise resolving to the result if successful - */ - send (method, params = []) { - return new Promise((resolve, reject) => { - try { - this._provider.sendAsync({ id: 1, jsonrpc: '2.0', method, params }, (error, response) => { - error = error || response.error - error ? reject(error) : resolve(response) - }) - } catch (error) { - reject(error) - } - }) - } -} - -/** - * Converts a legacy provider into an EIP-1193-compliant standard provider - * @param {Object} provider - Legacy provider to convert - * @returns {Object} Standard provider - */ -export default function createStandardProvider (provider) { - const standardProvider = new StandardProvider(provider) - const sendLegacy = provider.send - provider.send = (methodOrPayload, callbackOrArgs) => { - if (typeof methodOrPayload === 'string' && !callbackOrArgs || Array.isArray(callbackOrArgs)) { - return standardProvider.send(methodOrPayload, callbackOrArgs) - } - return sendLegacy.call(provider, methodOrPayload, callbackOrArgs) - } - return provider -} diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 0f752f1af..d81d8587b 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -1,6 +1,5 @@ /*global Web3*/ - // need to make sure we aren't affected by overlapping namespaces // and that we dont affect the app with our namespace // mostly a fix for web3's BigNumber if AMD's "define" is defined... @@ -32,17 +31,14 @@ const restoreContextAfterImports = () => { } cleanContextForImports() -require('web3/dist/web3.min.js') + const log = require('loglevel') const LocalMessageDuplexStream = require('post-message-stream') -const setupDappAutoReload = require('./lib/auto-reload.js') const MetamaskInpageProvider = require('metamask-inpage-provider') -const ObjectMultiplex = require('obj-multiplex') -const pump = require('pump') -const promisify = require('pify') -const createStandardProvider = require('./createStandardProvider').default -let warned = false +// TODO:deprecate:2020-01-13 +require('web3/dist/web3.min.js') +const setupDappAutoReload = require('./lib/auto-reload.js') restoreContextAfterImports() @@ -64,106 +60,6 @@ const inpageProvider = new MetamaskInpageProvider(metamaskStream) // set a high max listener count to avoid unnecesary warnings inpageProvider.setMaxListeners(100) -const pageMux = new ObjectMultiplex() -const onboardingStream = pageMux.createStream('onboarding') -pump( - pageMux, - metamaskStream, - error => log.error('MetaMask muxed in-page traffic failed', error) -) - -let warnedOfAutoRefreshDeprecation = false -// augment the provider with its enable method -inpageProvider.enable = function ({ force } = {}) { - if ( - !warnedOfAutoRefreshDeprecation && - inpageProvider.autoRefreshOnNetworkChange - ) { - console.warn(`MetaMask: MetaMask will soon stop reloading pages on network change. -If you rely upon this behavior, add a 'networkChanged' event handler to trigger the reload manually: https://metamask.github.io/metamask-docs/API_Reference/Ethereum_Provider#ethereum.on(eventname%2C-callback) -Set 'ethereum.autoRefreshOnNetworkChange' to 'false' to silence this warning: https://metamask.github.io/metamask-docs/API_Reference/Ethereum_Provider#ethereum.autorefreshonnetworkchange' -`) - warnedOfAutoRefreshDeprecation = true - } - return new Promise((resolve, reject) => { - inpageProvider.sendAsync({ method: 'eth_requestAccounts', params: [force] }, (error, response) => { - if (error || response.error) { - reject(error || response.error) - } else { - resolve(response.result) - } - }) - }) -} - -// give the dapps control of a refresh they can toggle this off on the window.ethereum -// this will be default true so it does not break any old apps. -inpageProvider.autoRefreshOnNetworkChange = true - - -// publicConfig isn't populated until we get a message from background. -// Using this getter will ensure the state is available -const getPublicConfigWhenReady = async () => { - const store = inpageProvider.publicConfigStore - let state = store.getState() - // if state is missing, wait for first update - if (!state.networkVersion) { - state = await new Promise(resolve => store.once('update', resolve)) - console.log('new state', state) - } - return state -} - -// add metamask-specific convenience methods -inpageProvider._metamask = new Proxy({ - /** - * Synchronously determines if this domain is currently enabled, with a potential false negative if called to soon - * - * @returns {boolean} - returns true if this domain is currently enabled - */ - isEnabled: function () { - const { isEnabled } = inpageProvider.publicConfigStore.getState() - return Boolean(isEnabled) - }, - - /** - * Asynchronously determines if this domain is currently enabled - * - * @returns {Promise} - Promise resolving to true if this domain is currently enabled - */ - isApproved: async function () { - const { isEnabled } = await getPublicConfigWhenReady() - return Boolean(isEnabled) - }, - - /** - * Determines if MetaMask is unlocked by the user - * - * @returns {Promise} - Promise resolving to true if MetaMask is currently unlocked - */ - isUnlocked: async function () { - const { isUnlocked } = await getPublicConfigWhenReady() - return Boolean(isUnlocked) - }, - - /** - * Registers a page as having initated onboarding. This facilitates MetaMask focusing the initiating tab after onboarding. - * - * @returns {Promise} - Promise resolving to undefined - */ - registerOnboarding: async () => { - await promisify(onboardingStream.write({ type: 'registerOnboarding' })) - }, -}, { - get: function (obj, prop) { - !warned && console.warn('Heads up! ethereum._metamask exposes methods that have ' + - 'not been standardized yet. This means that these methods may not be implemented ' + - 'in other dapp browsers and may be removed from MetaMask in the future.') - warned = true - return obj[prop] - }, -}) - // Work around for web3@1.0 deleting the bound `sendAsync` but not the unbound // `sendAsync` method on the prototype, causing `this` reference issues const proxiedInpageProvider = new Proxy(inpageProvider, { @@ -172,12 +68,12 @@ const proxiedInpageProvider = new Proxy(inpageProvider, { deleteProperty: () => true, }) -window.ethereum = createStandardProvider(proxiedInpageProvider) - // -// setup web3 +// TODO:deprecate:2020-01-13 // +// setup web3 + if (typeof window.web3 !== 'undefined') { throw new Error(`MetaMask detected another web3. MetaMask will not work reliably with another web3 extension. @@ -192,9 +88,13 @@ web3.setProvider = function () { } log.debug('MetaMask - injected web3') -setupDappAutoReload(web3, inpageProvider.publicConfigStore) +proxiedInpageProvider._web3Ref = web3.eth -// set web3 defaultAccount -inpageProvider.publicConfigStore.subscribe(function (state) { - web3.eth.defaultAccount = state.selectedAddress -}) +// setup dapp auto reload AND proxy web3 +setupDappAutoReload(web3, inpageProvider._publicConfigStore) + +// +// end deprecate:2020-01-13 +// + +window.ethereum = proxiedInpageProvider diff --git a/app/scripts/lib/auto-reload.js b/app/scripts/lib/auto-reload.js index 343191f4c..e2b9c17bd 100644 --- a/app/scripts/lib/auto-reload.js +++ b/app/scripts/lib/auto-reload.js @@ -1,3 +1,6 @@ + +// TODO:deprecate:2020-01-13 + module.exports = setupDappAutoReload function setupDappAutoReload (web3, observable) { @@ -13,7 +16,7 @@ function setupDappAutoReload (web3, observable) { lastTimeUsed = Date.now() // show warning once on web3 access if (!hasBeenWarned && key !== 'currentProvider') { - console.warn('MetaMask: web3 will be deprecated in the near future in favor of the ethereumProvider\nhttps://medium.com/metamask/4a899ad6e59e') + console.warn(`MetaMask: On 2020-01-13, MetaMask will no longer inject web3. For more information, see: https://medium.com/metamask/no-longer-injecting-web3-js-4a899ad6e59e`) hasBeenWarned = true } // return value normally diff --git a/app/scripts/lib/createOriginMiddleware.js b/app/scripts/lib/createOriginMiddleware.js index 98bb0e3b3..4ff9a3386 100644 --- a/app/scripts/lib/createOriginMiddleware.js +++ b/app/scripts/lib/createOriginMiddleware.js @@ -1,3 +1,4 @@ + module.exports = createOriginMiddleware /** diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index 49294c84d..b7212c980 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -1,5 +1,6 @@ const extension = require('extensionizer') const log = require('loglevel') +const { checkForError } = require('./util') /** * A wrapper around the extension's storage local API @@ -90,21 +91,3 @@ module.exports = class ExtensionStore { function isEmpty (obj) { return Object.keys(obj).length === 0 } - -/** - * Returns an Error if extension.runtime.lastError is present - * this is a workaround for the non-standard error object thats used - * @returns {Error} - */ -function checkForError () { - const lastError = extension.runtime.lastError - if (!lastError) { - return - } - // if it quacks like an Error, its an Error - if (lastError.stack && lastError.message) { - return lastError - } - // repair incomplete error object (eg chromium v77) - return new Error(lastError.message) -} diff --git a/app/scripts/lib/message-manager.js b/app/scripts/lib/message-manager.js index c66b3a9e1..a947188e5 100644 --- a/app/scripts/lib/message-manager.js +++ b/app/scripts/lib/message-manager.js @@ -1,7 +1,7 @@ const EventEmitter = require('events') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') -const { errors: rpcErrors } = require('eth-json-rpc-errors') +const { ethErrors } = require('eth-json-rpc-errors') const createId = require('./random-id') /** @@ -85,7 +85,7 @@ module.exports = class MessageManager extends EventEmitter { case 'signed': return resolve(data.rawSig) case 'rejected': - return reject(rpcErrors.eth.userRejectedRequest('MetaMask Message Signature: User denied message signature.')) + return reject(ethErrors.provider.userRejectedRequest('MetaMask Message Signature: User denied message signature.')) default: return reject(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`)) } diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index c538ef17f..fb30cc03c 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -1,7 +1,7 @@ const EventEmitter = require('events') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') -const { errors: rpcErrors } = require('eth-json-rpc-errors') +const { ethErrors } = require('eth-json-rpc-errors') const createId = require('./random-id') const hexRe = /^[0-9A-Fa-f]+$/g const log = require('loglevel') @@ -91,7 +91,7 @@ module.exports = class PersonalMessageManager extends EventEmitter { case 'signed': return resolve(data.rawSig) case 'rejected': - return reject(rpcErrors.eth.userRejectedRequest('MetaMask Message Signature: User denied message signature.')) + return reject(ethErrors.provider.userRejectedRequest('MetaMask Message Signature: User denied message signature.')) default: return reject(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`)) } diff --git a/app/scripts/lib/typed-message-manager.js b/app/scripts/lib/typed-message-manager.js index 7a73e7761..5e3c48038 100644 --- a/app/scripts/lib/typed-message-manager.js +++ b/app/scripts/lib/typed-message-manager.js @@ -2,7 +2,7 @@ const EventEmitter = require('events') const ObservableStore = require('obs-store') const createId = require('./random-id') const assert = require('assert') -const { errors: rpcErrors } = require('eth-json-rpc-errors') +const { ethErrors } = require('eth-json-rpc-errors') const sigUtil = require('eth-sig-util') const log = require('loglevel') const jsonschema = require('jsonschema') @@ -81,7 +81,7 @@ module.exports = class TypedMessageManager extends EventEmitter { case 'signed': return resolve(data.rawSig) case 'rejected': - return reject(rpcErrors.eth.userRejectedRequest('MetaMask Message Signature: User denied message signature.')) + return reject(ethErrors.provider.userRejectedRequest('MetaMask Message Signature: User denied message signature.')) case 'errored': return reject(new Error(`MetaMask Message Signature: ${data.error}`)) default: diff --git a/app/scripts/lib/util.js b/app/scripts/lib/util.js index 114203d7f..36b836eb1 100644 --- a/app/scripts/lib/util.js +++ b/app/scripts/lib/util.js @@ -1,3 +1,4 @@ +const extension = require('extensionizer') const ethUtil = require('ethereumjs-util') const assert = require('assert') const BN = require('bn.js') @@ -148,6 +149,32 @@ function getRandomArrayItem (array) { return array[Math.floor((Math.random() * array.length))] } +function mapObjectValues (object, cb) { + const mappedObject = {} + Object.keys(object).forEach(key => { + mappedObject[key] = cb(key, object[key]) + }) + return mappedObject +} + +/** + * Returns an Error if extension.runtime.lastError is present + * this is a workaround for the non-standard error object thats used + * @returns {Error} + */ +function checkForError () { + const lastError = extension.runtime.lastError + if (!lastError) { + return + } + // if it quacks like an Error, its an Error + if (lastError.stack && lastError.message) { + return lastError + } + // repair incomplete error object (eg chromium v77) + return new Error(lastError.message) +} + module.exports = { removeListeners, applyListeners, @@ -159,4 +186,6 @@ module.exports = { bnToHex, BnMultiplyByFraction, getRandomArrayItem, + mapObjectValues, + checkForError, } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 9b38451a4..246ae511d 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -8,11 +8,9 @@ const assert = require('assert').strict const EventEmitter = require('events') const pump = require('pump') const Dnode = require('dnode') -const pify = require('pify') const extension = require('extensionizer') const ObservableStore = require('obs-store') const ComposableObservableStore = require('./lib/ComposableObservableStore') -const createDnodeRemoteGetter = require('./lib/createDnodeRemoteGetter') const asStream = require('obs-store/lib/asStream') const AccountTracker = require('./lib/account-tracker') const RpcEngine = require('json-rpc-engine') @@ -20,8 +18,8 @@ const debounce = require('debounce') const createEngineStream = require('json-rpc-middleware-stream/engineStream') const createFilterMiddleware = require('eth-json-rpc-filters') const createSubscriptionManager = require('eth-json-rpc-filters/subscriptionManager') -const createOriginMiddleware = require('./lib/createOriginMiddleware') const createLoggerMiddleware = require('./lib/createLoggerMiddleware') +const createOriginMiddleware = require('./lib/createOriginMiddleware') const providerAsMiddleware = require('eth-json-rpc-middleware/providerAsMiddleware') const {setupMultiplex} = require('./lib/stream-utils.js') const KeyringController = require('eth-keyring-controller') @@ -41,8 +39,8 @@ const TypedMessageManager = require('./lib/typed-message-manager') const TransactionController = require('./controllers/transactions') const TokenRatesController = require('./controllers/token-rates') const DetectTokensController = require('./controllers/detect-tokens') -const ProviderApprovalController = require('./controllers/provider-approval') const ABTestController = require('./controllers/ab-test') +const { PermissionsController } = require('./controllers/permissions/') const nodeify = require('./lib/nodeify') const accountImporter = require('./account-import-strategies') const getBuyEthUrl = require('./lib/buy-eth-url') @@ -58,6 +56,7 @@ const TrezorKeyring = require('eth-trezor-keyring') const LedgerBridgeKeyring = require('eth-ledger-bridge-keyring') const EthQuery = require('eth-query') const ethUtil = require('ethereumjs-util') +const nanoid = require('nanoid') const contractMap = require('eth-contract-metadata') const { AddressBookController, @@ -90,16 +89,24 @@ module.exports = class MetamaskController extends EventEmitter { // platform-specific api this.platform = opts.platform + this.getRequestAccountTabIds = opts.getRequestAccountTabIds + this.getOpenMetamaskTabsIds = opts.getOpenMetamaskTabsIds + // observable state store this.store = new ComposableObservableStore(initState) + // external connections by origin + // Do not modify directly. Use the associated methods. + this.connections = {} + // lock to ensure only one vault created at once this.createVaultMutex = new Mutex() - // network store + // next, we will initialize the controllers + // controller initializaiton order matters + this.networkController = new NetworkController(initState.NetworkController) - // preferences controller this.preferencesController = new PreferencesController({ initState: initState.PreferencesController, initLangCode: opts.initLangCode, @@ -107,17 +114,14 @@ module.exports = class MetamaskController extends EventEmitter { network: this.networkController, }) - // app-state controller this.appStateController = new AppStateController({ preferencesStore: this.preferencesController.store, onInactiveTimeout: () => this.setLocked(), initState: initState.AppStateController, }) - // currency controller this.currencyRateController = new CurrencyRateController(undefined, initState.CurrencyController) - // infura controller this.infuraController = new InfuraController({ initState: initState.InfuraController, }) @@ -125,7 +129,7 @@ module.exports = class MetamaskController extends EventEmitter { this.phishingController = new PhishingController() - // rpc provider + // now we can initialize the RPC provider, which other controllers require this.initializeProvider() this.provider = this.networkController.getProviderAndBlockTracker().provider this.blockTracker = this.networkController.getProviderAndBlockTracker().blockTracker @@ -154,7 +158,7 @@ module.exports = class MetamaskController extends EventEmitter { initState: initState.IncomingTransactionsController, }) - // account tracker watches balances, nonces, and any code at their address. + // account tracker watches balances, nonces, and any code at their address this.accountTracker = new AccountTracker({ provider: this.provider, blockTracker: this.blockTracker, @@ -188,7 +192,6 @@ module.exports = class MetamaskController extends EventEmitter { this.accountTracker._updateAccounts() }) - // key mgmt const additionalKeyrings = [TrezorKeyring, LedgerBridgeKeyring] this.keyringController = new KeyringController({ keyringTypes: additionalKeyrings, @@ -196,16 +199,25 @@ module.exports = class MetamaskController extends EventEmitter { getNetwork: this.networkController.getNetworkState.bind(this.networkController), encryptor: opts.encryptor || undefined, }) - this.keyringController.memStore.subscribe((s) => this._onKeyringControllerUpdate(s)) - // detect tokens controller + this.permissionsController = new PermissionsController({ + keyringController: this.keyringController, + platform: opts.platform, + notifyDomain: this.notifyConnections.bind(this), + notifyAllDomains: this.notifyAllConnections.bind(this), + }, initState.PermissionsController, initState.PermissionsMetadata) + this.detectTokensController = new DetectTokensController({ preferences: this.preferencesController, network: this.networkController, keyringMemStore: this.keyringController.memStore, }) + this.abTestController = new ABTestController({ + initState: initState.ABTestController, + }) + this.addressBookController = new AddressBookController(undefined, initState.AddressBookController) this.threeBoxController = new ThreeBoxController({ @@ -217,9 +229,9 @@ module.exports = class MetamaskController extends EventEmitter { version, }) - // tx mgmt this.txController = new TransactionController({ initState: initState.TransactionController || initState.TransactionManager, + getPermittedAccounts: this.permissionsController.getAccounts.bind(this.permissionsController), networkStore: this.networkController.networkStore, preferencesStore: this.preferencesController.store, txHistoryLimit: 40, @@ -270,18 +282,6 @@ module.exports = class MetamaskController extends EventEmitter { this.isClientOpenAndUnlocked = memState.isUnlocked && this._isClientOpen }) - this.providerApprovalController = new ProviderApprovalController({ - closePopup: opts.closePopup, - initState: initState.ProviderApprovalController, - keyringController: this.keyringController, - openPopup: opts.openPopup, - preferencesController: this.preferencesController, - }) - - this.abTestController = new ABTestController({ - initState: initState.ABTestController, - }) - this.store.updateStructure({ AppStateController: this.appStateController.store, TransactionController: this.txController.store, @@ -294,10 +294,11 @@ module.exports = class MetamaskController extends EventEmitter { InfuraController: this.infuraController.store, CachedBalancesController: this.cachedBalancesController.store, OnboardingController: this.onboardingController.store, - ProviderApprovalController: this.providerApprovalController.store, IncomingTransactionsController: this.incomingTransactionsController.store, - ThreeBoxController: this.threeBoxController.store, ABTestController: this.abTestController.store, + PermissionsController: this.permissionsController.permissions, + PermissionsMetadata: this.permissionsController.store, + ThreeBoxController: this.threeBoxController.store, }) this.memStore = new ComposableObservableStore(null, { @@ -318,11 +319,9 @@ module.exports = class MetamaskController extends EventEmitter { ShapeshiftController: this.shapeshiftController, InfuraController: this.infuraController.store, OnboardingController: this.onboardingController.store, - // ProviderApprovalController - ProviderApprovalController: this.providerApprovalController.store, - ProviderApprovalControllerMemStore: this.providerApprovalController.memStore, IncomingTransactionsController: this.incomingTransactionsController.store, - // ThreeBoxController + PermissionsController: this.permissionsController.permissions, + PermissionsMetadata: this.permissionsController.store, ThreeBoxController: this.threeBoxController.store, ABTestController: this.abTestController.store, // ENS Controller @@ -343,20 +342,15 @@ module.exports = class MetamaskController extends EventEmitter { version, // account mgmt getAccounts: async ({ origin }) => { - // Expose no accounts if this origin has not been approved, preventing - // account-requring RPC methods from completing successfully - const exposeAccounts = this.providerApprovalController.shouldExposeAccounts(origin) - if (origin !== 'metamask' && !exposeAccounts) { - return [] - } - const isUnlocked = this.keyringController.memStore.getState().isUnlocked - const selectedAddress = this.preferencesController.getSelectedAddress() - // only show address if account is unlocked - if (isUnlocked && selectedAddress) { - return [selectedAddress] - } else { - return [] + if (origin === 'metamask') { + const selectedAddress = this.preferencesController.getSelectedAddress() + return selectedAddress ? [selectedAddress] : [] + } else if ( + this.keyringController.memStore.getState().isUnlocked + ) { + return await this.permissionsController.getAccounts(origin) } + return [] // changing this is a breaking change }, // tx signing processTransaction: this.newUnapprovedTransaction.bind(this), @@ -377,7 +371,7 @@ module.exports = class MetamaskController extends EventEmitter { * Constructor helper: initialize a public config store. * This store is used to make some config info available to Dapps synchronously. */ - createPublicConfigStore ({ checkIsEnabled }) { + createPublicConfigStore () { // subset of state for metamask inpage provider const publicConfigStore = new ObservableStore() @@ -390,23 +384,16 @@ module.exports = class MetamaskController extends EventEmitter { } function updatePublicConfigStore (memState) { - const publicState = selectPublicState(memState) - publicConfigStore.putState(publicState) + publicConfigStore.putState(selectPublicState(memState)) } - function selectPublicState ({ isUnlocked, selectedAddress, network, provider }) { - const isEnabled = checkIsEnabled() - const isReady = isUnlocked && isEnabled - const result = { + function selectPublicState ({ isUnlocked, network, provider }) { + return { isUnlocked, - isEnabled, - selectedAddress: isReady ? selectedAddress : null, networkVersion: network, chainId: selectChainId({ network, provider }), } - return result } - return publicConfigStore } @@ -438,13 +425,13 @@ module.exports = class MetamaskController extends EventEmitter { */ getApi () { const keyringController = this.keyringController - const preferencesController = this.preferencesController - const txController = this.txController const networkController = this.networkController - const providerApprovalController = this.providerApprovalController const onboardingController = this.onboardingController + const permissionsController = this.permissionsController + const preferencesController = this.preferencesController const threeBoxController = this.threeBoxController const abTestController = this.abTestController + const txController = this.txController return { // etc @@ -502,7 +489,6 @@ module.exports = class MetamaskController extends EventEmitter { setPreference: nodeify(preferencesController.setPreference, preferencesController), completeOnboarding: nodeify(preferencesController.completeOnboarding, preferencesController), addKnownMethodData: nodeify(preferencesController.addKnownMethodData, preferencesController), - unsetMigratedPrivacyMode: nodeify(preferencesController.unsetMigratedPrivacyMode, preferencesController), // BlacklistController whitelistPhishingDomain: this.whitelistPhishingDomain.bind(this), @@ -550,11 +536,6 @@ module.exports = class MetamaskController extends EventEmitter { signTypedMessage: nodeify(this.signTypedMessage, this), cancelTypedMessage: this.cancelTypedMessage.bind(this), - // provider approval - approveProviderRequestByOrigin: providerApprovalController.approveProviderRequestByOrigin.bind(providerApprovalController), - rejectProviderRequestByOrigin: providerApprovalController.rejectProviderRequestByOrigin.bind(providerApprovalController), - clearApprovedOrigins: providerApprovalController.clearApprovedOrigins.bind(providerApprovalController), - // onboarding controller setSeedPhraseBackedUp: nodeify(onboardingController.setSeedPhraseBackedUp, onboardingController), @@ -568,10 +549,21 @@ module.exports = class MetamaskController extends EventEmitter { // a/b test controller getAssignedABTestGroupName: nodeify(abTestController.getAssignedABTestGroupName, abTestController), + + // permissions + approvePermissionsRequest: nodeify(permissionsController.approvePermissionsRequest, permissionsController), + clearPermissions: permissionsController.clearPermissions.bind(permissionsController), + getApprovedAccounts: nodeify(permissionsController.getAccounts.bind(permissionsController)), + rejectPermissionsRequest: nodeify(permissionsController.rejectPermissionsRequest, permissionsController), + removePermissionsFor: permissionsController.removePermissionsFor.bind(permissionsController), + updateExposedAccounts: nodeify(permissionsController.updateExposedAccounts, permissionsController), + legacyExposeAccounts: nodeify(permissionsController.legacyExposeAccounts, permissionsController), + + getRequestAccountTabIds: (cb) => cb(null, this.getRequestAccountTabIds()), + getOpenMetamaskTabsIds: (cb) => cb(null, this.getOpenMetamaskTabsIds()), } } - //============================================================================= // VAULT / KEYRING RELATED METHODS //============================================================================= @@ -1351,10 +1343,10 @@ module.exports = class MetamaskController extends EventEmitter { // setup multiplexing const mux = setupMultiplex(connectionStream) - // connect features - const publicApi = this.setupPublicApi(mux.createStream('publicApi')) - this.setupProviderConnection(mux.createStream('provider'), senderUrl, extensionId, publicApi) - this.setupPublicConfig(mux.createStream('publicConfig'), senderUrl) + + // messages between inpage and background + this.setupProviderConnection(mux.createStream('provider'), senderUrl, extensionId) + this.setupPublicConfig(mux.createStream('publicConfig')) } /** @@ -1432,13 +1424,15 @@ module.exports = class MetamaskController extends EventEmitter { * resource is an extension. * @param {object} publicApi - The public API */ - setupProviderConnection (outStream, senderUrl, extensionId, publicApi) { - const getSiteMetadata = publicApi && publicApi.getSiteMetadata - const engine = this.setupProviderEngine(senderUrl, extensionId, getSiteMetadata) + setupProviderConnection (outStream, senderUrl, extensionId) { + const origin = senderUrl.hostname + const engine = this.setupProviderEngine(senderUrl, extensionId) // setup connection const providerStream = createEngineStream({ engine }) + const connectionId = this.addConnection(origin, { engine }) + pump( outStream, providerStream, @@ -1450,6 +1444,7 @@ module.exports = class MetamaskController extends EventEmitter { mid.destroy() } }) + connectionId && this.removeConnection(origin, connectionId) if (err) { log.error(err) } @@ -1460,7 +1455,8 @@ module.exports = class MetamaskController extends EventEmitter { /** * A method for creating a provider that is safely restricted for the requesting domain. **/ - setupProviderEngine (senderUrl, extensionId, getSiteMetadata) { + setupProviderEngine (senderUrl, extensionId) { + const origin = senderUrl.hostname // setup json rpc engine stack const engine = new RpcEngine() @@ -1474,20 +1470,17 @@ module.exports = class MetamaskController extends EventEmitter { const subscriptionManager = createSubscriptionManager({ provider, blockTracker }) subscriptionManager.events.on('notification', (message) => engine.emit('notification', message)) - // metadata + // append origin to each request engine.push(createOriginMiddleware({ origin })) + // logging engine.push(createLoggerMiddleware({ origin })) // filter and subscription polyfills engine.push(filterMiddleware) engine.push(subscriptionManager.middleware) + // permissions + engine.push(this.permissionsController.createMiddleware({ origin, extensionId })) // watch asset engine.push(this.preferencesController.requestWatchAsset.bind(this.preferencesController)) - // requestAccounts - engine.push(this.providerApprovalController.createMiddleware({ - senderUrl, - extensionId, - getSiteMetadata, - })) // forward to metamask primary provider engine.push(providerAsMiddleware(provider)) return engine @@ -1502,13 +1495,9 @@ module.exports = class MetamaskController extends EventEmitter { * this is a good candidate for deprecation. * * @param {*} outStream - The stream to provide public config over. - * @param {URL} senderUrl - The URL of requesting resource */ - setupPublicConfig (outStream, senderUrl) { - const configStore = this.createPublicConfigStore({ - // check the providerApprovalController's approvedOrigins - checkIsEnabled: () => this.providerApprovalController.shouldExposeAccounts(senderUrl.hostname), - }) + setupPublicConfig (outStream) { + const configStore = this.createPublicConfigStore() const configStream = asStream(configStore) pump( @@ -1524,6 +1513,8 @@ module.exports = class MetamaskController extends EventEmitter { ) } + // manage external connections + onMessage (message, sender, sendResponse) { if (!message || !message.type) { log.debug(`Ignoring invalid message: '${JSON.stringify(message)}'`) @@ -1562,39 +1553,98 @@ module.exports = class MetamaskController extends EventEmitter { } /** - * A method for providing our public api over a stream. - * This includes a method for setting site metadata like title and image + * Adds a reference to a connection by origin. Ignores the 'metamask' origin. + * Caller must ensure that the returned id is stored such that the reference + * can be deleted later. * - * @param {*} outStream - The stream to provide the api over. + * @param {string} origin - The connection's origin string. + * @param {Object} options - Data associated with the connection + * @param {Object} options.engine - The connection's JSON Rpc Engine + * @returns {string} - The connection's id (so that it can be deleted later) */ - setupPublicApi (outStream) { - const dnode = Dnode() - // connect dnode api to remote connection - pump( - outStream, - dnode, - outStream, - (err) => { - // report any error - if (err) { - log.error(err) - } - } - ) + addConnection (origin, { engine }) { + + if (origin === 'metamask') { + return null + } - const getRemote = createDnodeRemoteGetter(dnode) + if (!this.connections[origin]) { + this.connections[origin] = {} + } - const publicApi = { - // wrap with an await remote - getSiteMetadata: async () => { - const remote = await getRemote() - return await pify(remote.getSiteMetadata)() - }, + const id = nanoid() + this.connections[origin][id] = { + engine, + } + + return id + } + + /** + * Deletes a reference to a connection, by origin and id. + * Ignores unknown origins. + * + * @param {string} origin - The connection's origin string. + * @param {string} id - The connection's id, as returned from addConnection. + */ + removeConnection (origin, id) { + + const connections = this.connections[origin] + if (!connections) { + return + } + + delete connections[id] + + if (Object.keys(connections.length === 0)) { + delete this.connections[origin] + } + } + + /** + * Causes the RPC engines associated with the connections to the given origin + * to emit a notification event with the given payload. + * Does nothing if the extension is locked or the origin is unknown. + * + * @param {string} origin - The connection's origin string. + * @param {any} payload - The event payload. + */ + notifyConnections (origin, payload) { + + const { isUnlocked } = this.getState() + const connections = this.connections[origin] + if (!isUnlocked || !connections) { + return } - return publicApi + Object.values(connections).forEach(conn => { + conn.engine && conn.engine.emit('notification', payload) + }) } + /** + * Causes the RPC engines associated with all connections to emit a + * notification event with the given payload. + * Does nothing if the extension is locked. + * + * @param {any} payload - The event payload. + */ + notifyAllConnections (payload) { + + const { isUnlocked } = this.getState() + if (!isUnlocked) { + return + } + + Object.values(this.connections).forEach(origin => { + Object.values(origin).forEach(conn => { + conn.engine && conn.engine.emit('notification', payload) + }) + }) + } + + // handlers + /** * Handle a KeyringController update * @param {object} state the KC state @@ -1623,6 +1673,8 @@ module.exports = class MetamaskController extends EventEmitter { } } + // misc + /** * A method for emitting the full MetaMask state to all registered listeners. * @private @@ -1631,6 +1683,10 @@ module.exports = class MetamaskController extends EventEmitter { this.emit('update', this.getState()) } + //============================================================================= + // MISCELLANEOUS + //============================================================================= + /** * A method for estimating a good gas price at recent prices. * Returns the lowest price that would have been included in diff --git a/app/scripts/migrations/029.js b/app/scripts/migrations/029.js index e17479ccc..59724c154 100644 --- a/app/scripts/migrations/029.js +++ b/app/scripts/migrations/029.js @@ -24,4 +24,3 @@ module.exports = { return isApproved && now - createdTime > unacceptableDelay }), } - diff --git a/app/scripts/migrations/040.js b/app/scripts/migrations/040.js new file mode 100644 index 000000000..042f499b2 --- /dev/null +++ b/app/scripts/migrations/040.js @@ -0,0 +1,23 @@ +const version = 40 +const clone = require('clone') + +/** + * Site connections are now managed by the PermissionsController, and the + * ProviderApprovalController is removed. This migration deletes all + * ProviderApprovalController state. + */ +module.exports = { + version, + migrate: async function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + const state = versionedData.data + versionedData.data = transformState(state) + return versionedData + }, +} + +function transformState (state) { + delete state.ProviderApprovalController + return state +} diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index d54a8a7b3..5ae05d230 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -1,7 +1,7 @@ const extension = require('extensionizer') const {createExplorerLink: explorerLink} = require('etherscan-link') -const {getEnvironmentType} = require('../lib/util') +const { getEnvironmentType, checkForError } = require('../lib/util') const {ENVIRONMENT_TYPE_BACKGROUND} = require('../lib/enums') class ExtensionPlatform { @@ -66,6 +66,58 @@ class ExtensionPlatform { } } + queryTabs () { + return new Promise((resolve, reject) => { + extension.tabs.query({}, tabs => { + const err = checkForError() + if (err) { + reject(err) + } else { + resolve(tabs) + } + }) + }) + } + + currentTab () { + return new Promise((resolve, reject) => { + extension.tabs.getCurrent(tab => { + const err = checkForError() + if (err) { + reject(err) + } else { + resolve(tab) + } + }) + }) + } + + switchToTab (tabId) { + return new Promise((resolve, reject) => { + extension.tabs.update(tabId, {highlighted: true}, (tab) => { + const err = checkForError() + if (err) { + reject(err) + } else { + resolve(tab) + } + }) + }) + } + + closeTab (tabId) { + return new Promise((resolve, reject) => { + extension.tabs.remove(tabId, () => { + const err = checkForError() + if (err) { + reject(err) + } else { + resolve() + } + }) + }) + } + _showConfirmedTransaction (txMeta) { this._subscribeToNotificationClicked() diff --git a/docs/porting_to_new_environment.md b/docs/porting_to_new_environment.md index 9cb8e9c2d..92f06f37d 100644 --- a/docs/porting_to_new_environment.md +++ b/docs/porting_to_new_environment.md @@ -18,8 +18,8 @@ const providerFromEngine = require('eth-json-rpc-middleware/providerFromEngine') /** * returns a provider restricted to the requesting domain **/ -function incomingConnection (domain, getSiteMetadata) { - const engine = metamaskController.setupProviderEngine(domain, getSiteMetadata) +function incomingConnection (domain) { + const engine = metamaskController.setupProviderEngine(domain) const provider = providerFromEngine(engine) return provider } @@ -32,15 +32,6 @@ const filterMiddleware = engine._middleware.filter(mid => mid.name === 'filterMi filterMiddleware.destroy() ``` -### getSiteMetadata() - -This method is used to enhance our confirmation screens with images and text representing the requesting domain. - -It should return a promise that resolves with an object with the following properties: - -- `name`: The requesting site's name. -- `icon`: A URI representing the site's logo. - ### Using the Streams Interface Only use this if you intend to construct the [metamask-inpage-provider](https://github.com/MetaMask/metamask-inpage-provider) over a stream! diff --git a/package.json b/package.json index f7df8b7e5..48683a14e 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "eth-block-tracker": "^4.4.2", "eth-contract-metadata": "^1.11.0", "eth-ens-namehash": "^2.0.8", - "eth-json-rpc-errors": "^1.1.0", + "eth-json-rpc-errors": "^2.0.0", "eth-json-rpc-filters": "^4.1.1", "eth-json-rpc-infura": "^4.0.1", "eth-json-rpc-middleware": "^4.2.0", @@ -116,6 +116,7 @@ "ethjs-query": "^0.3.4", "extension-port-stream": "^1.0.0", "extensionizer": "^1.0.1", + "fast-deep-equal": "^2.0.1", "fast-json-patch": "^2.0.4", "fuse.js": "^3.2.0", "gaba": "^1.9.0", @@ -128,10 +129,11 @@ "lodash.shuffle": "^4.2.0", "loglevel": "^1.4.1", "luxon": "^1.8.2", - "metamask-inpage-provider": "^3.0.0", + "metamask-inpage-provider": "^4.0.2", "metamask-logo": "^2.1.4", "mkdirp": "^0.5.1", "multihashes": "^0.4.12", + "nanoid": "^2.1.6", "nonce-tracker": "^1.0.0", "number-to-bn": "^1.7.0", "obj-multiplex": "^1.0.0", @@ -173,7 +175,9 @@ "redux-thunk": "^2.2.0", "request-promise": "^4.2.1", "reselect": "^3.0.1", + "rpc-cap": "^1.0.1", "safe-event-emitter": "^1.0.1", + "safe-json-stringify": "^1.2.0", "single-call-balance-checker-abi": "^1.0.0", "string.prototype.matchall": "^3.0.1", "swappable-obj-proxy": "^1.1.0", diff --git a/test/e2e/contract-test/contract.js b/test/e2e/contract-test/contract.js index a6b5f110b..6c3941b9d 100644 --- a/test/e2e/contract-test/contract.js +++ b/test/e2e/contract-test/contract.js @@ -49,6 +49,8 @@ const initialize = () => { const approveTokensWithoutGas = document.getElementById('approveTokensWithoutGas') const signTypedData = document.getElementById('signTypedData') const signTypedDataResults = document.getElementById('signTypedDataResult') + const getAccountsButton = document.getElementById('getAccounts') + const getAccountsResults = document.getElementById('getAccountsResult') const contractStatus = document.getElementById('contractStatus') const tokenAddress = document.getElementById('tokenAddress') @@ -317,6 +319,16 @@ const initialize = () => { }) }) + getAccountsButton.addEventListener('click', async () => { + try { + const accounts = await ethereum.send({ method: 'eth_accounts' }) + getAccountsResults.innerHTML = accounts[0] || 'Not able to get accounts' + } catch (error) { + console.error(error) + getAccountsResults.innerHTML = `Error: ${error}` + } + }) + } updateButtons() diff --git a/test/e2e/contract-test/index.html b/test/e2e/contract-test/index.html index 9454a67dd..7655b8786 100644 --- a/test/e2e/contract-test/index.html +++ b/test/e2e/contract-test/index.html @@ -42,6 +42,11 @@ +
+

Get Accounts

+ +
+

Status

diff --git a/test/e2e/ethereum-on.spec.js b/test/e2e/ethereum-on.spec.js index ca062ca26..c50615521 100644 --- a/test/e2e/ethereum-on.spec.js +++ b/test/e2e/ethereum-on.spec.js @@ -113,7 +113,8 @@ describe('MetaMask', function () { let extension let popup let dapp - it('switches to a dapp', async () => { + + it('connects to the dapp', async () => { await openNewPage(driver, 'http://127.0.0.1:8080/') await delay(regularDelayMs) @@ -126,19 +127,27 @@ describe('MetaMask', function () { const windowHandles = await driver.getAllWindowHandles() extension = windowHandles[0] - popup = await switchToWindowWithTitle(driver, 'MetaMask Notification', windowHandles) - dapp = windowHandles.find(handle => handle !== extension && handle !== popup) + dapp = await switchToWindowWithTitle(driver, 'E2E Test Dapp', windowHandles) + popup = windowHandles.find(handle => handle !== extension && handle !== dapp) + + await driver.switchTo().window(popup) await delay(regularDelayMs) - const approveButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Connect')]`)) - await approveButton.click() + const accountButton = await findElement(driver, By.css('.permissions-connect-choose-account__account')) + await accountButton.click() + + const submitButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Submit')]`)) + await submitButton.click() + + await waitUntilXWindowHandles(driver, 2) await driver.switchTo().window(dapp) await delay(regularDelayMs) }) it('has the ganache network id within the dapp', async () => { const networkDiv = await findElement(driver, By.css('#network')) + await delay(regularDelayMs) assert.equal(await networkDiv.getText(), '5777') }) diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index 90cf35710..143e759ee 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -134,7 +134,7 @@ describe('MetaMask', function () { it('show account details dropdown menu', async () => { await driver.findElement(By.css('div.menu-bar__open-in-browser')).click() const options = await driver.findElements(By.css('div.menu.account-details-dropdown div.menu__item')) - assert.equal(options.length, 3) // HD Wallet type does not have to show the Remove Account option + assert.equal(options.length, 4) // HD Wallet type does not have to show the Remove Account option await delay(regularDelayMs) }) }) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index b5a8220b0..a22c0c1ca 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -432,7 +432,7 @@ describe('MetaMask', function () { await delay(largeDelayMs) }) - it('starts a send transaction inside the dapp', async () => { + it('connects the dapp', async () => { await openNewPage(driver, 'http://127.0.0.1:8080/') await delay(regularDelayMs) @@ -445,15 +445,22 @@ describe('MetaMask', function () { windowHandles = await driver.getAllWindowHandles() extension = windowHandles[0] - popup = await switchToWindowWithTitle(driver, 'MetaMask Notification', windowHandles) - dapp = windowHandles.find(handle => handle !== extension && handle !== popup) + dapp = await switchToWindowWithTitle(driver, 'E2E Test Dapp', windowHandles) + popup = windowHandles.find(handle => handle !== extension && handle !== dapp) + + await driver.switchTo().window(popup) await delay(regularDelayMs) - const approveButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Connect')]`)) - await approveButton.click() + const accountButton = await findElement(driver, By.css('.permissions-connect-choose-account__account')) + await accountButton.click() + + const submitButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Submit')]`)) + await submitButton.click() + + await waitUntilXWindowHandles(driver, 2) await driver.switchTo().window(dapp) - await delay(2000) + await delay(regularDelayMs) }) it('initiates a send from the dapp', async () => { diff --git a/test/e2e/permissions.spec.js b/test/e2e/permissions.spec.js new file mode 100644 index 000000000..b7147d7a2 --- /dev/null +++ b/test/e2e/permissions.spec.js @@ -0,0 +1,201 @@ +const assert = require('assert') +const webdriver = require('selenium-webdriver') +const { By, until } = webdriver +const { + delay, +} = require('./func') +const { + checkBrowserForConsoleErrors, + findElement, + findElements, + openNewPage, + verboseReportOnFailure, + waitUntilXWindowHandles, + switchToWindowWithTitle, + setupFetchMocking, + prepareExtensionForTesting, +} = require('./helpers') +const enLocaleMessages = require('../../app/_locales/en/messages.json') + +describe('MetaMask', function () { + let driver + let publicAddress + + const tinyDelayMs = 200 + const regularDelayMs = tinyDelayMs * 2 + const largeDelayMs = regularDelayMs * 2 + + this.timeout(0) + this.bail(true) + + before(async function () { + const result = await prepareExtensionForTesting() + driver = result.driver + await setupFetchMocking(driver) + }) + + afterEach(async function () { + if (process.env.SELENIUM_BROWSER === 'chrome') { + const errors = await checkBrowserForConsoleErrors(driver) + if (errors.length) { + const errorReports = errors.map(err => err.message) + const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` + console.error(new Error(errorMessage)) + } + } + if (this.currentTest.state === 'failed') { + await verboseReportOnFailure(driver, this.currentTest) + } + }) + + after(async function () { + await driver.quit() + }) + + describe('Going through the first time flow, but skipping the seed phrase challenge', () => { + it('clicks the continue button on the welcome screen', async () => { + await findElement(driver, By.css('.welcome-page__header')) + const welcomeScreenBtn = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) + welcomeScreenBtn.click() + await delay(largeDelayMs) + }) + + it('clicks the "Create New Wallet" option', async () => { + const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) + customRpcButton.click() + await delay(largeDelayMs) + }) + + it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { + const optOutButton = await findElement(driver, By.css('.btn-default')) + optOutButton.click() + await delay(largeDelayMs) + }) + + it('accepts a secure password', async () => { + const passwordBox = await findElement(driver, By.css('.first-time-flow__form #create-password')) + const passwordBoxConfirm = await findElement(driver, By.css('.first-time-flow__form #confirm-password')) + const button = await findElement(driver, By.css('.first-time-flow__form button')) + + await passwordBox.sendKeys('correct horse battery staple') + await passwordBoxConfirm.sendKeys('correct horse battery staple') + + const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox')) + await tosCheckBox.click() + + await button.click() + await delay(largeDelayMs) + }) + + it('skips the seed phrase challenge', async () => { + const button = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) + await button.click() + await delay(regularDelayMs) + + const detailsButton = await findElement(driver, By.css('.account-details__details-button')) + await detailsButton.click() + await delay(regularDelayMs) + }) + + it('gets the current accounts address', async () => { + const addressInput = await findElement(driver, By.css('.qr-ellip-address')) + publicAddress = await addressInput.getAttribute('value') + const accountModal = await driver.findElement(By.css('span .modal')) + + await driver.executeScript("document.querySelector('.account-modal-close').click()") + + await driver.wait(until.stalenessOf(accountModal)) + await delay(regularDelayMs) + }) + }) + + describe('sets permissions', () => { + let extension + let popup + let dapp + + it('connects to the dapp', async () => { + await openNewPage(driver, 'http://127.0.0.1:8080/') + await delay(regularDelayMs) + + const connectButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Connect')]`)) + await connectButton.click() + + await waitUntilXWindowHandles(driver, 3) + const windowHandles = await driver.getAllWindowHandles() + + extension = windowHandles[0] + dapp = await switchToWindowWithTitle(driver, 'E2E Test Dapp', windowHandles) + popup = windowHandles.find(handle => handle !== extension && handle !== dapp) + + await driver.switchTo().window(popup) + + await delay(regularDelayMs) + + const accountButton = await findElement(driver, By.css('.permissions-connect-choose-account__account')) + await accountButton.click() + + const submitButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Submit')]`)) + await submitButton.click() + + await waitUntilXWindowHandles(driver, 2) + await driver.switchTo().window(extension) + await delay(regularDelayMs) + }) + + it('shows connected sites', async () => { + const connectedSites = await findElement(driver, By.xpath(`//button[contains(text(), 'Connected Sites')]`)) + await connectedSites.click() + + await findElement(driver, By.css('.connected-sites__title')) + + const domains = await findElements(driver, By.css('.connected-sites-list__domain')) + assert.equal(domains.length, 1) + + const domainName = await findElement(driver, By.css('.connected-sites-list__domain-name')) + assert.equal(await domainName.getText(), 'E2E Test Dapp') + + await domains[0].click() + + const permissionDescription = await findElement(driver, By.css('.connected-sites-list__permission-description')) + assert.equal(await permissionDescription.getText(), 'View the address of the selected account') + }) + + it('can get accounts within the dapp', async () => { + await driver.switchTo().window(dapp) + await delay(regularDelayMs) + + const getAccountsButton = await findElement(driver, By.xpath(`//button[contains(text(), 'eth_accounts')]`)) + await getAccountsButton.click() + + const getAccountsResult = await findElement(driver, By.css('#getAccountsResult')) + assert.equal((await getAccountsResult.getText()).toLowerCase(), publicAddress.toLowerCase()) + }) + + it('can disconnect all accounts', async () => { + await driver.switchTo().window(extension) + + const disconnectAllButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Disconnect All')]`)) + await disconnectAllButton.click() + + const disconnectModal = await driver.findElement(By.css('span .modal')) + + const disconnectAllModalButton = await findElement(driver, By.css('.disconnect-all-modal .btn-danger')) + await disconnectAllModalButton.click() + + await driver.wait(until.stalenessOf(disconnectModal)) + await delay(regularDelayMs) + }) + + it('can no longer get accounts within the dapp', async () => { + await driver.switchTo().window(dapp) + await delay(regularDelayMs) + + const getAccountsButton = await findElement(driver, By.xpath(`//button[contains(text(), 'eth_accounts')]`)) + await getAccountsButton.click() + + const getAccountsResult = await findElement(driver, By.css('#getAccountsResult')) + assert.equal(await getAccountsResult.getText(), 'Not able to get accounts') + }) + }) +}) diff --git a/test/e2e/run-all.sh b/test/e2e/run-all.sh index 33c2428da..55a06fc88 100755 --- a/test/e2e/run-all.sh +++ b/test/e2e/run-all.sh @@ -60,6 +60,14 @@ concurrently --kill-others \ 'yarn dapp' \ 'sleep 5 && mocha test/e2e/ethereum-on.spec' +concurrently --kill-others \ + --names 'ganache,dapp,e2e' \ + --prefix '[{time}][{name}]' \ + --success first \ + 'yarn ganache:start' \ + 'yarn dapp' \ + 'sleep 5 && mocha test/e2e/permissions.spec' + export GANACHE_ARGS="${BASE_GANACHE_ARGS} --deterministic --account=0x250F458997A364988956409A164BA4E16F0F99F916ACDD73ADCD3A1DE30CF8D1,0 --account=0x53CB0AB5226EEBF4D872113D98332C1555DC304443BEE1CF759D15798D3C55A9,25000000000000000000" concurrently --kill-others \ --names 'ganache,sendwithprivatedapp,e2e' \ diff --git a/test/e2e/signature-request.spec.js b/test/e2e/signature-request.spec.js index a5be61baf..f36b6ac51 100644 --- a/test/e2e/signature-request.spec.js +++ b/test/e2e/signature-request.spec.js @@ -119,12 +119,13 @@ describe('MetaMask', function () { }) }) - describe('provider listening for events', () => { + describe('successfuly signs typed data', () => { let extension let popup let dapp let windowHandles - it('switches to a dapp', async () => { + + it('connects to the dapp', async () => { await openNewPage(driver, 'http://127.0.0.1:8080/') await delay(regularDelayMs) @@ -134,18 +135,24 @@ describe('MetaMask', function () { await delay(regularDelayMs) await waitUntilXWindowHandles(driver, 3) - windowHandles = await driver.getAllWindowHandles() + const windowHandles = await driver.getAllWindowHandles() extension = windowHandles[0] - popup = await switchToWindowWithTitle(driver, 'MetaMask Notification', windowHandles) - dapp = windowHandles.find(handle => handle !== extension && handle !== popup) + dapp = await switchToWindowWithTitle(driver, 'E2E Test Dapp', windowHandles) + popup = windowHandles.find(handle => handle !== extension && handle !== dapp) + + await driver.switchTo().window(popup) await delay(regularDelayMs) - const approveButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Connect')]`)) - await approveButton.click() + const accountButton = await findElement(driver, By.css('.permissions-connect-choose-account__account')) + await accountButton.click() + + const submitButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Submit')]`)) + await submitButton.click() + + await waitUntilXWindowHandles(driver, 2) await driver.switchTo().window(dapp) - await delay(regularDelayMs) }) it('creates a sign typed data signature request', async () => { @@ -153,6 +160,7 @@ describe('MetaMask', function () { await signTypedMessage.click() await delay(largeDelayMs) + await delay(regularDelayMs) windowHandles = await driver.getAllWindowHandles() await switchToWindowWithTitle(driver, 'MetaMask Notification', windowHandles) await delay(regularDelayMs) diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js index f49e518c3..7aea39a36 100644 --- a/test/unit/app/controllers/preferences-controller-test.js +++ b/test/unit/app/controllers/preferences-controller-test.js @@ -1,6 +1,7 @@ const assert = require('assert') const ObservableStore = require('obs-store') const PreferencesController = require('../../../../app/scripts/controllers/preferences') +const { addInternalMethodPrefix } = require('../../../../app/scripts/controllers/permissions') const sinon = require('sinon') describe('preferences controller', function () { @@ -375,7 +376,7 @@ describe('preferences controller', function () { await preferencesController.requestWatchAsset(req, res, asy.next, asy.end) sandbox.assert.called(stubEnd) sandbox.assert.notCalled(stubNext) - req.method = 'wallet_watchAsset' + req.method = addInternalMethodPrefix('watchAsset') req.params.type = 'someasset' await preferencesController.requestWatchAsset(req, res, asy.next, asy.end) sandbox.assert.calledTwice(stubEnd) diff --git a/test/unit/app/controllers/provider-approval-test.js b/test/unit/app/controllers/provider-approval-test.js deleted file mode 100644 index eeb9e813b..000000000 --- a/test/unit/app/controllers/provider-approval-test.js +++ /dev/null @@ -1,330 +0,0 @@ -const assert = require('assert') -const sinon = require('sinon') -const ProviderApprovalController = require('../../../../app/scripts/controllers/provider-approval') - -const mockLockedKeyringController = { - memStore: { - getState: () => ({ - isUnlocked: false, - }), - }, -} - -const mockUnlockedKeyringController = { - memStore: { - getState: () => ({ - isUnlocked: true, - }), - }, -} - -describe('ProviderApprovalController', () => { - describe('#_handleProviderRequest', () => { - it('should add a pending provider request when unlocked', () => { - const controller = new ProviderApprovalController({ - keyringController: mockUnlockedKeyringController, - }) - - const metadata = { - hostname: 'https://example.com', - origin: 'example.com', - siteTitle: 'Example', - siteImage: 'https://example.com/logo.svg', - } - - controller._handleProviderRequest(metadata) - assert.deepEqual(controller._getMergedState(), { - approvedOrigins: {}, - providerRequests: [metadata], - }) - }) - - it('should add a pending provider request when locked', () => { - const controller = new ProviderApprovalController({ - keyringController: mockLockedKeyringController, - }) - - const metadata = { - hostname: 'https://example.com', - origin: 'example.com', - siteTitle: 'Example', - siteImage: 'https://example.com/logo.svg', - } - controller._handleProviderRequest(metadata) - assert.deepEqual(controller._getMergedState(), { - approvedOrigins: {}, - providerRequests: [metadata], - }) - }) - - it('should add a 2nd pending provider request when unlocked', () => { - const controller = new ProviderApprovalController({ - keyringController: mockUnlockedKeyringController, - }) - - const metadata = [{ - hostname: 'https://example1.com', - origin: 'example1.com', - siteTitle: 'Example 1', - siteImage: 'https://example1.com/logo.svg', - }, { - hostname: 'https://example2.com', - origin: 'example2.com', - siteTitle: 'Example 2', - siteImage: 'https://example2.com/logo.svg', - }] - - controller._handleProviderRequest(metadata[0]) - controller._handleProviderRequest(metadata[1]) - assert.deepEqual(controller._getMergedState(), { - approvedOrigins: {}, - providerRequests: metadata, - }) - }) - - it('should add a 2nd pending provider request when locked', () => { - const controller = new ProviderApprovalController({ - keyringController: mockLockedKeyringController, - }) - - const metadata = [{ - hostname: 'https://example1.com', - origin: 'example1.com', - siteTitle: 'Example 1', - siteImage: 'https://example1.com/logo.svg', - }, { - hostname: 'https://example2.com', - origin: 'example2.com', - siteTitle: 'Example 2', - siteImage: 'https://example2.com/logo.svg', - }] - - controller._handleProviderRequest(metadata[0]) - controller._handleProviderRequest(metadata[1]) - assert.deepEqual(controller._getMergedState(), { - approvedOrigins: {}, - providerRequests: metadata, - }) - }) - - it('should call openPopup when unlocked and when given', () => { - const openPopup = sinon.spy() - const controller = new ProviderApprovalController({ - openPopup, - keyringController: mockUnlockedKeyringController, - }) - - const metadata = { - hostname: 'https://example.com', - origin: 'example.com', - siteTitle: 'Example', - siteImage: 'https://example.com/logo.svg', - } - controller._handleProviderRequest(metadata) - assert.ok(openPopup.calledOnce) - }) - - it('should call openPopup when locked and when given', () => { - const openPopup = sinon.spy() - const controller = new ProviderApprovalController({ - openPopup, - keyringController: mockLockedKeyringController, - }) - - const metadata = { - hostname: 'https://example.com', - origin: 'example.com', - siteTitle: 'Example', - siteImage: 'https://example.com/logo.svg', - } - controller._handleProviderRequest(metadata) - assert.ok(openPopup.calledOnce) - }) - - it('should NOT call openPopup when unlocked and when the domain has already been approved', () => { - const openPopup = sinon.spy() - const controller = new ProviderApprovalController({ - openPopup, - keyringController: mockUnlockedKeyringController, - }) - - controller.store.updateState({ - approvedOrigins: { - 'example.com': { - siteTitle: 'Example', - siteImage: 'https://example.com/logo.svg', - }, - }, - }) - const metadata = { - hostname: 'https://example.com', - origin: 'example.com', - siteTitle: 'Example', - siteImage: 'https://example.com/logo.svg', - } - controller._handleProviderRequest(metadata) - assert.ok(openPopup.notCalled) - }) - }) - - describe('#approveProviderRequestByOrigin', () => { - it('should mark the origin as approved and remove the provider request', () => { - const controller = new ProviderApprovalController({ - keyringController: mockUnlockedKeyringController, - }) - - const metadata = { - hostname: 'https://example.com', - origin: 'example.com', - siteTitle: 'Example', - siteImage: 'https://example.com/logo.svg', - } - controller._handleProviderRequest(metadata) - controller.approveProviderRequestByOrigin('example.com') - assert.deepEqual(controller._getMergedState(), { - providerRequests: [], - approvedOrigins: { - 'example.com': { - hostname: 'https://example.com', - siteTitle: 'Example', - siteImage: 'https://example.com/logo.svg', - }, - }, - }) - }) - - it('should mark the origin as approved and multiple requests for the same domain', () => { - const controller = new ProviderApprovalController({ - keyringController: mockUnlockedKeyringController, - }) - - const metadata = { - hostname: 'https://example.com', - origin: 'example.com', - siteTitle: 'Example', - siteImage: 'https://example.com/logo.svg', - } - controller._handleProviderRequest(metadata) - controller._handleProviderRequest(metadata) - controller.approveProviderRequestByOrigin('example.com') - assert.deepEqual(controller._getMergedState(), { - providerRequests: [], - approvedOrigins: { - 'example.com': { - hostname: 'https://example.com', - siteTitle: 'Example', - siteImage: 'https://example.com/logo.svg', - }, - }, - }) - }) - - it('should mark the origin as approved without a provider request', () => { - const controller = new ProviderApprovalController({ - keyringController: mockUnlockedKeyringController, - }) - - controller.approveProviderRequestByOrigin('example.com') - assert.deepEqual(controller._getMergedState(), { - providerRequests: [], - approvedOrigins: { - 'example.com': { - hostname: null, - siteTitle: null, - siteImage: null, - }, - }, - }) - }) - }) - - describe('#rejectProviderRequestByOrigin', () => { - it('should remove the origin from approved', () => { - const controller = new ProviderApprovalController({ - keyringController: mockUnlockedKeyringController, - }) - - const metadata = { - hostname: 'https://example.com', - origin: 'example.com', - siteTitle: 'Example', - siteImage: 'https://example.com/logo.svg', - } - controller._handleProviderRequest(metadata) - controller.approveProviderRequestByOrigin('example.com') - controller.rejectProviderRequestByOrigin('example.com') - assert.deepEqual(controller._getMergedState(), { - providerRequests: [], - approvedOrigins: {}, - }) - }) - - it('should reject the origin even without a pending request', () => { - const controller = new ProviderApprovalController({ - keyringController: mockUnlockedKeyringController, - }) - - controller.rejectProviderRequestByOrigin('example.com') - assert.deepEqual(controller._getMergedState(), { - providerRequests: [], - approvedOrigins: {}, - }) - }) - }) - - describe('#clearApprovedOrigins', () => { - it('should clear the approved origins', () => { - const controller = new ProviderApprovalController({ - keyringController: mockUnlockedKeyringController, - }) - - const metadata = { - hostname: 'https://example.com', - origin: 'example.com', - siteTitle: 'Example', - siteImage: 'https://example.com/logo.svg', - } - controller._handleProviderRequest(metadata) - controller.approveProviderRequestByOrigin('example.com') - controller.clearApprovedOrigins() - assert.deepEqual(controller._getMergedState(), { - providerRequests: [], - approvedOrigins: {}, - }) - }) - }) - - describe('#shouldExposeAccounts', () => { - it('should return true for an approved origin', () => { - const controller = new ProviderApprovalController({ - keyringController: mockUnlockedKeyringController, - }) - - const metadata = { - hostname: 'https://example.com', - origin: 'example.com', - siteTitle: 'Example', - siteImage: 'https://example.com/logo.svg', - } - controller._handleProviderRequest(metadata) - controller.approveProviderRequestByOrigin('example.com') - assert.ok(controller.shouldExposeAccounts('example.com')) - }) - - it('should return false for an origin not yet approved', () => { - const controller = new ProviderApprovalController({ - keyringController: mockUnlockedKeyringController, - }) - - const metadata = { - hostname: 'https://example.com', - origin: 'example.com', - siteTitle: 'Example', - siteImage: 'https://example.com/logo.svg', - } - controller._handleProviderRequest(metadata) - controller.approveProviderRequestByOrigin('example.com') - assert.ok(!controller.shouldExposeAccounts('bad.website')) - }) - }) -}) diff --git a/test/unit/app/controllers/transactions/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js index d0a989e71..d398c7e04 100644 --- a/test/unit/app/controllers/transactions/tx-controller-test.js +++ b/test/unit/app/controllers/transactions/tx-controller-test.js @@ -48,6 +48,7 @@ describe('Transaction Controller', function () { ethTx.sign(fromAccount.key) resolve() }), + getPermittedAccounts: () => {}, }) txController.nonceTracker.getNonceLock = () => Promise.resolve({ nextNonce: 0, releaseLock: noop }) }) @@ -176,13 +177,15 @@ describe('Transaction Controller', function () { describe('#addUnapprovedTransaction', function () { const selectedAddress = '0x1678a085c290ebd122dc42cba69373b5953b831d' - let getSelectedAddress + let getSelectedAddress, getPermittedAccounts beforeEach(function () { getSelectedAddress = sinon.stub(txController, 'getSelectedAddress').returns(selectedAddress) + getPermittedAccounts = sinon.stub(txController, 'getPermittedAccounts').returns([selectedAddress]) }) afterEach(function () { getSelectedAddress.restore() + getPermittedAccounts.restore() }) it('should add an unapproved transaction and return a valid txMeta', function (done) { diff --git a/ui/app/components/app/account-details/account-details.component.js b/ui/app/components/app/account-details/account-details.component.js index 55078cee0..e75e777a6 100644 --- a/ui/app/components/app/account-details/account-details.component.js +++ b/ui/app/components/app/account-details/account-details.component.js @@ -19,9 +19,11 @@ export default class AccountDetails extends Component { static propTypes = { hideSidebar: PropTypes.func, showAccountDetailModal: PropTypes.func, + showConnectedSites: PropTypes.func.isRequired, label: PropTypes.string.isRequired, checksummedAddress: PropTypes.string.isRequired, name: PropTypes.string.isRequired, + history: PropTypes.object.isRequired, } state = { @@ -48,6 +50,7 @@ export default class AccountDetails extends Component { const { hideSidebar, showAccountDetailModal, + showConnectedSites, label, checksummedAddress, name, @@ -65,14 +68,19 @@ export default class AccountDetails extends Component {
{label}
-
- +
+ {name} - +
+ + +
list.concat(keyring.accounts), []) @@ -71,6 +76,8 @@ export default class AccountMenu extends PureComponent { const keyring = keyrings.find(kr => { return kr.accounts.includes(simpleAddress) || kr.accounts.includes(identity.address) }) + const addressDomains = addressConnectedDomainMap[identity.address] || {} + const iconAndNameForOpenDomain = addressDomains[originOfCurrentTab] return (
+ { iconAndNameForOpenDomain + ? ( +
+ +
+ ) + : null + } { this.renderKeyringType(keyring) } { this.renderRemoveAccount(keyring, identity) }
diff --git a/ui/app/components/app/account-menu/account-menu.container.js b/ui/app/components/app/account-menu/account-menu.container.js index ae2e28e76..00a0666ec 100644 --- a/ui/app/components/app/account-menu/account-menu.container.js +++ b/ui/app/components/app/account-menu/account-menu.container.js @@ -11,7 +11,12 @@ import { showInfoPage, showModal, } from '../../../store/actions' -import { getMetaMaskAccounts } from '../../../selectors/selectors' +import { + getAddressConnectedDomainMap, + getMetaMaskAccounts, + getOriginOfCurrentTab, +} from '../../../selectors/selectors' + import AccountMenu from './account-menu.component' function mapStateToProps (state) { @@ -23,6 +28,8 @@ function mapStateToProps (state) { keyrings, identities, accounts: getMetaMaskAccounts(state), + addressConnectedDomainMap: getAddressConnectedDomainMap(state), + originOfCurrentTab: getOriginOfCurrentTab(state), } } diff --git a/ui/app/components/app/account-menu/index.scss b/ui/app/components/app/account-menu/index.scss index 614e19104..93b9766d3 100644 --- a/ui/app/components/app/account-menu/index.scss +++ b/ui/app/components/app/account-menu/index.scss @@ -175,4 +175,8 @@ opacity: 1; } } + + &__icon-list { + display: flex; + } } diff --git a/ui/app/components/app/connected-sites-list/connected-sites-list.component.js b/ui/app/components/app/connected-sites-list/connected-sites-list.component.js new file mode 100644 index 000000000..a04f87486 --- /dev/null +++ b/ui/app/components/app/connected-sites-list/connected-sites-list.component.js @@ -0,0 +1,157 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import classnames from 'classnames' +import Button from '../../ui/button' +import IconWithFallBack from '../../ui/icon-with-fallback' + +export default class ConnectedSitesList extends Component { + static contextTypes = { + t: PropTypes.func, + } + + static propTypes = { + renderableDomains: PropTypes.arrayOf(PropTypes.shape({ + name: PropTypes.string, + icon: PropTypes.string, + key: PropTypes.string, + lastConnectedTime: PropTypes.string, + permissionDescriptions: PropTypes.array, + })).isRequired, + domains: PropTypes.object, + showDisconnectAccountModal: PropTypes.func.isRequired, + showDisconnectAllModal: PropTypes.func.isRequired, + tabToConnect: PropTypes.object, + legacyExposeAccounts: PropTypes.func.isRequired, + selectedAddress: PropTypes.string.isRequired, + getOpenMetamaskTabsIds: PropTypes.func.isRequired, + } + + state = { + expandedDomain: '', + } + + componentWillMount () { + const { getOpenMetamaskTabsIds } = this.props + getOpenMetamaskTabsIds() + } + + handleDomainItemClick (domainKey) { + if (this.state.expandedDomain === domainKey) { + this.setState({ expandedDomain: '' }) + } else { + this.setState({ expandedDomain: domainKey }) + } + } + + render () { + const { + renderableDomains, + domains, + showDisconnectAccountModal, + showDisconnectAllModal, + tabToConnect, + legacyExposeAccounts, + selectedAddress, + } = this.props + const { expandedDomain } = this.state + const { t } = this.context + + return ( +
+ { + renderableDomains.map((domain, domainIndex) => { + const domainIsExpanded = expandedDomain === domain.key + return ( +
+
this.handleDomainItemClick(domain.key) }> +
+ + +
+
+
+ { domain.extensionId ? t('externalExtension') : domain.name } +
+
+ { domain.lastConnectedTime + ? ( +
+ { t('domainLastConnect', [domain.lastConnectedTime]) } +
+ ) + : null + } + {domainIsExpanded + ? ( +
+ { domain.extensionId ? t('extensionId', [domain.extensionId]) : domain.secondaryName } +
+ ) + : null + } +
+
+
+ { domainIsExpanded ? : } +
+
+ { domainIsExpanded + ? ( +
+
+ { + domain.permissionDescriptions.map((description, pdIndex) => { + return ( +
+ +
+ { description } +
+
+ ) + }) + } +
+
showDisconnectAccountModal(domain.key, domains[domain.key]) } + > + { t('disconnectAccount') } +
+
+ ) + : null + } +
+ ) + }) + } +
+
+ +
+ { tabToConnect + ? ( +
+ +
+ ) + : null + } +
+
+ ) + } +} diff --git a/ui/app/components/app/connected-sites-list/connected-sites-list.container.js b/ui/app/components/app/connected-sites-list/connected-sites-list.container.js new file mode 100644 index 000000000..de45831a9 --- /dev/null +++ b/ui/app/components/app/connected-sites-list/connected-sites-list.container.js @@ -0,0 +1,57 @@ +import { connect } from 'react-redux' +import { compose } from 'recompose' + +import ConnectedSitesList from './connected-sites-list.component' +import { + showModal, + legacyExposeAccounts, + getOpenMetamaskTabsIds, +} from '../../../store/actions' +import { + getRenderablePermissionsDomains, + getPermissionsDomains, + getAddressConnectedToCurrentTab, + getSelectedAddress, +} from '../../../selectors/selectors' +import { getOriginFromUrl } from '../../../helpers/utils/util' + +const mapStateToProps = state => { + const addressConnectedToCurrentTab = getAddressConnectedToCurrentTab(state) + const { openMetaMaskTabs } = state.appState + const { title, url, id } = state.activeTab + + let tabToConnect + + if (!addressConnectedToCurrentTab && url && !openMetaMaskTabs[id]) { + tabToConnect = { + title, + origin: getOriginFromUrl(url), + } + } + + return { + domains: getPermissionsDomains(state), + renderableDomains: getRenderablePermissionsDomains(state), + tabToConnect, + selectedAddress: getSelectedAddress(state), + } +} + +const mapDispatchToProps = dispatch => { + return { + showDisconnectAccountModal: (domainKey, domain) => { + dispatch(showModal({ name: 'DISCONNECT_ACCOUNT', domainKey, domain })) + }, + showDisconnectAllModal: () => { + dispatch(showModal({ name: 'DISCONNECT_ALL' })) + }, + legacyExposeAccounts: (origin, account) => { + dispatch(legacyExposeAccounts(origin, [account])) + }, + getOpenMetamaskTabsIds: () => dispatch(getOpenMetamaskTabsIds()), + } +} + +export default compose( + connect(mapStateToProps, mapDispatchToProps) +)(ConnectedSitesList) diff --git a/ui/app/components/app/connected-sites-list/index.js b/ui/app/components/app/connected-sites-list/index.js new file mode 100644 index 000000000..431a3a8eb --- /dev/null +++ b/ui/app/components/app/connected-sites-list/index.js @@ -0,0 +1 @@ +export { default } from './connected-sites-list.container' diff --git a/ui/app/components/app/connected-sites-list/index.scss b/ui/app/components/app/connected-sites-list/index.scss new file mode 100644 index 000000000..c2d98d2aa --- /dev/null +++ b/ui/app/components/app/connected-sites-list/index.scss @@ -0,0 +1,125 @@ +.connected-sites-list { + font-family: Roboto; + font-style: normal; + font-weight: normal; + + &__domain, &__domain--expanded { + border-bottom: 1px solid #c4c4c4; + } + + &__domain { + cursor: pointer; + } + + &__domain--expanded { + background: #FAFBFC; + cursor: initial; + } + + &__domain-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px; + } + + &__domain-item-info-container { + display: flex; + } + + &__identicon-container { + position: relative; + display: flex; + justify-content: center; + align-items: center; + height: 32px; + width: 32px; + } + + &__identicon-border { + height: 32px; + width: 32px; + border-radius: 50%; + border: 1px solid #F2F3F4; + position: absolute; + background: #FFFFFF; + } + + &__identicon { + width: 24px; + height: 24px; + z-index: 1; + + &--default { + z-index: 1; + color: black; + } + } + + &__domain-info { + display: flex; + flex-direction: column; + margin-left: 16px; + } + + &__domain-names { + display: flex; + align-items: center; + } + + &__domain-name { + font-size: 18px; + color: #24292E; + } + + &__domain-origin, &__domain-last-connected { + font-size: 12px; + color: #6A737D; + } + + &__domain-last-connected { + margin-top: 2px; + } + + &__expand-arrow { + align-self: flex-start; + margin-top: 6px; + } + + &__permissions { + padding-left: 16px; + padding-bottom: 24px; + } + + &__permission { + display: flex; + align-items: center; + color: #6A737D; + margin-left: 16px; + } + + &__permission-description { + margin-left: 18px; + } + + &__disconnect { + margin-top: 24px; + color: #D73A49; + cursor: pointer; + } + + &__bottom-buttons { + display: flex; + align-items: center; + } + + &__disconnect-all { + padding: 10px; + width: 50%; + } + + &__connect-to { + padding: 10px; + width: 50%; + } +} \ No newline at end of file diff --git a/ui/app/components/app/dropdowns/account-details-dropdown.js b/ui/app/components/app/dropdowns/account-details-dropdown.js index 89e7f91ef..dc09b8c64 100644 --- a/ui/app/components/app/dropdowns/account-details-dropdown.js +++ b/ui/app/components/app/dropdowns/account-details-dropdown.js @@ -1,9 +1,12 @@ import React, { Component } from 'react' const PropTypes = require('prop-types') +const { compose } = require('recompose') +const { withRouter } = require('react-router-dom') const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../../store/actions') const { getSelectedIdentity, getRpcPrefsForCurrentProvider } = require('../../../selectors/selectors') +const { CONNECTED_ROUTE } = require('../../../helpers/constants/routes') const genAccountLink = require('../../../../lib/account-link.js') const { Menu, Item, CloseArea } = require('./components/menu') @@ -12,7 +15,7 @@ AccountDetailsDropdown.contextTypes = { metricsEvent: PropTypes.func, } -module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDetailsDropdown) +module.exports = compose(withRouter, connect(mapStateToProps, mapDispatchToProps))(AccountDetailsDropdown) function mapStateToProps (state) { return { @@ -58,6 +61,7 @@ AccountDetailsDropdown.prototype.render = function AccountDetailsDropdown () { viewOnEtherscan, showRemoveAccountConfirmationModal, rpcPrefs, + history, } = this.props const address = selectedIdentity.address @@ -134,6 +138,23 @@ AccountDetailsDropdown.prototype.render = function AccountDetailsDropdown () { )} /> + { + e.stopPropagation() + this.context.metricsEvent({ + eventOpts: { + category: 'Navigation', + action: 'Account Options', + name: 'Opened Connected Sites', + }, + }) + history.push(CONNECTED_ROUTE) + }} + text={this.context.t('connectedSites')} + icon={( + + )} + /> { isRemovable ? ( diff --git a/ui/app/components/app/index.scss b/ui/app/components/app/index.scss index 1afbebd00..7578aa204 100644 --- a/ui/app/components/app/index.scss +++ b/ui/app/components/app/index.scss @@ -38,7 +38,7 @@ @import '../../pages/index'; -@import 'provider-page-container/index'; +@import 'permission-page-container/index'; @import 'selected-account/index'; @@ -64,18 +64,12 @@ @import 'transaction-status/index'; -@import 'app-header/index'; - @import 'sidebars/index'; @import '../ui/unit-input/index'; @import 'gas-customization/gas-modal-page-container/index'; -@import 'gas-customization/gas-modal-page-container/index'; - -@import 'gas-customization/gas-modal-page-container/index'; - @import 'gas-customization/index'; @import 'gas-customization/gas-price-button-group/index'; @@ -87,3 +81,7 @@ @import 'multiple-notifications/index'; @import 'signature-request/index'; + +@import 'connected-sites-list/index'; + +@import '../ui/icon-with-fallback/index'; diff --git a/ui/app/components/app/modal/modal.component.js b/ui/app/components/app/modal/modal.component.js index f0fdd3bd5..6c45160fd 100644 --- a/ui/app/components/app/modal/modal.component.js +++ b/ui/app/components/app/modal/modal.component.js @@ -16,6 +16,7 @@ export default class Modal extends PureComponent { submitType: PropTypes.string, submitText: PropTypes.string, submitDisabled: PropTypes.bool, + hideFooter: PropTypes.bool, // Cancel button (left button) onCancel: PropTypes.func, cancelType: PropTypes.string, @@ -41,6 +42,7 @@ export default class Modal extends PureComponent { cancelText, contentClass, containerClass, + hideFooter, } = this.props return ( @@ -61,27 +63,32 @@ export default class Modal extends PureComponent {
{ children }
-
- { - onCancel && ( + { !hideFooter + ? ( +
+ { + onCancel && ( + + ) + } - ) - } - -
+
+ ) + : null + } ) } diff --git a/ui/app/components/app/modals/clear-approved-origins/clear-approved-origins.component.js b/ui/app/components/app/modals/clear-approved-origins/clear-approved-origins.component.js deleted file mode 100644 index ceaa20a95..000000000 --- a/ui/app/components/app/modals/clear-approved-origins/clear-approved-origins.component.js +++ /dev/null @@ -1,39 +0,0 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import Modal, { ModalContent } from '../../modal' - -export default class ClearApprovedOrigins extends PureComponent { - static propTypes = { - hideModal: PropTypes.func.isRequired, - clearApprovedOrigins: PropTypes.func.isRequired, - } - - static contextTypes = { - t: PropTypes.func, - } - - handleClear = () => { - const { clearApprovedOrigins, hideModal } = this.props - clearApprovedOrigins() - hideModal() - } - - render () { - const { t } = this.context - - return ( - this.props.hideModal()} - submitText={t('ok')} - cancelText={t('nevermind')} - submitType="secondary" - > - - - ) - } -} diff --git a/ui/app/components/app/modals/clear-approved-origins/index.js b/ui/app/components/app/modals/clear-approved-origins/index.js deleted file mode 100644 index b3e321995..000000000 --- a/ui/app/components/app/modals/clear-approved-origins/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './clear-approved-origins.container' diff --git a/ui/app/components/app/modals/disconnect-account/disconnect-account.component.js b/ui/app/components/app/modals/disconnect-account/disconnect-account.component.js new file mode 100644 index 000000000..4fe5c7227 --- /dev/null +++ b/ui/app/components/app/modals/disconnect-account/disconnect-account.component.js @@ -0,0 +1,52 @@ +import React, { PureComponent } from 'react' +import PropTypes from 'prop-types' +import Modal from '../../modal' +import Button from '../../../ui/button' + + +export default class DisconnectAccount extends PureComponent { + static propTypes = { + hideModal: PropTypes.func.isRequired, + disconnectAccount: PropTypes.func.isRequired, + accountLabel: PropTypes.string.isRequired, + } + + static contextTypes = { + t: PropTypes.func, + } + + render () { + const { t } = this.context + const { hideModal, disconnectAccount, accountLabel } = this.props + + return ( + hideModal()} + hideFooter + > +
+
+ { t('disconnectAccountModalDescription', [ accountLabel ]) } +
+ + +
+
+ ) + } +} diff --git a/ui/app/components/app/modals/disconnect-account/disconnect-account.container.js b/ui/app/components/app/modals/disconnect-account/disconnect-account.container.js new file mode 100644 index 000000000..b0511bb47 --- /dev/null +++ b/ui/app/components/app/modals/disconnect-account/disconnect-account.container.js @@ -0,0 +1,44 @@ +import { connect } from 'react-redux' +import { compose } from 'recompose' +import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' +import DisconnectAccount from './disconnect-account.component' +import { getCurrentAccountWithSendEtherInfo } from '../../../../selectors/selectors' +import { removePermissionsFor } from '../../../../store/actions' + +const mapStateToProps = state => { + return { + ...state.appState.modal.modalState.props || {}, + accountLabel: getCurrentAccountWithSendEtherInfo(state).name, + } +} + +const mapDispatchToProps = dispatch => { + return { + disconnectAccount: (domainKey, domain) => { + const permissionMethodNames = domain.permissions.map(perm => perm.parentCapability) + dispatch(removePermissionsFor({ [domainKey]: permissionMethodNames })) + }, + } +} + +const mergeProps = (stateProps, dispatchProps, ownProps) => { + const { + domainKey, + domain, + } = stateProps + const { + disconnectAccount: dispatchDisconnectAccount, + } = dispatchProps + + return { + ...ownProps, + ...stateProps, + ...dispatchProps, + disconnectAccount: () => dispatchDisconnectAccount(domainKey, domain), + } +} + +export default compose( + withModalProps, + connect(mapStateToProps, mapDispatchToProps, mergeProps) +)(DisconnectAccount) diff --git a/ui/app/components/app/modals/disconnect-account/index.js b/ui/app/components/app/modals/disconnect-account/index.js new file mode 100644 index 000000000..43bfac9fd --- /dev/null +++ b/ui/app/components/app/modals/disconnect-account/index.js @@ -0,0 +1 @@ +export { default } from './disconnect-account.container' diff --git a/ui/app/components/app/modals/disconnect-account/index.scss b/ui/app/components/app/modals/disconnect-account/index.scss new file mode 100644 index 000000000..861b7cec2 --- /dev/null +++ b/ui/app/components/app/modals/disconnect-account/index.scss @@ -0,0 +1,25 @@ +.disconnect-account-modal { + &__description { + color: #24292E; + margin-bottom: 24px; + } + + &__cancel-button { + border: none; + margin-top: 12px; + } +} + +.disconnect-account-modal-container { + .modal-container__header-text { + @extend %header--18; + } + + .modal-container__content { + padding-bottom: 18px; + + @media screen and (max-width: 575px) { + padding-bottom: 18px; + } + } +} \ No newline at end of file diff --git a/ui/app/components/app/modals/disconnect-all/disconnect-all.component.js b/ui/app/components/app/modals/disconnect-all/disconnect-all.component.js new file mode 100644 index 000000000..2d29fd9ea --- /dev/null +++ b/ui/app/components/app/modals/disconnect-all/disconnect-all.component.js @@ -0,0 +1,54 @@ +import React, { PureComponent } from 'react' +import PropTypes from 'prop-types' +import Modal from '../../modal' +import Button from '../../../ui/button' +import { DEFAULT_ROUTE } from '../../../../helpers/constants/routes' + +export default class DisconnectAll extends PureComponent { + static propTypes = { + hideModal: PropTypes.func.isRequired, + disconnectAll: PropTypes.func.isRequired, + history: PropTypes.object.isRequired, + } + + static contextTypes = { + t: PropTypes.func, + } + + render () { + const { t } = this.context + const { hideModal, disconnectAll, history } = this.props + + return ( + hideModal()} + hideFooter + > +
+
+ { t('disconnectAllModalDescription') } +
+ + +
+
+ ) + } +} diff --git a/ui/app/components/app/modals/clear-approved-origins/clear-approved-origins.container.js b/ui/app/components/app/modals/disconnect-all/disconnect-all.container.js similarity index 53% rename from ui/app/components/app/modals/clear-approved-origins/clear-approved-origins.container.js rename to ui/app/components/app/modals/disconnect-all/disconnect-all.container.js index 2276bc7e7..2415c3fa9 100644 --- a/ui/app/components/app/modals/clear-approved-origins/clear-approved-origins.container.js +++ b/ui/app/components/app/modals/disconnect-all/disconnect-all.container.js @@ -1,16 +1,20 @@ import { connect } from 'react-redux' import { compose } from 'recompose' +import { withRouter } from 'react-router-dom' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import ClearApprovedOriginsComponent from './clear-approved-origins.component' -import { clearApprovedOrigins } from '../../../../store/actions' +import DisconnectAll from './disconnect-all.component' +import { clearPermissions } from '../../../../store/actions' const mapDispatchToProps = dispatch => { return { - clearApprovedOrigins: () => dispatch(clearApprovedOrigins()), + disconnectAll: () => { + dispatch(clearPermissions()) + }, } } export default compose( withModalProps, + withRouter, connect(null, mapDispatchToProps) -)(ClearApprovedOriginsComponent) +)(DisconnectAll) diff --git a/ui/app/components/app/modals/disconnect-all/index.js b/ui/app/components/app/modals/disconnect-all/index.js new file mode 100644 index 000000000..7fdfac530 --- /dev/null +++ b/ui/app/components/app/modals/disconnect-all/index.js @@ -0,0 +1 @@ +export { default } from './disconnect-all.container' diff --git a/ui/app/components/app/modals/disconnect-all/index.scss b/ui/app/components/app/modals/disconnect-all/index.scss new file mode 100644 index 000000000..8f69baade --- /dev/null +++ b/ui/app/components/app/modals/disconnect-all/index.scss @@ -0,0 +1,38 @@ +.disconnect-all-modal { + height: 160px; + display: flex; + flex-direction: column; + justify-content: space-between; + + &__description { + color: #24292E; + margin-bottom: 24px; + } + + &__cancel-button { + border: none; + margin-top: 12px; + } + + .btn-secondary { + border: none; + } +} + +.disconnect-all-modal-container { + .modal-container__header-text { + font-family: Roboto; + font-style: normal; + font-weight: bold; + font-size: 18px; + color: #24292E; + } + + .modal-container__content { + padding-bottom: 18px; + + @media screen and (max-width: 575px) { + padding-bottom: 18px; + } + } +} diff --git a/ui/app/components/app/modals/index.scss b/ui/app/components/app/modals/index.scss index da7a27b84..dbf47265f 100644 --- a/ui/app/components/app/modals/index.scss +++ b/ui/app/components/app/modals/index.scss @@ -11,3 +11,9 @@ @import './add-to-addressbook-modal/index'; @import './edit-approval-permission/index'; + +@import './disconnect-account/index'; + +@import './disconnect-all/index'; + +@import './new-account-modal/index'; diff --git a/ui/app/components/app/modals/modal.js b/ui/app/components/app/modals/modal.js index 02690722b..0409e901f 100644 --- a/ui/app/components/app/modals/modal.js +++ b/ui/app/components/app/modals/modal.js @@ -24,11 +24,13 @@ import CancelTransaction from './cancel-transaction' import MetaMetricsOptInModal from './metametrics-opt-in-modal' import RejectTransactions from './reject-transactions' -import ClearApprovedOrigins from './clear-approved-origins' import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container' import ConfirmDeleteNetwork from './confirm-delete-network' import AddToAddressBookModal from './add-to-addressbook-modal' import EditApprovalPermission from './edit-approval-permission' +import NewAccountModal from './new-account-modal' +import DisconnectAccount from './disconnect-account' +import DisconnectAll from './disconnect-all' const modalContainerBaseStyle = { transform: 'translate3d(-50%, 0, 0px)', @@ -139,6 +141,87 @@ const MODALS = { }, }, + NEW_ACCOUNT: { + contents: , + mobileModalStyle: { + width: '95%', + top: '10%', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', + borderRadius: '10px', + }, + laptopModalStyle: { + width: '375px', + top: '10%', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', + borderRadius: '10px', + }, + contentStyle: { + borderRadius: '10px', + }, + }, + + DISCONNECT_ACCOUNT: { + contents: , + mobileModalStyle: { + width: '95%', + top: '10%', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', + borderRadius: '10px', + }, + laptopModalStyle: { + width: '375px', + top: '10%', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', + borderRadius: '10px', + }, + contentStyle: { + borderRadius: '10px', + }, + }, + + DISCONNECT_ALL: { + contents: , + mobileModalStyle: { + width: '95%', + top: '10%', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', + borderRadius: '10px', + }, + laptopModalStyle: { + width: '375px', + top: '10%', + boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', + borderRadius: '10px', + }, + contentStyle: { + borderRadius: '10px', + }, + }, + ACCOUNT_DETAILS: { contents: , ...accountModalStyle, @@ -161,19 +244,6 @@ const MODALS = { }, }, - CLEAR_APPROVED_ORIGINS: { - contents: , - mobileModalStyle: { - ...modalContainerMobileStyle, - }, - laptopModalStyle: { - ...modalContainerLaptopStyle, - }, - contentStyle: { - borderRadius: '8px', - }, - }, - METAMETRICS_OPT_IN_MODAL: { contents: , mobileModalStyle: { diff --git a/ui/app/components/app/modals/new-account-modal/index.js b/ui/app/components/app/modals/new-account-modal/index.js new file mode 100644 index 000000000..2c8b78890 --- /dev/null +++ b/ui/app/components/app/modals/new-account-modal/index.js @@ -0,0 +1 @@ +export { default } from './new-account-modal.container' diff --git a/ui/app/components/app/modals/new-account-modal/index.scss b/ui/app/components/app/modals/new-account-modal/index.scss new file mode 100644 index 000000000..d6c2d0ac1 --- /dev/null +++ b/ui/app/components/app/modals/new-account-modal/index.scss @@ -0,0 +1,37 @@ +.new-account-modal { + @extend %col-nowrap; + @extend %modal; + + &__content { + @extend %col-nowrap; + padding: 1.5rem; + border-bottom: 1px solid $Grey-100; + + &__header { + @extend %h3; + } + } + + &__input-label { + color: $Grey-600; + margin-top: 1.25rem; + } + + &__input { + @extend %input; + margin-top: 0.75rem; + + &::placeholder { + color: $Grey-300; + } + } + + &__footer { + @extend %row-nowrap; + padding: 1rem; + + button + button { + margin-left: 1rem; + } + } +} diff --git a/ui/app/components/app/modals/new-account-modal/new-account-modal.component.js b/ui/app/components/app/modals/new-account-modal/new-account-modal.component.js new file mode 100644 index 000000000..26224ae63 --- /dev/null +++ b/ui/app/components/app/modals/new-account-modal/new-account-modal.component.js @@ -0,0 +1,78 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import Button from '../../../ui/button/button.component' + +export default class NewAccountModal extends Component { + + static contextTypes = { + t: PropTypes.func, + } + + static propTypes = { + hideModal: PropTypes.func.isRequired, + newAccountNumber: PropTypes.number.isRequired, + onSave: PropTypes.func.isRequired, + } + + state = { + alias: '', + } + + onChange = e => { + this.setState({ + alias: e.target.value, + }) + } + + onSubmit = () => { + this.props.onSave(this.state.alias) + .then(this.props.hideModal) + } + + onKeyPress = e => { + if (e.key === 'Enter' && this.state.alias) { + this.onSubmit() + } + } + + render () { + const { t } = this.context + + return ( +
+
+
+ {t('newAccount')} +
+
+ {t('accountName')} +
+ +
+
+ + +
+
+ ) + } +} diff --git a/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js b/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js new file mode 100644 index 000000000..812e98dbd --- /dev/null +++ b/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js @@ -0,0 +1,44 @@ +import { connect } from 'react-redux' +import NewAccountModal from './new-account-modal.component' +import actions from '../../../../store/actions' + +function mapStateToProps (state) { + return { + ...state.appState.modal.modalState.props || {}, + } +} + +function mapDispatchToProps (dispatch) { + return { + hideModal: () => dispatch(actions.hideModal()), + createAccount: newAccountName => { + return dispatch(actions.addNewAccount()) + .then(newAccountAddress => { + if (newAccountName) { + dispatch(actions.setAccountLabel(newAccountAddress, newAccountName)) + } + return newAccountAddress + }) + }, + } +} + +function mergeProps (stateProps, dispatchProps) { + const { + onCreateNewAccount, + } = stateProps + const { + createAccount, + } = dispatchProps + + return { + ...stateProps, + ...dispatchProps, + onSave: (newAccountName) => { + return createAccount(newAccountName) + .then(newAccountAddress => onCreateNewAccount(newAccountAddress)) + }, + } +} + +export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(NewAccountModal) diff --git a/ui/app/components/app/permission-page-container/index.js b/ui/app/components/app/permission-page-container/index.js new file mode 100644 index 000000000..ea3b8daaa --- /dev/null +++ b/ui/app/components/app/permission-page-container/index.js @@ -0,0 +1,3 @@ +export {default} from './permission-page-container.container' +export {default as PermissionPageContainerContent} from './permission-page-container-content' +export {default as PermissionPageContainerHeader} from './permission-page-container-header' diff --git a/ui/app/components/app/permission-page-container/index.scss b/ui/app/components/app/permission-page-container/index.scss new file mode 100644 index 000000000..7979867fa --- /dev/null +++ b/ui/app/components/app/permission-page-container/index.scss @@ -0,0 +1,281 @@ +.permission-approval-container { + display: flex; + border: none; + box-shadow: none; + margin-top: 45px; + width: 466px; + min-height: 468px; + + &__header { + display: flex; + flex-direction: column; + align-items: flex-end; + border-bottom: 1px solid $geyser; + padding: 9px; + } + + &__title { + @extend %header--18; + line-height: 25px; + text-align: center; + position: fixed; + left: 0; + width: 100%; + } + + &__content { + display: flex; + overflow-y: auto; + flex: 1; + flex-direction: column; + color: #7C808E; + + &--redirect { + margin-top: 60px; + } + + h1, h2 { + color: #4A4A4A; + display: flex; + justify-content: center; + text-align: center; + } + + h2 { + font-size: 16px; + line-height: 18px; + padding: 20px; + } + + h1 { + font-size: 22px; + line-height: 26px; + padding: 20px; + } + + p { + padding: 0 40px; + text-align: center; + font-size: 12px; + line-height: 18px; + } + + a, a:hover { + color: $dodger-blue; + } + + section { + h1 { + padding: 30px 0px 0px 0px; + } + + h2 { + padding: 0px 0px 20px 0px; + } + } + + &__requested { + text-align: left; + } + + &__revoke-note { + margin-top: 24px; + } + + &__checkbox { + margin-right: 10px; + } + + &__permission { + margin-top: 18px; + + i { + color: #6A737D; + } + label { + margin-left: 6px; + color: #24292E; + } + } + + .permission-approval-visual { + display: flex; + flex-direction: row; + justify-content: space-evenly; + position: relative; + margin: 0 32px; + margin-top: 40px; + + section { + display: flex; + flex-direction: column; + align-items: center; + flex: 1; + } + + h1 { + font-size: 14px; + line-height: 18px; + padding: 8px 0 0; + } + + h2 { + font-size: 12px; + line-height: 17px; + color: #6A737D; + padding: 0; + } + + &__check { + width: 40px; + height: 40px; + background: white url("/images/permissions-check.svg") no-repeat; + margin-top: 24px; + z-index: 1; + } + + &__reject { + background: white; + z-index: 1; + display: flex; + justify-content: center; + align-items: center; + + i { + color: #D73A49; + transform: scale(3); + } + } + + &__broken-line { + z-index: 0; + position: absolute; + top: 43px; + } + + &__identicon, .icon-with-fallback__identicon { + width: 32px; + height: 32px; + z-index: 1; + + &--default { + background-color: #777A87; + color: white; + width: 64px; + height: 64px; + border-radius: 32px; + display: flex; + align-items: center; + justify-content: center; + font-weight: bold; + z-index: 1; + } + } + + &__identicon-container, .icon-with-fallback__identicon-container { + padding: 1rem; + flex: 1; + position: relative; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + } + + &__identicon-border, .icon-with-fallback__identicon-border { + height: 64px; + width: 64px; + border-radius: 50%; + border: 1px solid white; + position: absolute; + background: #FFFFFF; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.25); + } + + &:before { + border-top: 2px dashed #CDD1E4; + content: ""; + margin: 0 auto; + position: absolute; + top: 32px; + left: 0; + bottom: 0; + right: 0; + width: 65%; + z-index: -1; + } + + &__account-info { + display: flex; + flex-direction: column; + align-items: center; + + &__label { + @extend %content-text; + line-height: 20px; + color: #000000; + } + + &__address { + @extend %font; + font-size: 12px; + line-height: 17px; + color: #6A737D; + } + } + } + + .secure-badge { + display: flex; + justify-content: center; + padding: 25px; + } + } + + &__permissions-header { + @extend %content-text; + line-height: 20px; + color: #6A737D; + + &--redirect { + text-align: center; + } + } + + &__permissions-container { + display: flex; + flex-direction: column; + margin-top: 33px; + } + + .page-container__footer { + border-top: none; + align-items: center; + + header { + width: 300px; + } + } + + &__permissions-header-redirect { + text-align: center; + } + + @media screen and (max-width: 575px) { + width: 100%; + margin-top: 25px; + padding: 10px; + + &__title { + position: initial; + } + + &__content-approval-visual { + margin-top: 16px; + } + + .page-container__footer header { + padding: 0; + } + } +} diff --git a/ui/app/components/app/permission-page-container/permission-page-container-content/index.js b/ui/app/components/app/permission-page-container/permission-page-container-content/index.js new file mode 100644 index 000000000..899d168f9 --- /dev/null +++ b/ui/app/components/app/permission-page-container/permission-page-container-content/index.js @@ -0,0 +1 @@ +export {default} from './permission-page-container-content.component' diff --git a/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js b/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js new file mode 100644 index 000000000..d6a62dbbf --- /dev/null +++ b/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js @@ -0,0 +1,163 @@ +import PropTypes from 'prop-types' +import React, { PureComponent } from 'react' +import Identicon from '../../../ui/identicon' +import IconWithFallBack from '../../../ui/icon-with-fallback' +import classnames from 'classnames' + +export default class PermissionPageContainerContent extends PureComponent { + + static propTypes = { + requestMetadata: PropTypes.object.isRequired, + domainMetadata: PropTypes.object.isRequired, + selectedPermissions: PropTypes.object.isRequired, + permissionsDescriptions: PropTypes.object.isRequired, + onPermissionToggle: PropTypes.func.isRequired, + selectedAccount: PropTypes.object, + redirect: PropTypes.bool, + permissionRejected: PropTypes.bool, + } + + static defaultProps = { + redirect: null, + permissionRejected: null, + selectedAccount: {}, + } + + static contextTypes = { + t: PropTypes.func, + } + + renderAccountInfo = (account) => { + return ( +
+
+ { account.label } +
+
+ { account.truncatedAddress } +
+
+ ) + } + + renderPermissionApprovalVisual = () => { + const { + requestMetadata, domainMetadata, selectedAccount, redirect, permissionRejected, + } = this.props + + return ( +
+
+ + { redirect ? null :

{domainMetadata.name}

} + { redirect ? null :

{requestMetadata.origin}

} +
+ { permissionRejected + ? + : + } + +
+
+
+ +
+ { redirect ? null : this.renderAccountInfo(selectedAccount) } +
+
+ ) + } + + renderRequestedPermissions () { + const { + selectedPermissions, permissionsDescriptions, onPermissionToggle, + } = this.props + const { t } = this.context + + const items = Object.keys(selectedPermissions).map((methodName) => { + + // the request will almost certainly be reject by rpc-cap if this happens + if (!permissionsDescriptions[methodName]) { + console.warn(`Unknown permission requested: ${methodName}`) + } + const description = permissionsDescriptions[methodName] || methodName + // don't allow deselecting eth_accounts + const isDisabled = methodName === 'eth_accounts' + + return ( +
{ + if (!isDisabled) { + onPermissionToggle(methodName) + } + }} + > + { selectedPermissions[methodName] + ? + : + } + +
+ ) + }) + + return ( +
+ {items} +
{ t('revokeInPermissions') }
+
+ ) + } + + render () { + const { domainMetadata, redirect, permissionRejected } = this.props + const { t } = this.context + + let titleArgs + if (redirect && permissionRejected) { + titleArgs = [ 'cancelledConnectionWithMetaMask' ] + } else if (redirect) { + titleArgs = [ 'connectingWithMetaMask' ] + } else if (domainMetadata.extensionId) { + titleArgs = [ 'externalExtension', [domainMetadata.extensionId] ] + } else { + titleArgs = [ 'likeToConnect', [domainMetadata.name] ] + } + + return ( +
+
+ { t(...titleArgs) } +
+ {this.renderPermissionApprovalVisual()} + { !redirect + ? ( +
+
+ { domainMetadata.extensionId + ? t('thisWillAllowExternalExtension', [domainMetadata.extensionId]) + : t('thisWillAllow', [domainMetadata.name]) + } +
+ { this.renderRequestedPermissions() } +
+ ) + : ( +
+ { t('redirectingBackToDapp') } +
+ ) + } +
+ ) + } +} diff --git a/ui/app/components/app/permission-page-container/permission-page-container-header/index.js b/ui/app/components/app/permission-page-container/permission-page-container-header/index.js new file mode 100644 index 000000000..45ef9036b --- /dev/null +++ b/ui/app/components/app/permission-page-container/permission-page-container-header/index.js @@ -0,0 +1 @@ +export {default} from './permission-page-container-header.component' diff --git a/ui/app/components/app/provider-page-container/provider-page-container-header/provider-page-container-header.component.js b/ui/app/components/app/permission-page-container/permission-page-container-header/permission-page-container-header.component.js similarity index 58% rename from ui/app/components/app/provider-page-container/provider-page-container-header/provider-page-container-header.component.js rename to ui/app/components/app/permission-page-container/permission-page-container-header/permission-page-container-header.component.js index 41bf6c3dd..8ba3444ba 100644 --- a/ui/app/components/app/provider-page-container/provider-page-container-header/provider-page-container-header.component.js +++ b/ui/app/components/app/permission-page-container/permission-page-container-header/permission-page-container-header.component.js @@ -1,10 +1,10 @@ import React, {PureComponent} from 'react' import NetworkDisplay from '../../network-display' -export default class ProviderPageContainerHeader extends PureComponent { +export default class PermissionPageContainerHeader extends PureComponent { render () { return ( -
+
) diff --git a/ui/app/components/app/permission-page-container/permission-page-container.component.js b/ui/app/components/app/permission-page-container/permission-page-container.component.js new file mode 100644 index 000000000..b7cbcd6ba --- /dev/null +++ b/ui/app/components/app/permission-page-container/permission-page-container.component.js @@ -0,0 +1,151 @@ +import PropTypes from 'prop-types' +import React, { Component } from 'react' +import deepEqual from 'fast-deep-equal' +import { PermissionPageContainerContent } from '.' +import { PageContainerFooter } from '../../ui/page-container' + +export default class PermissionPageContainer extends Component { + + static propTypes = { + approvePermissionsRequest: PropTypes.func.isRequired, + rejectPermissionsRequest: PropTypes.func.isRequired, + selectedIdentity: PropTypes.object, + permissionsDescriptions: PropTypes.object.isRequired, + request: PropTypes.object, + redirect: PropTypes.bool, + permissionRejected: PropTypes.bool, + requestMetadata: PropTypes.object, + targetDomainMetadata: PropTypes.object.isRequired, + }; + + static defaultProps = { + redirect: null, + permissionRejected: null, + request: {}, + requestMetadata: {}, + selectedIdentity: {}, + }; + + static contextTypes = { + t: PropTypes.func, + metricsEvent: PropTypes.func, + }; + + state = { + selectedPermissions: this.getRequestedMethodState( + this.getRequestedMethodNames(this.props) + ), + } + + componentDidUpdate () { + const newMethodNames = this.getRequestedMethodNames(this.props) + + if (!deepEqual(Object.keys(this.state.selectedPermissions), newMethodNames)) { + // this should be a new request, so just overwrite + this.setState({ + selectedPermissions: this.getRequestedMethodState(newMethodNames), + }) + } + } + + getRequestedMethodState (methodNames) { + return methodNames.reduce( + (acc, methodName) => { + acc[methodName] = true + return acc + }, + {} + ) + } + + getRequestedMethodNames (props) { + return Object.keys(props.request.permissions || {}) + } + + onPermissionToggle = methodName => { + this.setState({ + selectedPermissions: { + ...this.state.selectedPermissions, + [methodName]: !this.state.selectedPermissions[methodName], + }, + }) + } + + componentDidMount () { + this.context.metricsEvent({ + eventOpts: { + category: 'Auth', + action: 'Connect', + name: 'Tab Opened', + }, + }) + } + + onCancel = () => { + const { request, rejectPermissionsRequest } = this.props + rejectPermissionsRequest(request.metadata.id) + } + + onSubmit = () => { + const { + request: _request, approvePermissionsRequest, rejectPermissionsRequest, selectedIdentity, + } = this.props + + const request = { + ..._request, + permissions: { ..._request.permissions }, + } + + Object.keys(this.state.selectedPermissions).forEach(key => { + if (!this.state.selectedPermissions[key]) { + delete request.permissions[key] + } + }) + + if (Object.keys(request.permissions).length > 0) { + approvePermissionsRequest(request, [selectedIdentity.address]) + } else { + rejectPermissionsRequest(request.metadata.id) + } + } + + render () { + const { + requestMetadata, + targetDomainMetadata, + permissionsDescriptions, + selectedIdentity, + redirect, + permissionRejected, + } = this.props + + return ( +
+ + { !redirect + ? ( + this.onCancel()} + cancelText={this.context.t('cancel')} + onSubmit={() => this.onSubmit()} + submitText={this.context.t('submit')} + submitButtonType="confirm" + buttonSizeLarge={false} + /> + ) + : null + } +
+ ) + } +} diff --git a/ui/app/components/app/permission-page-container/permission-page-container.container.js b/ui/app/components/app/permission-page-container/permission-page-container.container.js new file mode 100644 index 000000000..f83393c70 --- /dev/null +++ b/ui/app/components/app/permission-page-container/permission-page-container.container.js @@ -0,0 +1,28 @@ +import { connect } from 'react-redux' +import { compose } from 'recompose' +import { withRouter } from 'react-router-dom' +import PermissionPageContainer from './permission-page-container.component' +import { + getPermissionsDescriptions, + getDomainMetadata, +} from '../../../selectors/selectors' + +const mapStateToProps = (state, ownProps) => { + const { request, cachedOrigin } = ownProps + const { metadata: requestMetadata = {} } = request || {} + + const domainMetadata = getDomainMetadata(state) + const origin = requestMetadata.origin || cachedOrigin + const targetDomainMetadata = (domainMetadata[origin] || { name: origin, icon: null }) + + return { + permissionsDescriptions: getPermissionsDescriptions(state), + requestMetadata, + targetDomainMetadata, + } +} + +export default compose( + withRouter, + connect(mapStateToProps) +)(PermissionPageContainer) diff --git a/ui/app/components/app/provider-page-container/index.js b/ui/app/components/app/provider-page-container/index.js deleted file mode 100644 index 927c35940..000000000 --- a/ui/app/components/app/provider-page-container/index.js +++ /dev/null @@ -1,3 +0,0 @@ -export {default} from './provider-page-container.component' -export {default as ProviderPageContainerContent} from './provider-page-container-content' -export {default as ProviderPageContainerHeader} from './provider-page-container-header' diff --git a/ui/app/components/app/provider-page-container/index.scss b/ui/app/components/app/provider-page-container/index.scss deleted file mode 100644 index 8d35ac179..000000000 --- a/ui/app/components/app/provider-page-container/index.scss +++ /dev/null @@ -1,121 +0,0 @@ -.provider-approval-container { - display: flex; - - &__header { - display: flex; - flex-direction: column; - align-items: flex-end; - border-bottom: 1px solid $geyser; - padding: 9px; - } - - &__content { - display: flex; - overflow-y: auto; - flex: 1; - flex-direction: column; - justify-content: space-between; - color: #7C808E; - - h1, h2 { - color: #4A4A4A; - display: flex; - justify-content: center; - text-align: center; - } - - h2 { - font-size: 16px; - line-height: 18px; - padding: 20px; - } - - h1 { - font-size: 22px; - line-height: 26px; - padding: 20px; - } - - p { - padding: 0 40px; - text-align: center; - font-size: 12px; - line-height: 18px; - } - - a, a:hover { - color: $dodger-blue; - } - - .provider-approval-visual { - display: flex; - flex-direction: row; - justify-content: space-evenly; - position: relative; - margin: 0 32px; - - section { - display: flex; - flex-direction: column; - align-items: center; - flex: 1; - } - - h1 { - font-size: 14px; - line-height: 18px; - padding: 8px 0 0; - } - - h2 { - font-size: 10px; - line-height: 14px; - padding: 0; - color: #A2A4AC; - } - - &__check { - width: 40px; - height: 40px; - background: white url("/images/provider-approval-check.svg") no-repeat; - margin-top: 14px; - } - - &__identicon { - width: 64px; - height: 64px; - - &--default { - background-color: #777A87; - color: white; - width: 64px; - height: 64px; - border-radius: 32px; - display: flex; - align-items: center; - justify-content: center; - font-weight: bold; - } - } - - &:before { - border-top: 2px dashed #CDD1E4; - content: ""; - margin: 0 auto; - position: absolute; - top: 32px; - left: 0; - bottom: 0; - right: 0; - width: 65%; - z-index: -1; - } - } - - .secure-badge { - display: flex; - justify-content: center; - padding: 25px; - } - } -} diff --git a/ui/app/components/app/provider-page-container/provider-page-container-content/index.js b/ui/app/components/app/provider-page-container/provider-page-container-content/index.js deleted file mode 100644 index 73e491adc..000000000 --- a/ui/app/components/app/provider-page-container/provider-page-container-content/index.js +++ /dev/null @@ -1 +0,0 @@ -export {default} from './provider-page-container-content.container' diff --git a/ui/app/components/app/provider-page-container/provider-page-container-content/provider-page-container-content.component.js b/ui/app/components/app/provider-page-container/provider-page-container-content/provider-page-container-content.component.js deleted file mode 100644 index 4f94015b1..000000000 --- a/ui/app/components/app/provider-page-container/provider-page-container-content/provider-page-container-content.component.js +++ /dev/null @@ -1,87 +0,0 @@ -import PropTypes from 'prop-types' -import React, {PureComponent} from 'react' -import Identicon from '../../../ui/identicon' - -export default class ProviderPageContainerContent extends PureComponent { - static propTypes = { - origin: PropTypes.string.isRequired, - selectedIdentity: PropTypes.object.isRequired, - siteImage: PropTypes.string, - siteTitle: PropTypes.string, - hostname: PropTypes.string, - extensionId: PropTypes.string, - } - - static contextTypes = { - t: PropTypes.func, - }; - - renderConnectVisual = (title, identifier) => { - const { selectedIdentity, siteImage } = this.props - - return ( -
-
- {siteImage ? ( - - ) : ( - - {title.charAt(0).toUpperCase()} - - )} -

{title}

-

{identifier}

-
- -
- -

{selectedIdentity.name}

-
-
- ) - } - - render () { - const { siteTitle, hostname, extensionId } = this.props - const { t } = this.context - - const title = extensionId ? - 'External Extension' : - siteTitle || hostname - - const identifier = extensionId ? - `Extension ID: '${extensionId}'` : - hostname - - return ( -
-
-

{t('connectRequest')}

- {this.renderConnectVisual(title, identifier)} -

{t('providerRequest', [title])}

-

- {t('providerRequestInfo')} -
- - {t('learnMore')}. - -

-
-
- -
-
- ) - } -} diff --git a/ui/app/components/app/provider-page-container/provider-page-container-content/provider-page-container-content.container.js b/ui/app/components/app/provider-page-container/provider-page-container-content/provider-page-container-content.container.js deleted file mode 100644 index 4dbdddd16..000000000 --- a/ui/app/components/app/provider-page-container/provider-page-container-content/provider-page-container-content.container.js +++ /dev/null @@ -1,11 +0,0 @@ -import { connect } from 'react-redux' -import ProviderPageContainerContent from './provider-page-container-content.component' -import { getSelectedIdentity } from '../../../../selectors/selectors' - -const mapStateToProps = (state) => { - return { - selectedIdentity: getSelectedIdentity(state), - } -} - -export default connect(mapStateToProps)(ProviderPageContainerContent) diff --git a/ui/app/components/app/provider-page-container/provider-page-container-header/index.js b/ui/app/components/app/provider-page-container/provider-page-container-header/index.js deleted file mode 100644 index 430627d3a..000000000 --- a/ui/app/components/app/provider-page-container/provider-page-container-header/index.js +++ /dev/null @@ -1 +0,0 @@ -export {default} from './provider-page-container-header.component' diff --git a/ui/app/components/app/provider-page-container/provider-page-container.component.js b/ui/app/components/app/provider-page-container/provider-page-container.component.js deleted file mode 100644 index 7d152e4cb..000000000 --- a/ui/app/components/app/provider-page-container/provider-page-container.component.js +++ /dev/null @@ -1,107 +0,0 @@ -import PropTypes from 'prop-types' -import React, {PureComponent} from 'react' -import { ProviderPageContainerContent, ProviderPageContainerHeader } from '.' -import { PageContainerFooter } from '../../ui/page-container' -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../../app/scripts/lib/enums' -import { getEnvironmentType } from '../../../../../app/scripts/lib/util' - -export default class ProviderPageContainer extends PureComponent { - static propTypes = { - approveProviderRequestByOrigin: PropTypes.func.isRequired, - rejectProviderRequestByOrigin: PropTypes.func.isRequired, - origin: PropTypes.string.isRequired, - siteImage: PropTypes.string, - siteTitle: PropTypes.string, - hostname: PropTypes.string, - extensionId: PropTypes.string, - }; - - static contextTypes = { - t: PropTypes.func, - metricsEvent: PropTypes.func, - }; - - componentDidMount () { - if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_NOTIFICATION) { - window.addEventListener('beforeunload', this._beforeUnload) - } - this.context.metricsEvent({ - eventOpts: { - category: 'Auth', - action: 'Connect', - name: 'Popup Opened', - }, - }) - } - - _beforeUnload = () => { - const { origin, rejectProviderRequestByOrigin } = this.props - this.context.metricsEvent({ - eventOpts: { - category: 'Auth', - action: 'Connect', - name: 'Cancel Connect Request Via Notification Close', - }, - }) - this._removeBeforeUnload() - rejectProviderRequestByOrigin(origin) - } - - _removeBeforeUnload () { - window.removeEventListener('beforeunload', this._beforeUnload) - } - - componentWillUnmount () { - this._removeBeforeUnload() - } - - onCancel = () => { - const { origin, rejectProviderRequestByOrigin } = this.props - this.context.metricsEvent({ - eventOpts: { - category: 'Auth', - action: 'Connect', - name: 'Canceled', - }, - }) - this._removeBeforeUnload() - rejectProviderRequestByOrigin(origin) - } - - onSubmit = () => { - const { approveProviderRequestByOrigin, origin } = this.props - this.context.metricsEvent({ - eventOpts: { - category: 'Auth', - action: 'Connect', - name: 'Confirmed', - }, - }) - this._removeBeforeUnload() - approveProviderRequestByOrigin(origin) - } - - render () { - const {origin, siteImage, siteTitle, hostname, extensionId} = this.props - - return ( -
- - - this.onCancel()} - cancelText={this.context.t('cancel')} - onSubmit={() => this.onSubmit()} - submitText={this.context.t('connect')} - submitButtonType="confirm" - /> -
- ) - } -} diff --git a/ui/app/components/app/wallet-view/wallet-view.component.js b/ui/app/components/app/wallet-view/wallet-view.component.js index ceccfea51..dc3abf259 100644 --- a/ui/app/components/app/wallet-view/wallet-view.component.js +++ b/ui/app/components/app/wallet-view/wallet-view.component.js @@ -7,7 +7,7 @@ import AccountDetails from '../account-details' const { checksumAddress } = require('../../../helpers/utils/util') const TokenList = require('../token-list') -const { ADD_TOKEN_ROUTE } = require('../../../helpers/constants/routes') +const { ADD_TOKEN_ROUTE, CONNECTED_ROUTE } = require('../../../helpers/constants/routes') export default class WalletView extends Component { static contextTypes = { @@ -91,6 +91,18 @@ export default class WalletView extends Component { ) } + showConnectedSites = () => { + const { + sidebarOpen, + hideSidebar, + history, + } = this.props + history.push(CONNECTED_ROUTE) + if (sidebarOpen) { + hideSidebar() + } + } + render () { const { responsiveDisplayClassname, @@ -124,6 +136,7 @@ export default class WalletView extends Component { label={label} checksummedAddress={checksummedAddress} name={identities[selectedAddress].name} + showConnectedSites={this.showConnectedSites} /> {this.renderWalletBalance()} diff --git a/ui/app/components/ui/icon-with-fallback/icon-with-fallback.component.js b/ui/app/components/ui/icon-with-fallback/icon-with-fallback.component.js new file mode 100644 index 000000000..13b3e93d7 --- /dev/null +++ b/ui/app/components/ui/icon-with-fallback/icon-with-fallback.component.js @@ -0,0 +1,42 @@ +import React, { PureComponent } from 'react' +import PropTypes from 'prop-types' + +export default class IconWithFallback extends PureComponent { + static propTypes = { + icon: PropTypes.string, + name: PropTypes.string, + } + + static defaultProps = { + name: '', + icon: null, + } + + state = { + iconError: false, + } + + render () { + const { icon, name } = this.props + + return ( +
+
+ { !this.state.iconError && icon + ? ( + this.setState({ iconError: true })} + /> + ) + : ( + + { name.length ? name.charAt(0).toUpperCase() : '' } + + ) + } +
+ ) + } +} diff --git a/ui/app/components/ui/icon-with-fallback/index.js b/ui/app/components/ui/icon-with-fallback/index.js new file mode 100644 index 000000000..8c1f9a154 --- /dev/null +++ b/ui/app/components/ui/icon-with-fallback/index.js @@ -0,0 +1 @@ +export { default } from './icon-with-fallback.component' diff --git a/ui/app/components/ui/icon-with-fallback/index.scss b/ui/app/components/ui/icon-with-fallback/index.scss new file mode 100644 index 000000000..02ffe371d --- /dev/null +++ b/ui/app/components/ui/icon-with-fallback/index.scss @@ -0,0 +1,30 @@ +.icon-with-fallback { + &__identicon-container { + position: relative; + display: flex; + justify-content: center; + align-items: center; + height: 32px; + width: 32px; + } + + &__identicon-border { + height: 32px; + width: 32px; + border-radius: 50%; + border: 1px solid #F2F3F4; + position: absolute; + background: #FFFFFF; + } + + &__identicon { + width: 24px; + height: 24px; + z-index: 1; + + &--default { + z-index: 1; + color: black; + } + } +} diff --git a/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js b/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js index da8da45d1..338df83d8 100644 --- a/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js +++ b/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js @@ -14,6 +14,7 @@ export default class PageContainerFooter extends Component { disabled: PropTypes.bool, submitButtonType: PropTypes.string, hideCancel: PropTypes.bool, + buttonSizeLarge: PropTypes.bool, } static contextTypes = { @@ -31,6 +32,7 @@ export default class PageContainerFooter extends Component { submitButtonType, hideCancel, cancelButtonType, + buttonSizeLarge = false, } = this.props return ( @@ -40,7 +42,7 @@ export default class PageContainerFooter extends Component { {!hideCancel && ( -
-
- - ) - } - - renderApprovedOriginsList () { - const { t } = this.context - const { approvedOrigins, rejectProviderRequestByOrigin, showClearApprovalModal } = this.props - const approvedEntries = Object.entries(approvedOrigins) - const approvalListEmpty = approvedEntries.length === 0 - - return ( -
-
- { t('connected') } - - { t('connectedDescription') } - -
-
- { - approvalListEmpty - ?
- : null - } - { - approvedEntries.map(([origin, { siteTitle, siteImage }]) => ( - { - rejectProviderRequestByOrigin(origin) - }} - /> - )) - } -
-
- -
-
- ) - } - - render () { - return ( -
- { this.renderNewOriginInput() } - { this.renderApprovedOriginsList() } -
- ) - } -} diff --git a/ui/app/pages/settings/connections-tab/connections-tab.container.js b/ui/app/pages/settings/connections-tab/connections-tab.container.js deleted file mode 100644 index cf3efc2b4..000000000 --- a/ui/app/pages/settings/connections-tab/connections-tab.container.js +++ /dev/null @@ -1,39 +0,0 @@ -import ConnectionsTab from './connections-tab.component' -import { compose } from 'recompose' -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { - approveProviderRequestByOrigin, - rejectProviderRequestByOrigin, - showModal, -} from '../../../store/actions' - -export const mapStateToProps = state => { - const { - activeTab, - metamask, - } = state - const { - approvedOrigins, - } = metamask - - return { - activeTab, - approvedOrigins, - } -} - -export const mapDispatchToProps = dispatch => { - return { - approveProviderRequestByOrigin: (origin) => dispatch(approveProviderRequestByOrigin(origin)), - rejectProviderRequestByOrigin: (origin) => dispatch(rejectProviderRequestByOrigin(origin)), - showClearApprovalModal: () => dispatch(showModal({ - name: 'CLEAR_APPROVED_ORIGINS', - })), - } -} - -export default compose( - withRouter, - connect(mapStateToProps, mapDispatchToProps) -)(ConnectionsTab) diff --git a/ui/app/pages/settings/connections-tab/index.js b/ui/app/pages/settings/connections-tab/index.js deleted file mode 100644 index b04f4e33a..000000000 --- a/ui/app/pages/settings/connections-tab/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './connections-tab.container' diff --git a/ui/app/pages/settings/connections-tab/index.scss b/ui/app/pages/settings/connections-tab/index.scss deleted file mode 100644 index 249a7193f..000000000 --- a/ui/app/pages/settings/connections-tab/index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './connected-site-row/index'; diff --git a/ui/app/pages/settings/index.scss b/ui/app/pages/settings/index.scss index 19545eb51..780b930e7 100644 --- a/ui/app/pages/settings/index.scss +++ b/ui/app/pages/settings/index.scss @@ -4,8 +4,6 @@ @import 'settings-tab/index'; -@import 'connections-tab/index'; - @import 'contact-list-tab/index'; .settings-page { diff --git a/ui/app/pages/settings/settings.component.js b/ui/app/pages/settings/settings.component.js index b0ee55dc7..12d395f31 100644 --- a/ui/app/pages/settings/settings.component.js +++ b/ui/app/pages/settings/settings.component.js @@ -4,7 +4,6 @@ import { Switch, Route, matchPath, withRouter } from 'react-router-dom' import TabBar from '../../components/app/tab-bar' import c from 'classnames' import SettingsTab from './settings-tab' -import ConnectionsTab from './connections-tab' import NetworksTab from './networks-tab' import AdvancedTab from './advanced-tab' import InfoTab from './info-tab' @@ -15,7 +14,6 @@ import { ADVANCED_ROUTE, SECURITY_ROUTE, GENERAL_ROUTE, - CONNECTIONS_ROUTE, ABOUT_US_ROUTE, SETTINGS_ROUTE, NETWORKS_ROUTE, @@ -160,7 +158,6 @@ class SettingsPage extends PureComponent { - { + const { address, name, balance } = account + return { + address, + truncatedAddress: `${address.slice(0, 6)}...${address.slice(-4)}`, + addressLabel: `${name} (...${address.slice(address.length - 4)})`, + label: name, + balance, + } + }) + return accountsWithLabels +} + function getCurrentAccountWithSendEtherInfo (state) { const currentAddress = getSelectedAddress(state) const accounts = accountsWithSendEtherInfoSelector(state) @@ -353,6 +385,22 @@ function getCustomNonceValue (state) { return String(state.metamask.customNonceValue) } +function getPermissionsDescriptions (state) { + return state.metamask.permissionsDescriptions +} + +function getPermissionsRequests (state) { + return state.metamask.permissionsRequests +} + +function getDomainMetadata (state) { + return state.metamask.domainMetadata +} + +function getActiveTab (state) { + return state.activeTab +} + function getMetaMetricState (state) { return { network: getCurrentNetworkId(state), @@ -386,3 +434,144 @@ function getKnownMethodData (state, data) { function getFeatureFlags (state) { return state.metamask.featureFlags } + +function getFirstPermissionRequest (state) { + const requests = getPermissionsRequests(state) + return requests && requests[0] ? requests[0] : null +} + +function hasPermissionRequests (state) { + return Boolean(getFirstPermissionRequest(state)) +} + +function getPermissionsDomains (state) { + return state.metamask.domains +} + +function getAddressConnectedDomainMap (state) { + const { + domains, + domainMetadata, + } = state.metamask + + const addressConnectedIconMap = {} + + if (domains) { + Object.keys(domains).forEach(domainKey => { + const { permissions } = domains[domainKey] + const { icon, name } = domainMetadata[domainKey] || {} + permissions.forEach(perm => { + const caveats = perm.caveats || [] + const exposedAccountCaveat = caveats.find(caveat => caveat.name === 'exposedAccounts') + if (exposedAccountCaveat && exposedAccountCaveat.value && exposedAccountCaveat.value.length) { + exposedAccountCaveat.value.forEach(address => { + const nameToRender = name || domainKey + addressConnectedIconMap[address] = addressConnectedIconMap[address] + ? { ...addressConnectedIconMap[address], [domainKey]: { icon, name: nameToRender } } + : { [domainKey]: { icon, name: nameToRender } } + }) + } + }) + }) + } + + return addressConnectedIconMap +} + +function getDomainToConnectedAddressMap (state) { + const { domains = {} } = state.metamask + + const domainToConnectedAddressMap = mapObjectValues(domains, (_, { permissions }) => { + const ethAccountsPermissions = permissions.filter(permission => permission.parentCapability === 'eth_accounts') + const ethAccountsPermissionsExposedAccountAddresses = ethAccountsPermissions.map(permission => { + const caveats = permission.caveats + const exposedAccountsCaveats = caveats.filter(caveat => caveat.name === 'exposedAccounts') + const exposedAccountsAddresses = exposedAccountsCaveats.map(caveat => caveat.value[0]) + return exposedAccountsAddresses + }) + const allAddressesConnectedToDomain = ethAccountsPermissionsExposedAccountAddresses.reduce((acc, arrayOfAddresses) => { + return [ ...acc, ...arrayOfAddresses ] + }, []) + return allAddressesConnectedToDomain + }) + + return domainToConnectedAddressMap +} + +function getAddressConnectedToCurrentTab (state) { + const domainToConnectedAddressMap = getDomainToConnectedAddressMap(state) + const originOfCurrentTab = getOriginOfCurrentTab(state) + const addressesConnectedToCurrentTab = domainToConnectedAddressMap[originOfCurrentTab] + const addressConnectedToCurrentTab = addressesConnectedToCurrentTab && addressesConnectedToCurrentTab[0] + return addressConnectedToCurrentTab +} + +function getRenderablePermissionsDomains (state) { + const { + domains = {}, + domainMetadata, + permissionsHistory, + permissionsDescriptions, + selectedAddress, + } = state.metamask + + const renderableDomains = Object.keys(domains).reduce((acc, domainKey) => { + const { permissions } = domains[domainKey] + const permissionsWithCaveatsForSelectedAddress = permissions.filter(perm => { + const caveats = perm.caveats || [] + const exposedAccountCaveat = caveats.find(caveat => caveat.name === 'exposedAccounts') + const exposedAccountCaveatValue = exposedAccountCaveat && exposedAccountCaveat.value && exposedAccountCaveat.value.length + ? exposedAccountCaveat.value[0] + : {} + return exposedAccountCaveatValue === selectedAddress + }) + + if (permissionsWithCaveatsForSelectedAddress.length) { + const permissionKeys = permissions.map(permission => permission.parentCapability) + const { + name, + icon, + extensionId, + } = domainMetadata[domainKey] || {} + const permissionsHistoryForDomain = permissionsHistory[domainKey] || {} + const ethAccountsPermissionsForDomain = permissionsHistoryForDomain['eth_accounts'] || {} + const accountsLastConnectedTime = ethAccountsPermissionsForDomain.accounts || {} + const selectedAddressLastConnectedTime = accountsLastConnectedTime[selectedAddress] + + const lastConnectedTime = selectedAddressLastConnectedTime + ? formatDate(selectedAddressLastConnectedTime, 'yyyy-M-d') + : '' + + return [ ...acc, { + name: name || domainKey, + secondaryName: name ? domainKey : '', + icon, + key: domainKey, + lastConnectedTime, + permissionDescriptions: permissionKeys.map(permissionKey => permissionsDescriptions[permissionKey]), + extensionId, + }] + } else { + return acc + } + }, []) + + return renderableDomains +} + +function getOriginOfCurrentTab (state) { + const { activeTab } = state + return activeTab && activeTab.url && getOriginFromUrl(activeTab.url) +} + +function getLastConnectedInfo (state) { + const { permissionsHistory = {} } = state.metamask + const lastConnectedInfoData = Object.keys(permissionsHistory).reduce((acc, origin) => { + const ethAccountsHistory = JSON.parse(JSON.stringify(permissionsHistory[origin]['eth_accounts'])) + return { + ...acc, + [origin]: ethAccountsHistory.accounts, + } + }, {}) + return lastConnectedInfoData +} diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index d6c29fcd6..a09548f0f 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -328,7 +328,6 @@ const actions = { setUseNativeCurrencyAsPrimaryCurrencyPreference, setShowFiatConversionOnTestnetsPreference, setAutoLogoutTimeLimit, - unsetMigratedPrivacyMode, // Onboarding setCompletedOnboarding, @@ -352,9 +351,12 @@ const actions = { createSpeedUpTransaction, createRetryTransaction, - approveProviderRequestByOrigin, - rejectProviderRequestByOrigin, - clearApprovedOrigins, + // Permissions + approvePermissionsRequest, + clearPermissions, + rejectPermissionsRequest, + removePermissionsFor, + legacyExposeAccounts, setFirstTimeFlowType, SET_FIRST_TIME_FLOW_TYPE: 'SET_FIRST_TIME_FLOW_TYPE', @@ -395,6 +397,13 @@ const actions = { turnThreeBoxSyncingOnAndInitialize, tryReverseResolveAddress, + + getRequestAccountTabIds, + getCurrentWindowTab, + SET_REQUEST_ACCOUNT_TABS: 'SET_REQUEST_ACCOUNT_TABS', + SET_CURRENT_WINDOW_TAB: 'SET_CURRENT_WINDOW_TAB', + getOpenMetamaskTabsIds, + SET_OPEN_METAMASK_TAB_IDS: 'SET_OPEN_METAMASK_TAB_IDS', } module.exports = actions @@ -2709,24 +2718,59 @@ function setPendingTokens (pendingTokens) { } } -function approveProviderRequestByOrigin (origin) { +// Permissions + +/** + * Approves the permission requests with the given IDs. + * @param {string} requestId - The id of the permissions request. + * @param {string[]} accounts - The accounts to expose, if any. + */ +function approvePermissionsRequest (requestId, accounts) { return () => { - background.approveProviderRequestByOrigin(origin) + background.approvePermissionsRequest(requestId, accounts) } } -function rejectProviderRequestByOrigin (origin) { +/** + * Rejects the permission requests with the given IDs. + * @param {Array} requestId + */ +function rejectPermissionsRequest (requestId) { return () => { - background.rejectProviderRequestByOrigin(origin) + background.rejectPermissionsRequest(requestId) } } -function clearApprovedOrigins () { +/** + * Exposes the given account(s) to the given origin. + * Call ONLY as a result of direct user action. + */ +function legacyExposeAccounts (origin, accounts) { return () => { - background.clearApprovedOrigins() + return background.legacyExposeAccounts(origin, accounts) } } +/** + * Clears the given permissions for the given origin. + */ +function removePermissionsFor (domains) { + return () => { + background.removePermissionsFor(domains) + } +} + +/** + * Clears all permissions for all domains. + */ +function clearPermissions () { + return () => { + background.clearPermissions() + } +} + +// //// + function setFirstTimeFlowType (type) { return (dispatch) => { log.debug(`background.setFirstTimeFlowType`) @@ -2847,12 +2891,6 @@ function getTokenParams (tokenAddress) { } } -function unsetMigratedPrivacyMode () { - return () => { - background.unsetMigratedPrivacyMode() - } -} - function setSeedPhraseBackedUp (seedPhraseBackupState) { return (dispatch) => { log.debug(`background.setSeedPhraseBackedUp`) @@ -2990,3 +3028,46 @@ function getNextNonce () { }) } } + +function setRequestAccountTabIds (requestAccountTabIds) { + return { + type: actions.SET_REQUEST_ACCOUNT_TABS, + value: requestAccountTabIds, + } +} + +function getRequestAccountTabIds () { + return async (dispatch) => { + const requestAccountTabIds = await pify(background.getRequestAccountTabIds).call(background) + dispatch(setRequestAccountTabIds(requestAccountTabIds)) + } +} + +function setOpenMetamaskTabsIDs (openMetaMaskTabIDs) { + return { + type: actions.SET_OPEN_METAMASK_TAB_IDS, + value: openMetaMaskTabIDs, + } +} + +function getOpenMetamaskTabsIds () { + return async (dispatch) => { + const openMetaMaskTabIDs = await pify(background.getOpenMetamaskTabsIds).call(background) + dispatch(setOpenMetamaskTabsIDs(openMetaMaskTabIDs)) + } +} + +function setCurrentWindowTab (currentWindowTab) { + return { + type: actions.SET_CURRENT_WINDOW_TAB, + value: currentWindowTab, + } +} + + +function getCurrentWindowTab () { + return async (dispatch) => { + const currentWindowTab = await global.platform.currentTab() + dispatch(setCurrentWindowTab(currentWindowTab)) + } +} diff --git a/yarn.lock b/yarn.lock index edd2a97fb..867488627 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10075,7 +10075,7 @@ eth-hd-keyring@^3.4.0: events "^1.1.1" xtend "^4.0.1" -eth-json-rpc-errors@^1.0.1, eth-json-rpc-errors@^1.1.0: +eth-json-rpc-errors@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/eth-json-rpc-errors/-/eth-json-rpc-errors-1.1.0.tgz#2a4291fb20c0483c99b53286a814ed14ca4efb2e" integrity sha512-AAA76BmwwSR5Mws+ivZUYxoDwMygDuMWxSTEmqDXhRPTExSWe5wuJLT/rSfvPSy9+owSudy67JmyRQ02RAOOYQ== @@ -12164,7 +12164,7 @@ fuse.js@^3.4.4: resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.4.5.tgz#8954fb43f9729bd5dbcb8c08f251db552595a7a6" integrity sha512-s9PGTaQIkT69HaeoTVjwGsLfb8V8ScJLx5XGFcKHg0MqLUH/UZ4EKOtqtXX9k7AFqCGxD1aJmYb8Q5VYDibVRQ== -gaba@^1.9.0: +gaba@^1.6.0, gaba@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/gaba/-/gaba-1.9.0.tgz#ccd9f99c56687b5acd39f9e3ceb435b2a59b6aa1" integrity sha512-HoVreAdZssL0jNHuzZ7WP+YKZ0riu44jVDWxhQ9hsgPuzxbVEsz9fO/HDxqAdNZS1Cswayq6+ciZ3HSCFWMKbQ== @@ -14247,6 +14247,11 @@ interpret@^1.2.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== +intersect-objects@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/intersect-objects/-/intersect-objects-1.0.0.tgz#b7630d28994b89b0f04d44728106136549ce816e" + integrity sha512-MS1xypHKJhWopnJgn4IbitVvt2vFy2KjINQJAPhAtDejZ+ZbMDfyPc6JsS/mWFRt9Eoku4A4usE4f2loEOoeKQ== + into-stream@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" @@ -17596,12 +17601,12 @@ lodash.uniqby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" integrity sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI= -lodash@4.17.14, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.8.0, lodash@~4.17.10, lodash@~4.17.2, lodash@~4.17.4: +lodash@4.17.14, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.8.0, lodash@~4.17.10, lodash@~4.17.2, lodash@~4.17.4: version "4.17.14" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== -lodash@=3.10.1, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15: +lodash@=3.10.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -18213,12 +18218,14 @@ mersenne-twister@^1.0.1: resolved "https://registry.yarnpkg.com/mersenne-twister/-/mersenne-twister-1.1.0.tgz#f916618ee43d7179efcf641bec4531eb9670978a" integrity sha1-+RZhjuQ9cXnvz2Qb7EUx65Zwl4o= -metamask-inpage-provider@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/metamask-inpage-provider/-/metamask-inpage-provider-3.0.0.tgz#3b9d4bae6f67962b6a7b1a9ee1efaf424f67b6f4" - integrity sha512-44bBCbQwcFF/XGaXSweCWHJaslKhJEFgvcHdxZf9Fm1QfK7VN4U3iAI0BVOLAIkRg0xV3w7xYGLpx2cM1BU7Qw== +metamask-inpage-provider@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/metamask-inpage-provider/-/metamask-inpage-provider-4.0.2.tgz#50d9e46b5fdd6610ce185a165004e3c6b762dbb3" + integrity sha512-GXoMa7rP+fx9CriCA+RPHjvJJpfy9531eRdMvbDKv0q95/1pvtzYkj6BdzjxtbM91n4zYl6tmeKDILu+le9Qog== dependencies: - json-rpc-engine "^5.1.3" + eth-json-rpc-errors "^2.0.0" + fast-deep-equal "^2.0.1" + json-rpc-engine "^5.1.5" json-rpc-middleware-stream "^2.1.1" loglevel "^1.6.1" obj-multiplex "^1.0.0" @@ -18890,6 +18897,11 @@ nanoid@^2.0.0: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.0.3.tgz#dde999e173bc9d7bd2ee2746b89909ade98e075e" integrity sha512-NbaoqdhIYmY6FXDRB4eYtDVC9Z9eCbn8TyaiC16LNKtpPv/aqa0tOPD8y6gNE4yUNnaZ7LLhYtXOev/6+cBtfw== +nanoid@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.1.6.tgz#0665418f692e54cf44f34d4010761f3240a03314" + integrity sha512-2NDzpiuEy3+H0AVtdt8LoFi7PnqkOnIzYmJQp7xsEU6VexLluHQwKREuiz57XaQC5006seIadPrIZJhyS2n7aw== + nanomatch@^1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.9.tgz#879f7150cb2dab7a471259066c104eee6e0fa7c2" @@ -23669,6 +23681,21 @@ rn-host-detect@^1.1.5: resolved "https://registry.yarnpkg.com/rn-host-detect/-/rn-host-detect-1.1.5.tgz#fbecb982b73932f34529e97932b9a63e58d8deb6" integrity sha512-ufk2dFT3QeP9HyZ/xTuMtW27KnFy815CYitJMqQm+pgG3ZAtHBsrU8nXizNKkqXGy3bQmhEoloVbrfbvMJMqkg== +rpc-cap@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rpc-cap/-/rpc-cap-1.0.1.tgz#c19f6651d9d003256c73831422e0bd60b4fa8b55" + integrity sha512-M75F5IfohYkwGvitWmstimP9OL+9h10m1ZRC2zCB1Nli4EPzL8n5re58xlrcOnwOO38FdSSPfcwcCzMuVT8K2g== + dependencies: + clone "^2.1.2" + eth-json-rpc-errors "^2.0.0" + fast-deep-equal "^2.0.1" + gaba "^1.6.0" + intersect-objects "^1.0.0" + is-subset "^0.1.1" + json-rpc-engine "^5.1.3" + obs-store "^4.0.3" + uuid "^3.3.2" + rsa-pem-to-jwk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/rsa-pem-to-jwk/-/rsa-pem-to-jwk-1.1.3.tgz#245e76bdb7e7234cfee7ca032d31b54c38fab98e" @@ -23804,6 +23831,11 @@ safe-json-parse@~1.0.1: resolved "https://registry.yarnpkg.com/safe-json-parse/-/safe-json-parse-1.0.1.tgz#3e76723e38dfdda13c9b1d29a1e07ffee4b30b57" integrity sha1-PnZyPjjf3aE8mx0poeB//uSzC1c= +safe-json-stringify@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz#356e44bc98f1f93ce45df14bcd7c01cda86e0afd" + integrity sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg== + safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" @@ -27220,7 +27252,7 @@ uuid@3.2.1: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" integrity sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA== -uuid@3.3.2, uuid@^3.0.1, uuid@^3.1.0, uuid@^3.2.1, uuid@^3.2.2, uuid@^3.3.2: +uuid@3.3.2, uuid@^3.0.1, uuid@^3.1.0, uuid@^3.2.1, uuid@^3.2.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== @@ -27230,7 +27262,7 @@ uuid@^2.0.1: resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" integrity sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho= -uuid@^3.3.3: +uuid@^3.3.2, uuid@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== From b4fd7aea32f069f3d4142f2bfe736a85601196ae Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 3 Dec 2019 15:16:59 -0400 Subject: [PATCH 010/689] Fix a typo made comparing previous prop (#7628) The prop `prevIsAccountMenuOpen` was referenced in `prevProps`, despite it not existing. It seems clear from the context that the intention was to check the `isAccountMenuOpen` prop from `prevProps`, and name the local variable `prevIsAccountMenuOpen`. --- ui/app/components/app/account-menu/account-menu.component.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui/app/components/app/account-menu/account-menu.component.js b/ui/app/components/app/account-menu/account-menu.component.js index 61edde489..0b241fba3 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/app/components/app/account-menu/account-menu.component.js @@ -29,7 +29,6 @@ export default class AccountMenu extends PureComponent { history: PropTypes.object, identities: PropTypes.object, isAccountMenuOpen: PropTypes.bool, - prevIsAccountMenuOpen: PropTypes.bool, keyrings: PropTypes.array, lockMetamask: PropTypes.func, selectedAddress: PropTypes.string, @@ -45,7 +44,7 @@ export default class AccountMenu extends PureComponent { } componentDidUpdate (prevProps) { - const { prevIsAccountMenuOpen } = prevProps + const { isAccountMenuOpen: prevIsAccountMenuOpen } = prevProps const { isAccountMenuOpen } = this.props if (!prevIsAccountMenuOpen && isAccountMenuOpen) { From d9bdba59482a93efed83dd5ac3c7ad4dbad83bbe Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 3 Dec 2019 16:04:28 -0400 Subject: [PATCH 011/689] Use ES6 exports for selectors (#7626) This lets us get rid of the big `selectors` object that was unpleasant to maintain. --- test/unit/ui/app/selectors.spec.js | 2 +- .../selected-account.container.js | 6 +- ui/app/components/app/token-list.js | 4 +- .../app/wallet-view/wallet-view.container.js | 8 +- .../token-balance/token-balance.container.js | 4 +- ui/app/selectors/selectors.js | 193 ++++++------------ ui/app/selectors/tests/selectors.test.js | 2 +- 7 files changed, 76 insertions(+), 143 deletions(-) diff --git a/test/unit/ui/app/selectors.spec.js b/test/unit/ui/app/selectors.spec.js index f8d58f61c..cc8e3e9f1 100644 --- a/test/unit/ui/app/selectors.spec.js +++ b/test/unit/ui/app/selectors.spec.js @@ -1,5 +1,5 @@ const assert = require('assert') -const selectors = require('../../../../ui/app/selectors/selectors') +import * as selectors from '../../../../ui/app/selectors/selectors' const mockState = require('../../../data/mock-state.json') const Eth = require('ethjs') diff --git a/ui/app/components/app/selected-account/selected-account.container.js b/ui/app/components/app/selected-account/selected-account.container.js index b5dbe74f3..cf6e21ed0 100644 --- a/ui/app/components/app/selected-account/selected-account.container.js +++ b/ui/app/components/app/selected-account/selected-account.container.js @@ -1,12 +1,12 @@ import { connect } from 'react-redux' import SelectedAccount from './selected-account.component' -const selectors = require('../../../selectors/selectors') +const { getSelectedAddress, getSelectedIdentity } = require('../../../selectors/selectors') const mapStateToProps = state => { return { - selectedAddress: selectors.getSelectedAddress(state), - selectedIdentity: selectors.getSelectedIdentity(state), + selectedAddress: getSelectedAddress(state), + selectedIdentity: getSelectedIdentity(state), network: state.metamask.network, } } diff --git a/ui/app/components/app/token-list.js b/ui/app/components/app/token-list.js index ee2f85cac..39710a012 100644 --- a/ui/app/components/app/token-list.js +++ b/ui/app/components/app/token-list.js @@ -4,14 +4,14 @@ import TokenCell from './token-cell' const inherits = require('util').inherits const TokenTracker = require('eth-token-tracker') const connect = require('react-redux').connect -const selectors = require('../../selectors/selectors') +const { getSelectedAddress } = require('../../selectors/selectors') const log = require('loglevel') function mapStateToProps (state) { return { network: state.metamask.network, tokens: state.metamask.tokens, - userAddress: selectors.getSelectedAddress(state), + userAddress: getSelectedAddress(state), assetImages: state.metamask.assetImages, } } diff --git a/ui/app/components/app/wallet-view/wallet-view.container.js b/ui/app/components/app/wallet-view/wallet-view.container.js index f0329e3c3..1e37bc2a8 100644 --- a/ui/app/components/app/wallet-view/wallet-view.container.js +++ b/ui/app/components/app/wallet-view/wallet-view.container.js @@ -3,17 +3,17 @@ import { withRouter } from 'react-router-dom' import { compose } from 'recompose' import WalletView from './wallet-view.component' import {showSendPage, hideSidebar, setSelectedToken, showAddTokenPage} from '../../../store/actions' -import * as selectors from '../../../selectors/selectors' +import { getMetaMaskAccounts, getSelectedAddress, getSelectedAccount } from '../../../selectors/selectors' function mapStateToProps (state) { return { network: state.metamask.network, sidebarOpen: state.appState.sidebar.isOpen, identities: state.metamask.identities, - accounts: selectors.getMetaMaskAccounts(state), + accounts: getMetaMaskAccounts(state), keyrings: state.metamask.keyrings, - selectedAddress: selectors.getSelectedAddress(state), - selectedAccount: selectors.getSelectedAccount(state), + selectedAddress: getSelectedAddress(state), + selectedAccount: getSelectedAccount(state), selectedTokenAddress: state.metamask.selectedTokenAddress, } } diff --git a/ui/app/components/ui/token-balance/token-balance.container.js b/ui/app/components/ui/token-balance/token-balance.container.js index a0f1efc20..6425f89d9 100644 --- a/ui/app/components/ui/token-balance/token-balance.container.js +++ b/ui/app/components/ui/token-balance/token-balance.container.js @@ -2,11 +2,11 @@ import { connect } from 'react-redux' import { compose } from 'recompose' import withTokenTracker from '../../../helpers/higher-order-components/with-token-tracker' import TokenBalance from './token-balance.component' -import selectors from '../../../selectors/selectors' +import { getSelectedAddress } from '../../../selectors/selectors' const mapStateToProps = state => { return { - userAddress: selectors.getSelectedAddress(state), + userAddress: getSelectedAddress(state), } } diff --git a/ui/app/selectors/selectors.js b/ui/app/selectors/selectors.js index fe8c108b4..bcd21d107 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/app/selectors/selectors.js @@ -2,10 +2,8 @@ import { NETWORK_TYPES } from '../helpers/constants/common' import { mapObjectValues } from '../../../app/scripts/lib/util' import { stripHexPrefix, addHexPrefix } from 'ethereumjs-util' -const abi = require('human-standard-token-abi') -const { - multiplyCurrencies, -} = require('../helpers/utils/conversion-util') +import abi from 'human-standard-token-abi' +import { multiplyCurrencies } from '../helpers/utils/conversion-util' import { addressSlicer, checksumAddress, @@ -13,78 +11,13 @@ import { getOriginFromUrl, } from '../helpers/utils/util' -const selectors = { - getSelectedAddress, - getSelectedIdentity, - getSelectedAccount, - getSelectedToken, - getSelectedTokenExchangeRate, - getSelectedTokenAssetImage, - getAssetImages, - getTokenExchangeRate, - conversionRateSelector, - accountsWithSendEtherInfoSelector, - getAccountsWithLabels, - getCurrentAccountWithSendEtherInfo, - getGasIsLoading, - getForceGasMin, - getAddressBook, - getSendFrom, - getCurrentCurrency, - getNativeCurrency, - getSendAmount, - getSelectedTokenToFiatRate, - getSelectedTokenContract, - getSendMaxModeState, - getCurrentViewContext, - getTotalUnapprovedCount, - preferencesSelector, - getMetaMaskAccounts, - getCurrentEthBalance, - getNetworkIdentifier, - isBalanceCached, - getAdvancedInlineGasShown, - getUseNonceField, - getCustomNonceValue, - getIsMainnet, - getCurrentNetworkId, - getSelectedAsset, - getCurrentKeyring, - getAccountType, - getNumberOfAccounts, - getNumberOfTokens, - getDaiV1Token, - isEthereumNetwork, - getPermissionsRequests, - getPermissionsDescriptions, - getDomainMetadata, - getActiveTab, - getMetaMetricState, - getRpcPrefsForCurrentProvider, - getKnownMethodData, - getAddressBookEntry, - getAddressBookEntryName, - getFeatureFlags, - getFirstPermissionRequest, - hasPermissionRequests, - getRenderablePermissionsDomains, - getPermissionsDomains, - getAddressConnectedDomainMap, - getDomainToConnectedAddressMap, - getOriginOfCurrentTab, - getAddressConnectedToCurrentTab, - getLastConnectedInfo, -} - -module.exports = selectors - -function getNetworkIdentifier (state) { +export function getNetworkIdentifier (state) { const { metamask: { provider: { type, nickname, rpcTarget } } } = state return nickname || rpcTarget || type } -function getCurrentKeyring (state) { +export function getCurrentKeyring (state) { const identity = getSelectedIdentity(state) if (!identity) { @@ -101,7 +34,7 @@ function getCurrentKeyring (state) { return keyring } -function getAccountType (state) { +export function getAccountType (state) { const currentKeyring = getCurrentKeyring(state) const type = currentKeyring && currentKeyring.type @@ -116,38 +49,38 @@ function getAccountType (state) { } } -function getSelectedAsset (state) { +export function getSelectedAsset (state) { const selectedToken = getSelectedToken(state) return selectedToken && selectedToken.symbol || 'ETH' } -function getCurrentNetworkId (state) { +export function getCurrentNetworkId (state) { return state.metamask.network } -function getSelectedAddress (state) { +export function getSelectedAddress (state) { const selectedAddress = state.metamask.selectedAddress || Object.keys(getMetaMaskAccounts(state))[0] return selectedAddress } -function getSelectedIdentity (state) { +export function getSelectedIdentity (state) { const selectedAddress = getSelectedAddress(state) const identities = state.metamask.identities return identities[selectedAddress] } -function getNumberOfAccounts (state) { +export function getNumberOfAccounts (state) { return Object.keys(state.metamask.accounts).length } -function getNumberOfTokens (state) { +export function getNumberOfTokens (state) { const tokens = state.metamask.tokens return tokens ? tokens.length : 0 } -function getMetaMaskAccounts (state) { +export function getMetaMaskAccounts (state) { const currentAccounts = state.metamask.accounts const cachedBalances = state.metamask.cachedBalances[state.metamask.network] const selectedAccounts = {} @@ -166,28 +99,28 @@ function getMetaMaskAccounts (state) { return selectedAccounts } -function isBalanceCached (state) { +export function isBalanceCached (state) { const selectedAccountBalance = state.metamask.accounts[getSelectedAddress(state)].balance const cachedBalance = getSelectedAccountCachedBalance(state) return Boolean(!selectedAccountBalance && cachedBalance) } -function getSelectedAccountCachedBalance (state) { +export function getSelectedAccountCachedBalance (state) { const cachedBalances = state.metamask.cachedBalances[state.metamask.network] const selectedAddress = getSelectedAddress(state) return cachedBalances && cachedBalances[selectedAddress] } -function getSelectedAccount (state) { +export function getSelectedAccount (state) { const accounts = getMetaMaskAccounts(state) const selectedAddress = getSelectedAddress(state) return accounts[selectedAddress] } -function getSelectedToken (state) { +export function getSelectedToken (state) { const tokens = state.metamask.tokens || [] const selectedTokenAddress = state.metamask.selectedTokenAddress const selectedToken = tokens.filter(({ address }) => address === selectedTokenAddress)[0] @@ -196,35 +129,35 @@ function getSelectedToken (state) { return selectedToken || sendToken || null } -function getSelectedTokenExchangeRate (state) { +export function getSelectedTokenExchangeRate (state) { const contractExchangeRates = state.metamask.contractExchangeRates const selectedToken = getSelectedToken(state) || {} const { address } = selectedToken return contractExchangeRates[address] || 0 } -function getSelectedTokenAssetImage (state) { +export function getSelectedTokenAssetImage (state) { const assetImages = state.metamask.assetImages || {} const selectedToken = getSelectedToken(state) || {} const { address } = selectedToken return assetImages[address] } -function getAssetImages (state) { +export function getAssetImages (state) { const assetImages = state.metamask.assetImages || {} return assetImages } -function getTokenExchangeRate (state, address) { +export function getTokenExchangeRate (state, address) { const contractExchangeRates = state.metamask.contractExchangeRates return contractExchangeRates[address] || 0 } -function conversionRateSelector (state) { +export function conversionRateSelector (state) { return state.metamask.conversionRate } -function getAddressBook (state) { +export function getAddressBook (state) { const network = state.metamask.network if (!state.metamask.addressBook[network]) { return [] @@ -232,24 +165,24 @@ function getAddressBook (state) { return Object.values(state.metamask.addressBook[network]) } -function getAddressBookEntry (state, address) { +export function getAddressBookEntry (state, address) { const addressBook = getAddressBook(state) const entry = addressBook.find(contact => contact.address === checksumAddress(address)) return entry } -function getAddressBookEntryName (state, address) { +export function getAddressBookEntryName (state, address) { const entry = getAddressBookEntry(state, address) || state.metamask.identities[address] return entry && entry.name !== '' ? entry.name : addressSlicer(address) } -function getDaiV1Token (state) { +export function getDaiV1Token (state) { const OLD_DAI_CONTRACT_ADDRESS = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359' const tokens = state.metamask.tokens || [] return tokens.find(({address}) => checksumAddress(address) === OLD_DAI_CONTRACT_ADDRESS) } -function accountsWithSendEtherInfoSelector (state) { +export function accountsWithSendEtherInfoSelector (state) { const accounts = getMetaMaskAccounts(state) const { identities } = state.metamask @@ -260,7 +193,7 @@ function accountsWithSendEtherInfoSelector (state) { return accountsWithSendEtherInfo } -function getAccountsWithLabels (state) { +export function getAccountsWithLabels (state) { const accountsWithoutLabel = accountsWithSendEtherInfoSelector(state) const accountsWithLabels = accountsWithoutLabel.map(account => { const { address, name, balance } = account @@ -275,46 +208,46 @@ function getAccountsWithLabels (state) { return accountsWithLabels } -function getCurrentAccountWithSendEtherInfo (state) { +export function getCurrentAccountWithSendEtherInfo (state) { const currentAddress = getSelectedAddress(state) const accounts = accountsWithSendEtherInfoSelector(state) return accounts.find(({ address }) => address === currentAddress) } -function getCurrentEthBalance (state) { +export function getCurrentEthBalance (state) { return getCurrentAccountWithSendEtherInfo(state).balance } -function getGasIsLoading (state) { +export function getGasIsLoading (state) { return state.appState.gasIsLoading } -function getForceGasMin (state) { +export function getForceGasMin (state) { return state.metamask.send.forceGasMin } -function getSendFrom (state) { +export function getSendFrom (state) { return state.metamask.send.from } -function getSendAmount (state) { +export function getSendAmount (state) { return state.metamask.send.amount } -function getSendMaxModeState (state) { +export function getSendMaxModeState (state) { return state.metamask.send.maxModeOn } -function getCurrentCurrency (state) { +export function getCurrentCurrency (state) { return state.metamask.currentCurrency } -function getNativeCurrency (state) { +export function getNativeCurrency (state) { return state.metamask.nativeCurrency } -function getSelectedTokenToFiatRate (state) { +export function getSelectedTokenToFiatRate (state) { const selectedTokenExchangeRate = getSelectedTokenExchangeRate(state) const conversionRate = conversionRateSelector(state) @@ -327,19 +260,19 @@ function getSelectedTokenToFiatRate (state) { return tokenToFiatRate } -function getSelectedTokenContract (state) { +export function getSelectedTokenContract (state) { const selectedToken = getSelectedToken(state) return selectedToken ? global.eth.contract(abi).at(selectedToken.address) : null } -function getCurrentViewContext (state) { +export function getCurrentViewContext (state) { const { currentView = {} } = state.appState return currentView.context } -function getTotalUnapprovedCount ({ metamask }) { +export function getTotalUnapprovedCount ({ metamask }) { const { unapprovedTxs = {}, unapprovedMsgCount, @@ -351,12 +284,12 @@ function getTotalUnapprovedCount ({ metamask }) { unapprovedTypedMessagesCount } -function getIsMainnet (state) { +export function getIsMainnet (state) { const networkType = getNetworkIdentifier(state) return networkType === NETWORK_TYPES.MAINNET } -function isEthereumNetwork (state) { +export function isEthereumNetwork (state) { const networkType = getNetworkIdentifier(state) const { KOVAN, @@ -369,39 +302,39 @@ function isEthereumNetwork (state) { return [ KOVAN, MAINNET, RINKEBY, ROPSTEN, GOERLI].includes(networkType) } -function preferencesSelector ({ metamask }) { +export function preferencesSelector ({ metamask }) { return metamask.preferences } -function getAdvancedInlineGasShown (state) { +export function getAdvancedInlineGasShown (state) { return Boolean(state.metamask.featureFlags.advancedInlineGas) } -function getUseNonceField (state) { +export function getUseNonceField (state) { return Boolean(state.metamask.useNonceField) } -function getCustomNonceValue (state) { +export function getCustomNonceValue (state) { return String(state.metamask.customNonceValue) } -function getPermissionsDescriptions (state) { +export function getPermissionsDescriptions (state) { return state.metamask.permissionsDescriptions } -function getPermissionsRequests (state) { +export function getPermissionsRequests (state) { return state.metamask.permissionsRequests } -function getDomainMetadata (state) { +export function getDomainMetadata (state) { return state.metamask.domainMetadata } -function getActiveTab (state) { +export function getActiveTab (state) { return state.activeTab } -function getMetaMetricState (state) { +export function getMetaMetricState (state) { return { network: getCurrentNetworkId(state), activeCurrency: getSelectedAsset(state), @@ -413,14 +346,14 @@ function getMetaMetricState (state) { } } -function getRpcPrefsForCurrentProvider (state) { +export function getRpcPrefsForCurrentProvider (state) { const { frequentRpcListDetail, provider } = state.metamask const selectRpcInfo = frequentRpcListDetail.find(rpcInfo => rpcInfo.rpcUrl === provider.rpcTarget) const { rpcPrefs = {} } = selectRpcInfo || {} return rpcPrefs } -function getKnownMethodData (state, data) { +export function getKnownMethodData (state, data) { if (!data) { return null } @@ -431,24 +364,24 @@ function getKnownMethodData (state, data) { return knownMethodData && knownMethodData[fourBytePrefix] } -function getFeatureFlags (state) { +export function getFeatureFlags (state) { return state.metamask.featureFlags } -function getFirstPermissionRequest (state) { +export function getFirstPermissionRequest (state) { const requests = getPermissionsRequests(state) return requests && requests[0] ? requests[0] : null } -function hasPermissionRequests (state) { +export function hasPermissionRequests (state) { return Boolean(getFirstPermissionRequest(state)) } -function getPermissionsDomains (state) { +export function getPermissionsDomains (state) { return state.metamask.domains } -function getAddressConnectedDomainMap (state) { +export function getAddressConnectedDomainMap (state) { const { domains, domainMetadata, @@ -478,7 +411,7 @@ function getAddressConnectedDomainMap (state) { return addressConnectedIconMap } -function getDomainToConnectedAddressMap (state) { +export function getDomainToConnectedAddressMap (state) { const { domains = {} } = state.metamask const domainToConnectedAddressMap = mapObjectValues(domains, (_, { permissions }) => { @@ -498,7 +431,7 @@ function getDomainToConnectedAddressMap (state) { return domainToConnectedAddressMap } -function getAddressConnectedToCurrentTab (state) { +export function getAddressConnectedToCurrentTab (state) { const domainToConnectedAddressMap = getDomainToConnectedAddressMap(state) const originOfCurrentTab = getOriginOfCurrentTab(state) const addressesConnectedToCurrentTab = domainToConnectedAddressMap[originOfCurrentTab] @@ -506,7 +439,7 @@ function getAddressConnectedToCurrentTab (state) { return addressConnectedToCurrentTab } -function getRenderablePermissionsDomains (state) { +export function getRenderablePermissionsDomains (state) { const { domains = {}, domainMetadata, @@ -559,12 +492,12 @@ function getRenderablePermissionsDomains (state) { return renderableDomains } -function getOriginOfCurrentTab (state) { +export function getOriginOfCurrentTab (state) { const { activeTab } = state return activeTab && activeTab.url && getOriginFromUrl(activeTab.url) } -function getLastConnectedInfo (state) { +export function getLastConnectedInfo (state) { const { permissionsHistory = {} } = state.metamask const lastConnectedInfoData = Object.keys(permissionsHistory).reduce((acc, origin) => { const ethAccountsHistory = JSON.parse(JSON.stringify(permissionsHistory[origin]['eth_accounts'])) diff --git a/ui/app/selectors/tests/selectors.test.js b/ui/app/selectors/tests/selectors.test.js index 92d7c0a84..813628968 100644 --- a/ui/app/selectors/tests/selectors.test.js +++ b/ui/app/selectors/tests/selectors.test.js @@ -1,5 +1,5 @@ import assert from 'assert' -import selectors from '../selectors.js' +import * as selectors from '../selectors' const { getAddressBook, } = selectors From 7e22244c03eceab294253826eec6022bebd81269 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 3 Dec 2019 16:53:25 -0330 Subject: [PATCH 012/689] Replace wild random number key with index (#7629) --- ui/app/components/app/account-panel.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/app/components/app/account-panel.js b/ui/app/components/app/account-panel.js index 3ffd97887..42e2ed589 100644 --- a/ui/app/components/app/account-panel.js +++ b/ui/app/components/app/account-panel.js @@ -42,8 +42,8 @@ AccountPanel.prototype.render = function () { {panelState.identiconLabel.substring(0, 7) + '...'}
- {panelState.attributes.map((attr) => ( -
+ {panelState.attributes.map((attr, index) => ( +
{attr.value}
From 5ed921cb76b639441fe131f3c1492bb4336a8d0e Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 27 Nov 2019 19:04:11 -0330 Subject: [PATCH 013/689] eslint: Enable object-curly-spacing ESLint rule --- .eslintrc | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc b/.eslintrc index 74b30dcbe..6fcfd2b53 100644 --- a/.eslintrc +++ b/.eslintrc @@ -146,6 +146,7 @@ "no-var": 2, "no-whitespace-before-property": 2, "no-with": 2, + "object-curly-spacing": [2, "always"], "one-var": [2, { "initialized": "never" }], "operator-linebreak": [2, "after", { "overrides": { "?": "ignore", ":": "ignore" } }], "padded-blocks": "off", From 274a9ecf53cd0326d41a370a37b1b6fd9d9c83d4 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 3 Dec 2019 17:20:55 -0330 Subject: [PATCH 014/689] yarn lint --fix --- app/scripts/background.js | 2 +- app/scripts/controllers/app-state.js | 6 +-- app/scripts/controllers/detect-tokens.js | 2 +- .../controllers/network/middleware/pending.js | 4 +- .../permissions/methodMiddleware.js | 2 +- app/scripts/controllers/preferences.js | 4 +- app/scripts/controllers/transactions/index.js | 4 +- .../lib/ens-ipfs/contracts/registry.js | 2 +- .../lib/ens-ipfs/contracts/resolver.js | 2 +- app/scripts/lib/ens-ipfs/resolver.js | 4 +- app/scripts/lib/ens-ipfs/setup.js | 4 +- app/scripts/lib/notification-manager.js | 2 +- app/scripts/metamask-controller.js | 16 +++---- app/scripts/migrations/028.js | 2 +- app/scripts/phishing-detect.js | 2 +- app/scripts/platforms/extension.js | 6 +-- app/scripts/ui.js | 8 ++-- development/selector.js | 2 +- gulpfile.js | 10 ++-- test/e2e/contract-test/contract.js | 4 +- test/e2e/helpers.js | 2 +- test/lib/render-helpers.js | 4 +- .../controllers/balance-controller.spec.js | 2 +- .../app/controllers/detect-tokens-test.js | 10 ++-- .../app/controllers/infura-controller-test.js | 2 +- .../controllers/metamask-controller-test.js | 12 ++--- .../network/pending-middleware-test.js | 4 +- .../preferences-controller-test.js | 42 ++++++++--------- .../transactions/pending-tx-test.js | 4 +- .../transactions/tx-controller-test.js | 22 ++++----- .../transactions/tx-state-manager-test.js | 4 +- test/unit/app/typed-message-manager.spec.js | 18 ++++---- test/unit/migrations/022-test.js | 2 +- test/unit/migrations/023-test.js | 6 +-- test/unit/migrations/026-test.js | 6 +-- test/unit/migrations/027-test.js | 6 +-- test/unit/migrations/028-test.js | 4 +- test/unit/migrations/030-test.js | 4 +- test/unit/migrations/031-test.js | 4 +- test/unit/migrations/migrator-test.js | 4 +- test/unit/ui/app/reducers/app.spec.js | 46 +++++++++---------- test/unit/ui/app/reducers/metamask.spec.js | 2 +- test/unit/ui/app/selectors.spec.js | 2 +- test/web3/schema.js | 2 +- .../add-token-button.component.js | 2 +- .../app/customize-gas-modal/gas-modal-card.js | 2 +- .../app/dropdowns/network-dropdown.js | 2 +- .../app/dropdowns/tests/dropdown.test.js | 2 +- .../advanced-gas-inputs.container.js | 2 +- ...gas-modal-page-container-container.test.js | 2 +- .../gas-price-chart/gas-price-chart.utils.js | 6 +-- .../tests/gas-price-chart.component.test.js | 2 +- .../home-notification.component.js | 2 +- .../account-details-modal.component.js | 2 +- .../cancel-transaction.component.test.js | 4 +- .../deposit-ether-modal.component.js | 4 +- .../app/modals/notification-modal.js | 4 +- .../modals/qr-scanner/qr-scanner.component.js | 10 ++-- ui/app/components/app/network.js | 2 +- .../app/permission-page-container/index.js | 6 +-- .../index.js | 2 +- .../permission-page-container-header/index.js | 2 +- ...mission-page-container-header.component.js | 2 +- .../tests/selected-account-component.test.js | 2 +- .../shift-list-item.container.js | 2 +- .../signature-request.component.js | 2 +- .../transaction-action.component.test.js | 4 +- .../transaction-activity-log.util.js | 2 +- .../transaction-breakdown.container.js | 2 +- ...transaction-list-item-details.component.js | 2 +- .../app/wallet-view/wallet-view.container.js | 2 +- ui/app/components/ui/alert/index.js | 2 +- .../ui/breadcrumbs/breadcrumbs.component.js | 2 +- .../currency-input.component.js | 2 +- .../currency-input.container.js | 2 +- .../tests/error-message.component.test.js | 4 +- .../ui/eth-balance/eth-balance.component.js | 2 +- .../loading-screen.component.js | 2 +- .../ui/lock-icon/lock-icon.component.js | 2 +- ui/app/components/ui/mascot.js | 2 +- .../page-container-header.component.test.js | 2 +- .../ui/spinner/spinner.component.js | 2 +- .../ui/token-input/token-input.container.js | 2 +- ui/app/components/ui/tooltip-v2.js | 6 +-- ui/app/ducks/app/app.js | 4 +- ui/app/ducks/gas/gas-duck.test.js | 36 +++++++-------- ui/app/ducks/gas/gas.duck.js | 2 +- ui/app/ducks/send/send-duck.test.js | 12 ++--- ui/app/helpers/utils/conversion-util.test.js | 2 +- ui/app/helpers/utils/util.js | 2 +- .../confirm-add-suggested-token.container.js | 2 +- ui/app/pages/confirm-transaction/conf-tx.js | 2 +- .../connect-hardware/connect-screen.js | 14 +++--- .../create-account/connect-hardware/index.js | 16 +++---- .../create-account.component.js | 2 +- .../import-with-seed-phrase.component.js | 4 +- .../import-with-seed-phrase.component.test.js | 10 ++-- .../new-account/new-account.component.js | 2 +- .../seed-phrase/seed-phrase.component.js | 2 +- ui/app/pages/keychains/restore-vault.js | 2 +- .../mobile-sync/mobile-sync.component.js | 10 ++-- ui/app/pages/routes/index.js | 2 +- .../add-recipient/add-recipient.component.js | 4 +- .../add-recipient/ens-input.component.js | 2 +- .../tests/add-recipient-utils.test.js | 16 +++---- .../tests/amount-max-button-container.test.js | 2 +- .../send-asset-row.component.js | 2 +- .../send-asset-row.container.js | 2 +- .../gas-fee-display.component.js | 2 +- .../test/gas-fee-display.component.test.js | 4 +- .../send-hex-data-row.component.js | 6 +-- .../send-row-error-message.component.js | 2 +- .../tests/send-row-wrapper-component.test.js | 2 +- .../send/send-footer/send-footer.component.js | 2 +- .../tests/send-footer-selectors.test.js | 4 +- ui/app/pages/send/send.container.js | 2 +- .../pages/send/tests/send-component.test.js | 4 +- .../pages/send/tests/send-container.test.js | 4 +- .../send/tests/send-selectors-test-data.js | 2 +- ui/app/pages/send/tests/send-utils.test.js | 12 ++--- .../advanced-tab/advanced-tab.container.js | 2 +- ui/app/selectors/selectors.js | 2 +- ui/app/selectors/tests/selectors-test-data.js | 2 +- ui/app/store/actions.js | 22 ++++----- ui/index.js | 2 +- ui/lib/feature-toggle-utils.js | 2 +- ui/lib/webcam-utils.js | 4 +- 127 files changed, 324 insertions(+), 324 deletions(-) diff --git a/app/scripts/background.js b/app/scripts/background.js index e5c9ea665..b58be5ebf 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -488,7 +488,7 @@ function openPopup () { } // On first install, open a new tab with MetaMask -extension.runtime.onInstalled.addListener(({reason}) => { +extension.runtime.onInstalled.addListener(({ reason }) => { if ((reason === 'install') && (!METAMASK_DEBUG)) { platform.openExtensionInBrowser() } diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index c60a1c4f5..688062def 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -7,8 +7,8 @@ class AppStateController { * @param opts */ constructor (opts = {}) { - const {initState, onInactiveTimeout, preferencesStore} = opts - const {preferences} = preferencesStore.getState() + const { initState, onInactiveTimeout, preferencesStore } = opts + const { preferences } = preferencesStore.getState() this.onInactiveTimeout = onInactiveTimeout || (() => {}) this.store = new ObservableStore(extend({ @@ -62,7 +62,7 @@ class AppStateController { * @private */ _resetTimer () { - const {timeoutMinutes} = this.store.getState() + const { timeoutMinutes } = this.store.getState() if (this.timer) { clearTimeout(this.timer) diff --git a/app/scripts/controllers/detect-tokens.js b/app/scripts/controllers/detect-tokens.js index 923aa2d15..3ad39984a 100644 --- a/app/scripts/controllers/detect-tokens.js +++ b/app/scripts/controllers/detect-tokens.js @@ -4,7 +4,7 @@ const { warn } = require('loglevel') const { MAINNET } = require('./network/enums') // By default, poll every 3 minutes const DEFAULT_INTERVAL = 180 * 1000 -const ERC20_ABI = [{'constant': true, 'inputs': [{'name': '_owner', 'type': 'address'}], 'name': 'balanceOf', 'outputs': [{'name': 'balance', 'type': 'uint256'}], 'payable': false, 'type': 'function'}] +const ERC20_ABI = [{ 'constant': true, 'inputs': [{ 'name': '_owner', 'type': 'address' }], 'name': 'balanceOf', 'outputs': [{ 'name': 'balance', 'type': 'uint256' }], 'payable': false, 'type': 'function' }] const SINGLE_CALL_BALANCES_ABI = require('single-call-balance-checker-abi') const SINGLE_CALL_BALANCES_ADDRESS = '0xb1f8e55c7f64d203c1400b9d8555d050f94adf39' /** diff --git a/app/scripts/controllers/network/middleware/pending.js b/app/scripts/controllers/network/middleware/pending.js index 96a5d40be..51c3c3e6d 100644 --- a/app/scripts/controllers/network/middleware/pending.js +++ b/app/scripts/controllers/network/middleware/pending.js @@ -3,7 +3,7 @@ const createAsyncMiddleware = require('json-rpc-engine/src/createAsyncMiddleware function createPendingNonceMiddleware ({ getPendingNonce }) { return createAsyncMiddleware(async (req, res, next) => { - const {method, params} = req + const { method, params } = req if (method !== 'eth_getTransactionCount') { return next() } @@ -17,7 +17,7 @@ function createPendingNonceMiddleware ({ getPendingNonce }) { function createPendingTxMiddleware ({ getPendingTransactionByHash }) { return createAsyncMiddleware(async (req, res, next) => { - const {method, params} = req + const { method, params } = req if (method !== 'eth_getTransactionByHash') { return next() } diff --git a/app/scripts/controllers/permissions/methodMiddleware.js b/app/scripts/controllers/permissions/methodMiddleware.js index e0b451c9f..06e50cc7f 100644 --- a/app/scripts/controllers/permissions/methodMiddleware.js +++ b/app/scripts/controllers/permissions/methodMiddleware.js @@ -11,7 +11,7 @@ module.exports = function createMethodMiddleware ({ return createAsyncMiddleware(async (req, res, next) => { if (typeof req.method !== 'string') { - res.error = ethErrors.rpc.invalidRequest({ data: req}) + res.error = ethErrors.rpc.invalidRequest({ data: req }) return } diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 409ce6876..907351e87 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -258,7 +258,7 @@ class PreferencesController { const identities = addresses.reduce((ids, address, index) => { const oldId = oldIdentities[address] || {} - ids[address] = {name: `Account ${index + 1}`, address, ...oldId} + ids[address] = { name: `Account ${index + 1}`, address, ...oldId } return ids }, {}) const accountTokens = addresses.reduce((tokens, address) => { @@ -474,7 +474,7 @@ class PreferencesController { throw new Error('setAccountLabel requires a valid address, got ' + String(account)) } const address = normalizeAddress(account) - const {identities} = this.store.getState() + const { identities } = this.store.getState() identities[address] = identities[address] || {} identities[address].name = label this.store.updateState({ identities }) diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index 85733aa38..d190b4e52 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -219,7 +219,7 @@ class TransactionController extends EventEmitter { // the specified address const permittedAddresses = await this.getPermittedAccounts(origin) if (!permittedAddresses.includes(normalizedTxParams.from)) { - throw ethErrors.provider.unauthorized({ data: { origin }}) + throw ethErrors.provider.unauthorized({ data: { origin } }) } } @@ -690,7 +690,7 @@ class TransactionController extends EventEmitter { // get the confirmed transactions nonce and from address const txMeta = this.txStateManager.getTx(txId) const { nonce, from } = txMeta.txParams - const sameNonceTxs = this.txStateManager.getFilteredTxList({nonce, from}) + const sameNonceTxs = this.txStateManager.getFilteredTxList({ nonce, from }) if (!sameNonceTxs.length) { return } diff --git a/app/scripts/lib/ens-ipfs/contracts/registry.js b/app/scripts/lib/ens-ipfs/contracts/registry.js index 99ca24458..6b60718a5 100644 --- a/app/scripts/lib/ens-ipfs/contracts/registry.js +++ b/app/scripts/lib/ens-ipfs/contracts/registry.js @@ -1 +1 @@ -module.exports = [{'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'resolver', 'outputs': [{'name': '', 'type': 'address'}], 'payable': false, 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'owner', 'outputs': [{'name': '', 'type': 'address'}], 'payable': false, 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'label', 'type': 'bytes32'}, {'name': 'owner', 'type': 'address'}], 'name': 'setSubnodeOwner', 'outputs': [], 'payable': false, 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'ttl', 'type': 'uint64'}], 'name': 'setTTL', 'outputs': [], 'payable': false, 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'ttl', 'outputs': [{'name': '', 'type': 'uint64'}], 'payable': false, 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'resolver', 'type': 'address'}], 'name': 'setResolver', 'outputs': [], 'payable': false, 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'owner', 'type': 'address'}], 'name': 'setOwner', 'outputs': [], 'payable': false, 'type': 'function'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'owner', 'type': 'address'}], 'name': 'Transfer', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': true, 'name': 'label', 'type': 'bytes32'}, {'indexed': false, 'name': 'owner', 'type': 'address'}], 'name': 'NewOwner', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'resolver', 'type': 'address'}], 'name': 'NewResolver', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'ttl', 'type': 'uint64'}], 'name': 'NewTTL', 'type': 'event'}] +module.exports = [{ 'constant': true, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }], 'name': 'resolver', 'outputs': [{ 'name': '', 'type': 'address' }], 'payable': false, 'type': 'function' }, { 'constant': true, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }], 'name': 'owner', 'outputs': [{ 'name': '', 'type': 'address' }], 'payable': false, 'type': 'function' }, { 'constant': false, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }, { 'name': 'label', 'type': 'bytes32' }, { 'name': 'owner', 'type': 'address' }], 'name': 'setSubnodeOwner', 'outputs': [], 'payable': false, 'type': 'function' }, { 'constant': false, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }, { 'name': 'ttl', 'type': 'uint64' }], 'name': 'setTTL', 'outputs': [], 'payable': false, 'type': 'function' }, { 'constant': true, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }], 'name': 'ttl', 'outputs': [{ 'name': '', 'type': 'uint64' }], 'payable': false, 'type': 'function' }, { 'constant': false, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }, { 'name': 'resolver', 'type': 'address' }], 'name': 'setResolver', 'outputs': [], 'payable': false, 'type': 'function' }, { 'constant': false, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }, { 'name': 'owner', 'type': 'address' }], 'name': 'setOwner', 'outputs': [], 'payable': false, 'type': 'function' }, { 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': 'node', 'type': 'bytes32' }, { 'indexed': false, 'name': 'owner', 'type': 'address' }], 'name': 'Transfer', 'type': 'event' }, { 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': 'node', 'type': 'bytes32' }, { 'indexed': true, 'name': 'label', 'type': 'bytes32' }, { 'indexed': false, 'name': 'owner', 'type': 'address' }], 'name': 'NewOwner', 'type': 'event' }, { 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': 'node', 'type': 'bytes32' }, { 'indexed': false, 'name': 'resolver', 'type': 'address' }], 'name': 'NewResolver', 'type': 'event' }, { 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': 'node', 'type': 'bytes32' }, { 'indexed': false, 'name': 'ttl', 'type': 'uint64' }], 'name': 'NewTTL', 'type': 'event' }] diff --git a/app/scripts/lib/ens-ipfs/contracts/resolver.js b/app/scripts/lib/ens-ipfs/contracts/resolver.js index b61fbed88..4ec3885f8 100644 --- a/app/scripts/lib/ens-ipfs/contracts/resolver.js +++ b/app/scripts/lib/ens-ipfs/contracts/resolver.js @@ -1,2 +1,2 @@ module.exports = -[{'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'hash', 'type': 'bytes32'}], 'name': 'setContent', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'content', 'outputs': [{'name': '', 'type': 'bytes32'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'interfaceID', 'type': 'bytes4'}], 'name': 'supportsInterface', 'outputs': [{'name': '', 'type': 'bool'}], 'payable': false, 'stateMutability': 'pure', 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'key', 'type': 'string'}, {'name': 'value', 'type': 'string'}], 'name': 'setText', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'contentTypes', 'type': 'uint256'}], 'name': 'ABI', 'outputs': [{'name': 'contentType', 'type': 'uint256'}, {'name': 'data', 'type': 'bytes'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'x', 'type': 'bytes32'}, {'name': 'y', 'type': 'bytes32'}], 'name': 'setPubkey', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'hash', 'type': 'bytes'}], 'name': 'setContenthash', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'addr', 'outputs': [{'name': '', 'type': 'address'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'key', 'type': 'string'}], 'name': 'text', 'outputs': [{'name': '', 'type': 'string'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'contentType', 'type': 'uint256'}, {'name': 'data', 'type': 'bytes'}], 'name': 'setABI', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'name', 'outputs': [{'name': '', 'type': 'string'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'name', 'type': 'string'}], 'name': 'setName', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'contenthash', 'outputs': [{'name': '', 'type': 'bytes'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'pubkey', 'outputs': [{'name': 'x', 'type': 'bytes32'}, {'name': 'y', 'type': 'bytes32'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'addr', 'type': 'address'}], 'name': 'setAddr', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'inputs': [{'name': 'ensAddr', 'type': 'address'}], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'constructor'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'a', 'type': 'address'}], 'name': 'AddrChanged', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'name', 'type': 'string'}], 'name': 'NameChanged', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': true, 'name': 'contentType', 'type': 'uint256'}], 'name': 'ABIChanged', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'x', 'type': 'bytes32'}, {'indexed': false, 'name': 'y', 'type': 'bytes32'}], 'name': 'PubkeyChanged', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'indexedKey', 'type': 'string'}, {'indexed': false, 'name': 'key', 'type': 'string'}], 'name': 'TextChanged', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'hash', 'type': 'bytes'}], 'name': 'ContenthashChanged', 'type': 'event'}] +[{ 'constant': false, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }, { 'name': 'hash', 'type': 'bytes32' }], 'name': 'setContent', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function' }, { 'constant': true, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }], 'name': 'content', 'outputs': [{ 'name': '', 'type': 'bytes32' }], 'payable': false, 'stateMutability': 'view', 'type': 'function' }, { 'constant': true, 'inputs': [{ 'name': 'interfaceID', 'type': 'bytes4' }], 'name': 'supportsInterface', 'outputs': [{ 'name': '', 'type': 'bool' }], 'payable': false, 'stateMutability': 'pure', 'type': 'function' }, { 'constant': false, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }, { 'name': 'key', 'type': 'string' }, { 'name': 'value', 'type': 'string' }], 'name': 'setText', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function' }, { 'constant': true, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }, { 'name': 'contentTypes', 'type': 'uint256' }], 'name': 'ABI', 'outputs': [{ 'name': 'contentType', 'type': 'uint256' }, { 'name': 'data', 'type': 'bytes' }], 'payable': false, 'stateMutability': 'view', 'type': 'function' }, { 'constant': false, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }, { 'name': 'x', 'type': 'bytes32' }, { 'name': 'y', 'type': 'bytes32' }], 'name': 'setPubkey', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function' }, { 'constant': false, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }, { 'name': 'hash', 'type': 'bytes' }], 'name': 'setContenthash', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function' }, { 'constant': true, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }], 'name': 'addr', 'outputs': [{ 'name': '', 'type': 'address' }], 'payable': false, 'stateMutability': 'view', 'type': 'function' }, { 'constant': true, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }, { 'name': 'key', 'type': 'string' }], 'name': 'text', 'outputs': [{ 'name': '', 'type': 'string' }], 'payable': false, 'stateMutability': 'view', 'type': 'function' }, { 'constant': false, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }, { 'name': 'contentType', 'type': 'uint256' }, { 'name': 'data', 'type': 'bytes' }], 'name': 'setABI', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function' }, { 'constant': true, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }], 'name': 'name', 'outputs': [{ 'name': '', 'type': 'string' }], 'payable': false, 'stateMutability': 'view', 'type': 'function' }, { 'constant': false, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }, { 'name': 'name', 'type': 'string' }], 'name': 'setName', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function' }, { 'constant': true, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }], 'name': 'contenthash', 'outputs': [{ 'name': '', 'type': 'bytes' }], 'payable': false, 'stateMutability': 'view', 'type': 'function' }, { 'constant': true, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }], 'name': 'pubkey', 'outputs': [{ 'name': 'x', 'type': 'bytes32' }, { 'name': 'y', 'type': 'bytes32' }], 'payable': false, 'stateMutability': 'view', 'type': 'function' }, { 'constant': false, 'inputs': [{ 'name': 'node', 'type': 'bytes32' }, { 'name': 'addr', 'type': 'address' }], 'name': 'setAddr', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function' }, { 'inputs': [{ 'name': 'ensAddr', 'type': 'address' }], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'constructor' }, { 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': 'node', 'type': 'bytes32' }, { 'indexed': false, 'name': 'a', 'type': 'address' }], 'name': 'AddrChanged', 'type': 'event' }, { 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': 'node', 'type': 'bytes32' }, { 'indexed': false, 'name': 'name', 'type': 'string' }], 'name': 'NameChanged', 'type': 'event' }, { 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': 'node', 'type': 'bytes32' }, { 'indexed': true, 'name': 'contentType', 'type': 'uint256' }], 'name': 'ABIChanged', 'type': 'event' }, { 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': 'node', 'type': 'bytes32' }, { 'indexed': false, 'name': 'x', 'type': 'bytes32' }, { 'indexed': false, 'name': 'y', 'type': 'bytes32' }], 'name': 'PubkeyChanged', 'type': 'event' }, { 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': 'node', 'type': 'bytes32' }, { 'indexed': false, 'name': 'indexedKey', 'type': 'string' }, { 'indexed': false, 'name': 'key', 'type': 'string' }], 'name': 'TextChanged', 'type': 'event' }, { 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': 'node', 'type': 'bytes32' }, { 'indexed': false, 'name': 'hash', 'type': 'bytes' }], 'name': 'ContenthashChanged', 'type': 'event' }] diff --git a/app/scripts/lib/ens-ipfs/resolver.js b/app/scripts/lib/ens-ipfs/resolver.js index 34b1304c1..985f0378c 100644 --- a/app/scripts/lib/ens-ipfs/resolver.js +++ b/app/scripts/lib/ens-ipfs/resolver.js @@ -34,7 +34,7 @@ async function resolveEnsToIpfsContentId ({ provider, name }) { const rawContentHash = contentLookupResult[0] const decodedContentHash = contentHash.decode(rawContentHash) const type = contentHash.getCodec(rawContentHash) - return {type: type, hash: decodedContentHash} + return { type: type, hash: decodedContentHash } } if (isLegacyResolver[0]) { // lookup content id @@ -43,7 +43,7 @@ async function resolveEnsToIpfsContentId ({ provider, name }) { if (hexValueIsEmpty(content)) { throw new Error(`EnsIpfsResolver - no content ID found for name "${name}"`) } - return {type: 'swarm-ns', hash: content.slice(2)} + return { type: 'swarm-ns', hash: content.slice(2) } } throw new Error(`EnsIpfsResolver - the resolver for name "${name}" is not standard, it should either supports contenthash() or content()`) } diff --git a/app/scripts/lib/ens-ipfs/setup.js b/app/scripts/lib/ens-ipfs/setup.js index a00c750a4..a703af5b5 100644 --- a/app/scripts/lib/ens-ipfs/setup.js +++ b/app/scripts/lib/ens-ipfs/setup.js @@ -10,7 +10,7 @@ function setupEnsIpfsResolver ({ provider }) { // install listener const urlPatterns = supportedTopLevelDomains.map(tld => `*://*.${tld}/*`) - extension.webRequest.onErrorOccurred.addListener(webRequestDidFail, { urls: urlPatterns, types: ['main_frame']}) + extension.webRequest.onErrorOccurred.addListener(webRequestDidFail, { urls: urlPatterns, types: ['main_frame'] }) // return api object return { @@ -43,7 +43,7 @@ function setupEnsIpfsResolver ({ provider }) { extension.tabs.update(tabId, { url: `loading.html` }) let url = `https://app.ens.domains/name/${name}` try { - const {type, hash} = await resolveEnsToIpfsContentId({ provider, name }) + const { type, hash } = await resolveEnsToIpfsContentId({ provider, name }) if (type === 'ipfs-ns') { const resolvedUrl = `https://gateway.ipfs.io/ipfs/${hash}${path}${search || ''}${fragment || ''}` try { diff --git a/app/scripts/lib/notification-manager.js b/app/scripts/lib/notification-manager.js index 85177cceb..d79326b52 100644 --- a/app/scripts/lib/notification-manager.js +++ b/app/scripts/lib/notification-manager.js @@ -27,7 +27,7 @@ class NotificationManager { // bring focus to existing chrome popup extension.windows.update(popup.id, { focused: true }) } else { - const {screenX, screenY, outerWidth, outerHeight} = window + const { screenX, screenY, outerWidth, outerHeight } = window const notificationTop = Math.round(screenY + (outerHeight / 2) - (NOTIFICATION_HEIGHT / 2)) const notificationLeft = Math.round(screenX + (outerWidth / 2) - (NOTIFICATION_WIDTH / 2)) const cb = (currentPopup) => { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 246ae511d..77a596a57 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -21,7 +21,7 @@ const createSubscriptionManager = require('eth-json-rpc-filters/subscriptionMana const createLoggerMiddleware = require('./lib/createLoggerMiddleware') const createOriginMiddleware = require('./lib/createOriginMiddleware') const providerAsMiddleware = require('eth-json-rpc-middleware/providerAsMiddleware') -const {setupMultiplex} = require('./lib/stream-utils.js') +const { setupMultiplex } = require('./lib/stream-utils.js') const KeyringController = require('eth-keyring-controller') const EnsController = require('./controllers/ens') const NetworkController = require('./controllers/network') @@ -45,9 +45,9 @@ const nodeify = require('./lib/nodeify') const accountImporter = require('./account-import-strategies') const getBuyEthUrl = require('./lib/buy-eth-url') const selectChainId = require('./lib/select-chain-id') -const {Mutex} = require('await-semaphore') -const {version} = require('../manifest.json') -const {BN} = require('ethereumjs-util') +const { Mutex } = require('await-semaphore') +const { version } = require('../manifest.json') +const { BN } = require('ethereumjs-util') const GWEI_BN = new BN('1000000000') const percentile = require('percentile') const seedPhraseVerifier = require('./lib/seed-phrase-verifier') @@ -929,8 +929,8 @@ module.exports = class MetamaskController extends EventEmitter { } }) - const {identities} = this.preferencesController.store.getState() - return {...keyState, identities} + const { identities } = this.preferencesController.store.getState() + return { ...keyState, identities } } /** @@ -1652,8 +1652,8 @@ module.exports = class MetamaskController extends EventEmitter { * @private */ async _onKeyringControllerUpdate (state) { - const {isUnlocked, keyrings} = state - const addresses = keyrings.reduce((acc, {accounts}) => acc.concat(accounts), []) + const { isUnlocked, keyrings } = state + const addresses = keyrings.reduce((acc, { accounts }) => acc.concat(accounts), []) if (!addresses.length) { return diff --git a/app/scripts/migrations/028.js b/app/scripts/migrations/028.js index 9e995ee1a..414128ccd 100644 --- a/app/scripts/migrations/028.js +++ b/app/scripts/migrations/028.js @@ -30,7 +30,7 @@ function transformState (state) { const tokens = newState.PreferencesController.tokens newState.PreferencesController.accountTokens = {} for (const identity in identities) { - newState.PreferencesController.accountTokens[identity] = {'mainnet': tokens} + newState.PreferencesController.accountTokens[identity] = { 'mainnet': tokens } } newState.PreferencesController.tokens = [] } diff --git a/app/scripts/phishing-detect.js b/app/scripts/phishing-detect.js index 266e4fc31..e99a5d273 100644 --- a/app/scripts/phishing-detect.js +++ b/app/scripts/phishing-detect.js @@ -3,7 +3,7 @@ const dnode = require('dnode') const { EventEmitter } = require('events') const PortStream = require('extension-port-stream') const extension = require('extensionizer') -const {setupMultiplex} = require('./lib/stream-utils.js') +const { setupMultiplex } = require('./lib/stream-utils.js') const { getEnvironmentType } = require('./lib/util') const ExtensionPlatform = require('./platforms/extension') diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 5ae05d230..62394dba5 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -1,8 +1,8 @@ const extension = require('extensionizer') -const {createExplorerLink: explorerLink} = require('etherscan-link') +const { createExplorerLink: explorerLink } = require('etherscan-link') const { getEnvironmentType, checkForError } = require('../lib/util') -const {ENVIRONMENT_TYPE_BACKGROUND} = require('../lib/enums') +const { ENVIRONMENT_TYPE_BACKGROUND } = require('../lib/enums') class ExtensionPlatform { @@ -94,7 +94,7 @@ class ExtensionPlatform { switchToTab (tabId) { return new Promise((resolve, reject) => { - extension.tabs.update(tabId, {highlighted: true}, (tab) => { + extension.tabs.update(tabId, { highlighted: true }, (tab) => { const err = checkForError() if (err) { reject(err) diff --git a/app/scripts/ui.js b/app/scripts/ui.js index f9a8dc16a..6b0bf6caf 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -13,14 +13,14 @@ const ExtensionPlatform = require('./platforms/extension') const NotificationManager = require('./lib/notification-manager') const notificationManager = new NotificationManager() const setupSentry = require('./lib/setupSentry') -const {EventEmitter} = require('events') +const { EventEmitter } = require('events') const Dnode = require('dnode') const Eth = require('ethjs') const EthQuery = require('eth-query') const urlUtil = require('url') const launchMetaMaskUi = require('../../ui') const StreamProvider = require('web3-stream-provider') -const {setupMultiplex} = require('./lib/stream-utils.js') +const { setupMultiplex } = require('./lib/stream-utils.js') const log = require('loglevel') start().catch(log.error) @@ -96,9 +96,9 @@ async function queryCurrentActiveTab (windowType) { return } - extension.tabs.query({active: true, currentWindow: true}, (tabs) => { + extension.tabs.query({ active: true, currentWindow: true }, (tabs) => { const [activeTab] = tabs - const {title, url} = activeTab + const { title, url } = activeTab const { hostname: origin, protocol } = url ? urlUtil.parse(url) : {} resolve({ title, origin, protocol, url, diff --git a/development/selector.js b/development/selector.js index 01011c710..0f47746e2 100644 --- a/development/selector.js +++ b/development/selector.js @@ -1,5 +1,5 @@ import PropTypes from 'prop-types' -import React, {Component} from 'react' +import React, { Component } from 'react' export default class Selector extends Component { state = {} diff --git a/gulpfile.js b/gulpfile.js index d5d74333a..d568ae7ff 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -191,7 +191,7 @@ gulp.task('manifest:production', function () { './dist/chrome/manifest.json', './dist/brave/manifest.json', './dist/opera/manifest.json', - ], {base: './dist/'}) + ], { base: './dist/' }) // Exclude chromereload script in production: .pipe(jsoneditor(function (json) { @@ -208,7 +208,7 @@ gulp.task('manifest:testing', function () { return gulp.src([ './dist/firefox/manifest.json', './dist/chrome/manifest.json', - ], {base: './dist/'}) + ], { base: './dist/' }) // Exclude chromereload script in production: .pipe(jsoneditor(function (json) { @@ -227,7 +227,7 @@ gulp.task('manifest:testing-local', function () { return gulp.src([ './dist/firefox/manifest.json', './dist/chrome/manifest.json', - ], {base: './dist/'}) + ], { base: './dist/' }) .pipe(jsoneditor(function (json) { json.background = { @@ -246,7 +246,7 @@ gulp.task('manifest:dev', function () { return gulp.src([ './dist/firefox/manifest.json', './dist/chrome/manifest.json', - ], {base: './dist/'}) + ], { base: './dist/' }) .pipe(jsoneditor(function (json) { json.background = { @@ -261,7 +261,7 @@ gulp.task('manifest:dev', function () { }) gulp.task('optimize:images', function () { - return gulp.src('./dist/**/images/**', {base: './dist/'}) + return gulp.src('./dist/**/images/**', { base: './dist/' }) .pipe(imagemin()) .pipe(gulp.dest('./dist/', { overwrite: true })) }) diff --git a/test/e2e/contract-test/contract.js b/test/e2e/contract-test/contract.js index 6c3941b9d..38ee72416 100644 --- a/test/e2e/contract-test/contract.js +++ b/test/e2e/contract-test/contract.js @@ -123,7 +123,7 @@ const initialize = () => { } const initializeAccountButtons = () => { - piggybankContract = web3.eth.contract([{'constant': false, 'inputs': [{'name': 'withdrawAmount', 'type': 'uint256'}], 'name': 'withdraw', 'outputs': [{'name': 'remainingBal', 'type': 'uint256'}], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [], 'name': 'owner', 'outputs': [{'name': '', 'type': 'address'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [], 'name': 'deposit', 'outputs': [{'name': '', 'type': 'uint256'}], 'payable': true, 'stateMutability': 'payable', 'type': 'function'}, {'inputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'constructor'}]) + piggybankContract = web3.eth.contract([{ 'constant': false, 'inputs': [{ 'name': 'withdrawAmount', 'type': 'uint256' }], 'name': 'withdraw', 'outputs': [{ 'name': 'remainingBal', 'type': 'uint256' }], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function' }, { 'constant': true, 'inputs': [], 'name': 'owner', 'outputs': [{ 'name': '', 'type': 'address' }], 'payable': false, 'stateMutability': 'view', 'type': 'function' }, { 'constant': false, 'inputs': [], 'name': 'deposit', 'outputs': [{ 'name': '', 'type': 'uint256' }], 'payable': true, 'stateMutability': 'payable', 'type': 'function' }, { 'inputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'constructor' }]) deployButton.onclick = async () => { contractStatus.innerHTML = 'Deploying' @@ -190,7 +190,7 @@ const initialize = () => { const _tokenName = 'TST' const _decimalUnits = 0 const _tokenSymbol = 'TST' - const humanstandardtokenContract = web3.eth.contract([{'constant': true, 'inputs': [], 'name': 'name', 'outputs': [{'name': '', 'type': 'string'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_spender', 'type': 'address'}, {'name': '_value', 'type': 'uint256'}], 'name': 'approve', 'outputs': [{'name': 'success', 'type': 'bool'}], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [], 'name': 'totalSupply', 'outputs': [{'name': '', 'type': 'uint256'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_from', 'type': 'address'}, {'name': '_to', 'type': 'address'}, {'name': '_value', 'type': 'uint256'}], 'name': 'transferFrom', 'outputs': [{'name': 'success', 'type': 'bool'}], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [], 'name': 'decimals', 'outputs': [{'name': '', 'type': 'uint8'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': true, 'inputs': [], 'name': 'version', 'outputs': [{'name': '', 'type': 'string'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': true, 'inputs': [{'name': '_owner', 'type': 'address'}], 'name': 'balanceOf', 'outputs': [{'name': 'balance', 'type': 'uint256'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': true, 'inputs': [], 'name': 'symbol', 'outputs': [{'name': '', 'type': 'string'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_to', 'type': 'address'}, {'name': '_value', 'type': 'uint256'}], 'name': 'transfer', 'outputs': [{'name': 'success', 'type': 'bool'}], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_spender', 'type': 'address'}, {'name': '_value', 'type': 'uint256'}, {'name': '_extraData', 'type': 'bytes'}], 'name': 'approveAndCall', 'outputs': [{'name': 'success', 'type': 'bool'}], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': '_owner', 'type': 'address'}, {'name': '_spender', 'type': 'address'}], 'name': 'allowance', 'outputs': [{'name': 'remaining', 'type': 'uint256'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'inputs': [{'name': '_initialAmount', 'type': 'uint256'}, {'name': '_tokenName', 'type': 'string'}, {'name': '_decimalUnits', 'type': 'uint8'}, {'name': '_tokenSymbol', 'type': 'string'}], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'constructor'}, {'payable': false, 'stateMutability': 'nonpayable', 'type': 'fallback'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': '_from', 'type': 'address'}, {'indexed': true, 'name': '_to', 'type': 'address'}, {'indexed': false, 'name': '_value', 'type': 'uint256'}], 'name': 'Transfer', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': '_owner', 'type': 'address'}, {'indexed': true, 'name': '_spender', 'type': 'address'}, {'indexed': false, 'name': '_value', 'type': 'uint256'}], 'name': 'Approval', 'type': 'event'}]) + const humanstandardtokenContract = web3.eth.contract([{ 'constant': true, 'inputs': [], 'name': 'name', 'outputs': [{ 'name': '', 'type': 'string' }], 'payable': false, 'stateMutability': 'view', 'type': 'function' }, { 'constant': false, 'inputs': [{ 'name': '_spender', 'type': 'address' }, { 'name': '_value', 'type': 'uint256' }], 'name': 'approve', 'outputs': [{ 'name': 'success', 'type': 'bool' }], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function' }, { 'constant': true, 'inputs': [], 'name': 'totalSupply', 'outputs': [{ 'name': '', 'type': 'uint256' }], 'payable': false, 'stateMutability': 'view', 'type': 'function' }, { 'constant': false, 'inputs': [{ 'name': '_from', 'type': 'address' }, { 'name': '_to', 'type': 'address' }, { 'name': '_value', 'type': 'uint256' }], 'name': 'transferFrom', 'outputs': [{ 'name': 'success', 'type': 'bool' }], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function' }, { 'constant': true, 'inputs': [], 'name': 'decimals', 'outputs': [{ 'name': '', 'type': 'uint8' }], 'payable': false, 'stateMutability': 'view', 'type': 'function' }, { 'constant': true, 'inputs': [], 'name': 'version', 'outputs': [{ 'name': '', 'type': 'string' }], 'payable': false, 'stateMutability': 'view', 'type': 'function' }, { 'constant': true, 'inputs': [{ 'name': '_owner', 'type': 'address' }], 'name': 'balanceOf', 'outputs': [{ 'name': 'balance', 'type': 'uint256' }], 'payable': false, 'stateMutability': 'view', 'type': 'function' }, { 'constant': true, 'inputs': [], 'name': 'symbol', 'outputs': [{ 'name': '', 'type': 'string' }], 'payable': false, 'stateMutability': 'view', 'type': 'function' }, { 'constant': false, 'inputs': [{ 'name': '_to', 'type': 'address' }, { 'name': '_value', 'type': 'uint256' }], 'name': 'transfer', 'outputs': [{ 'name': 'success', 'type': 'bool' }], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function' }, { 'constant': false, 'inputs': [{ 'name': '_spender', 'type': 'address' }, { 'name': '_value', 'type': 'uint256' }, { 'name': '_extraData', 'type': 'bytes' }], 'name': 'approveAndCall', 'outputs': [{ 'name': 'success', 'type': 'bool' }], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function' }, { 'constant': true, 'inputs': [{ 'name': '_owner', 'type': 'address' }, { 'name': '_spender', 'type': 'address' }], 'name': 'allowance', 'outputs': [{ 'name': 'remaining', 'type': 'uint256' }], 'payable': false, 'stateMutability': 'view', 'type': 'function' }, { 'inputs': [{ 'name': '_initialAmount', 'type': 'uint256' }, { 'name': '_tokenName', 'type': 'string' }, { 'name': '_decimalUnits', 'type': 'uint8' }, { 'name': '_tokenSymbol', 'type': 'string' }], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'constructor' }, { 'payable': false, 'stateMutability': 'nonpayable', 'type': 'fallback' }, { 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': '_from', 'type': 'address' }, { 'indexed': true, 'name': '_to', 'type': 'address' }, { 'indexed': false, 'name': '_value', 'type': 'uint256' }], 'name': 'Transfer', 'type': 'event' }, { 'anonymous': false, 'inputs': [{ 'indexed': true, 'name': '_owner', 'type': 'address' }, { 'indexed': true, 'name': '_spender', 'type': 'address' }, { 'indexed': false, 'name': '_value', 'type': 'uint256' }], 'name': 'Approval', 'type': 'event' }]) return humanstandardtokenContract.new( _initialAmount, diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 27de882eb..1f0498525 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -97,7 +97,7 @@ async function setupFetchMocking (driver) { return window.origFetch(...args) } if (window.chrome && window.chrome.webRequest) { - window.chrome.webRequest.onBeforeRequest.addListener(cancelInfuraRequest, {urls: ['https://*.infura.io/*']}, ['blocking']) + window.chrome.webRequest.onBeforeRequest.addListener(cancelInfuraRequest, { urls: ['https://*.infura.io/*'] }, ['blocking']) } function cancelInfuraRequest (requestDetails) { console.log(`fetchMocking - Canceling request: "${requestDetails.url}"`) diff --git a/test/lib/render-helpers.js b/test/lib/render-helpers.js index 81f0e27aa..64ae61cae 100644 --- a/test/lib/render-helpers.js +++ b/test/lib/render-helpers.js @@ -12,14 +12,14 @@ function shallowWithStore (component, store) { const context = { store, } - return shallow(component, {context}) + return shallow(component, { context }) } function mountWithStore (component, store) { const context = { store, } - return mount(component, {context}) + return mount(component, { context }) } function mountWithRouter (node) { diff --git a/test/unit/app/controllers/balance-controller.spec.js b/test/unit/app/controllers/balance-controller.spec.js index 9ef25b95f..dbf12246c 100644 --- a/test/unit/app/controllers/balance-controller.spec.js +++ b/test/unit/app/controllers/balance-controller.spec.js @@ -6,7 +6,7 @@ const BalanceController = require('../../../../app/scripts/controllers/balance') const AccountTracker = require('../../../../app/scripts/lib/account-tracker') const TransactionController = require('../../../../app/scripts/controllers/transactions') const { createTestProviderTools } = require('../../../stub/provider') -const provider = createTestProviderTools({ scaffold: {}}).provider +const provider = createTestProviderTools({ scaffold: {} }).provider const TEST_ADDRESS = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc' diff --git a/test/unit/app/controllers/detect-tokens-test.js b/test/unit/app/controllers/detect-tokens-test.js index c65ee97ab..5a832050a 100644 --- a/test/unit/app/controllers/detect-tokens-test.js +++ b/test/unit/app/controllers/detect-tokens-test.js @@ -23,7 +23,7 @@ describe('DetectTokensController', () => { .get(/.*/) .reply(200) - keyringMemStore = new ObservableStore({ isUnlocked: false}) + keyringMemStore = new ObservableStore({ isUnlocked: false }) network = new NetworkController() preferences = new PreferencesController({ network }) controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore }) @@ -90,8 +90,8 @@ describe('DetectTokensController', () => { .returns(preferences.addToken('0xbc86727e770de68b1060c91f6bb6945c73e10388', 'XNK', 18)) await controller.detectNewTokens() - assert.deepEqual(preferences.store.getState().tokens, [{address: '0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', decimals: 8, symbol: 'J8T'}, - {address: '0xbc86727e770de68b1060c91f6bb6945c73e10388', decimals: 18, symbol: 'XNK'}]) + assert.deepEqual(preferences.store.getState().tokens, [{ address: '0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', decimals: 8, symbol: 'J8T' }, + { address: '0xbc86727e770de68b1060c91f6bb6945c73e10388', decimals: 18, symbol: 'XNK' }]) }) it('should not detect same token while in main network', async () => { @@ -107,8 +107,8 @@ describe('DetectTokensController', () => { .returns(preferences.addToken('0xbc86727e770de68b1060c91f6bb6945c73e10388', 'XNK', 18)) await controller.detectNewTokens() - assert.deepEqual(preferences.store.getState().tokens, [{address: '0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', decimals: 8, symbol: 'J8T'}, - {address: '0xbc86727e770de68b1060c91f6bb6945c73e10388', decimals: 18, symbol: 'XNK'}]) + assert.deepEqual(preferences.store.getState().tokens, [{ address: '0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', decimals: 8, symbol: 'J8T' }, + { address: '0xbc86727e770de68b1060c91f6bb6945c73e10388', decimals: 18, symbol: 'XNK' }]) }) it('should trigger detect new tokens when change address', async () => { diff --git a/test/unit/app/controllers/infura-controller-test.js b/test/unit/app/controllers/infura-controller-test.js index 316f80378..6047c5f27 100644 --- a/test/unit/app/controllers/infura-controller-test.js +++ b/test/unit/app/controllers/infura-controller-test.js @@ -4,7 +4,7 @@ const InfuraController = require('../../../../app/scripts/controllers/infura') describe('infura-controller', function () { let infuraController, sandbox, networkStatus - const response = {'mainnet': 'degraded', 'ropsten': 'ok', 'kovan': 'ok', 'rinkeby': 'down', 'goerli': 'ok'} + const response = { 'mainnet': 'degraded', 'ropsten': 'ok', 'kovan': 'ok', 'rinkeby': 'down', 'goerli': 'ok' } before(async function () { infuraController = new InfuraController() diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index a904dec08..7091e015d 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -193,8 +193,8 @@ describe('MetaMaskController', function () { recentBlocks: [ { gasPrices: [ '0x3b9aca00', '0x174876e800'] }, { gasPrices: [ '0x3b9aca00', '0x174876e800'] }, - { gasPrices: [ '0x174876e800', '0x174876e800' ]}, - { gasPrices: [ '0x174876e800', '0x174876e800' ]}, + { gasPrices: [ '0x174876e800', '0x174876e800' ] }, + { gasPrices: [ '0x174876e800', '0x174876e800' ] }, ], } }, @@ -610,10 +610,10 @@ describe('MetaMaskController', function () { getNetworkstub.returns(42) metamaskController.txController.txStateManager._saveTxList([ - createTxMeta({ id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'} }), - createTxMeta({ id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'} }), + createTxMeta({ id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: { from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc' } }), + createTxMeta({ id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: { from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc' } }), createTxMeta({ id: 2, status: 'rejected', metamaskNetworkId: 32 }), - createTxMeta({ id: 3, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {from: '0xB09d8505E1F4EF1CeA089D47094f5DD3464083d4'} }), + createTxMeta({ id: 3, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: { from: '0xB09d8505E1F4EF1CeA089D47094f5DD3464083d4' } }), ]) }) @@ -876,7 +876,7 @@ describe('MetaMaskController', function () { }) const oldState = metamaskController.getState() - await metamaskController._onKeyringControllerUpdate({keyrings: []}) + await metamaskController._onKeyringControllerUpdate({ keyrings: [] }) assert.ok(addAddresses.notCalled) assert.ok(syncWithAddresses.notCalled) diff --git a/test/unit/app/controllers/network/pending-middleware-test.js b/test/unit/app/controllers/network/pending-middleware-test.js index ac6f8ad9a..5eba4ae01 100644 --- a/test/unit/app/controllers/network/pending-middleware-test.js +++ b/test/unit/app/controllers/network/pending-middleware-test.js @@ -7,7 +7,7 @@ describe('#createPendingNonceMiddleware', function () { const pendingNonceMiddleware = createPendingNonceMiddleware({ getPendingNonce }) it('should call next if not a eth_getTransactionCount request', (done) => { - const req = {method: 'eth_getBlockByNumber'} + const req = { method: 'eth_getBlockByNumber' } const res = {} pendingNonceMiddleware(req, res, () => done()) }) @@ -50,7 +50,7 @@ describe('#createPendingTxMiddleware', function () { 's': '0x0259b52ee8c58baaa385fb05c3f96116e58de89bcc165cb3bfdfc708672fed8a', } it('should call next if not a eth_getTransactionByHash request', (done) => { - const req = {method: 'eth_getBlockByNumber'} + const req = { method: 'eth_getBlockByNumber' } const res = {} pendingTxMiddleware(req, res, () => done()) }) diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js index 7aea39a36..1f6c08598 100644 --- a/test/unit/app/controllers/preferences-controller-test.js +++ b/test/unit/app/controllers/preferences-controller-test.js @@ -9,7 +9,7 @@ describe('preferences controller', function () { let network beforeEach(() => { - network = {providerStore: new ObservableStore({ type: 'mainnet' })} + network = { providerStore: new ObservableStore({ type: 'mainnet' }) } preferencesController = new PreferencesController({ network }) }) @@ -20,7 +20,7 @@ describe('preferences controller', function () { '0x7e57e2', ]) - const {identities} = preferencesController.store.getState() + const { identities } = preferencesController.store.getState() assert.deepEqual(identities, { '0xda22le': { name: 'Account 1', @@ -57,7 +57,7 @@ describe('preferences controller', function () { '0x7e57e277', ]) - const {identities} = preferencesController.store.getState() + const { identities } = preferencesController.store.getState() assert.deepEqual(identities, { '0xda22le77': { name: 'Account 1', @@ -246,7 +246,7 @@ describe('preferences controller', function () { assert.equal(tokens.length, 1, 'one token removed') const [token1] = tokens - assert.deepEqual(token1, {address: '0xb', symbol: 'B', decimals: 5}) + assert.deepEqual(token1, { address: '0xb', symbol: 'B', decimals: 5 }) }) it('should remove a token from its state on corresponding address', async function () { @@ -264,7 +264,7 @@ describe('preferences controller', function () { assert.equal(tokensFirst.length, 1, 'one token removed in account') const [token1] = tokensFirst - assert.deepEqual(token1, {address: '0xb', symbol: 'B', decimals: 5}) + assert.deepEqual(token1, { address: '0xb', symbol: 'B', decimals: 5 }) await preferencesController.setSelectedAddress('0x7e57e3') const tokensSecond = preferencesController.getTokens() @@ -286,7 +286,7 @@ describe('preferences controller', function () { assert.equal(tokensFirst.length, 1, 'one token removed in network') const [token1] = tokensFirst - assert.deepEqual(token1, {address: '0xb', symbol: 'B', decimals: 5}) + assert.deepEqual(token1, { address: '0xb', symbol: 'B', decimals: 5 }) network.providerStore.updateState({ type: 'rinkeby' }) const tokensSecond = preferencesController.getTokens() @@ -347,9 +347,9 @@ describe('preferences controller', function () { const sandbox = sinon.createSandbox() beforeEach(() => { - req = {params: {}} + req = { params: {} } res = {} - asy = {next: () => {}, end: () => {}} + asy = { next: () => {}, end: () => {} } stubNext = sandbox.stub(asy, 'next') stubEnd = sandbox.stub(asy, 'end').returns(0) stubHandleWatchAssetERC20 = sandbox.stub(preferencesController, '_handleWatchAssetERC20') @@ -359,7 +359,7 @@ describe('preferences controller', function () { }) it('shouldn not do anything if method not corresponds', async function () { - const asy = {next: () => {}, end: () => {}} + const asy = { next: () => {}, end: () => {} } const stubNext = sandbox.stub(asy, 'next') const stubEnd = sandbox.stub(asy, 'end').returns(0) req.method = 'metamask' @@ -368,7 +368,7 @@ describe('preferences controller', function () { sandbox.assert.called(stubNext) }) it('should do something if method is supported', async function () { - const asy = {next: () => {}, end: () => {}} + const asy = { next: () => {}, end: () => {} } const stubNext = sandbox.stub(asy, 'next') const stubEnd = sandbox.stub(asy, 'end').returns(0) req.method = 'metamask_watchAsset' @@ -392,7 +392,7 @@ describe('preferences controller', function () { assert.deepEqual(res, {}) }) it('should trigger handle add asset if type supported', async function () { - const asy = {next: () => {}, end: () => {}} + const asy = { next: () => {}, end: () => {} } req.method = 'metamask_watchAsset' req.params.type = 'ERC20' await preferencesController.requestWatchAsset(req, res, asy.next, asy.end) @@ -405,7 +405,7 @@ describe('preferences controller', function () { const sandbox = sinon.createSandbox() beforeEach(() => { - req = {params: {type: 'ERC20'}} + req = { params: { type: 'ERC20' } } }) after(() => { sandbox.restore() @@ -457,42 +457,42 @@ describe('preferences controller', function () { it('should validate ERC20 asset correctly', async function () { const validateSpy = sandbox.spy(preferencesController._validateERC20AssetParams) try { - validateSpy({rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC', decimals: 0}) + validateSpy({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC', decimals: 0 }) } catch (e) {} assert.equal(validateSpy.threw(), false, 'correct options object') const validateSpyAddress = sandbox.spy(preferencesController._validateERC20AssetParams) try { - validateSpyAddress({symbol: 'ABC', decimals: 0}) + validateSpyAddress({ symbol: 'ABC', decimals: 0 }) } catch (e) {} assert.equal(validateSpyAddress.threw(), true, 'options object with no address') const validateSpySymbol = sandbox.spy(preferencesController._validateERC20AssetParams) try { - validateSpySymbol({rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', decimals: 0}) + validateSpySymbol({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', decimals: 0 }) } catch (e) {} assert.equal(validateSpySymbol.threw(), true, 'options object with no symbol') const validateSpyDecimals = sandbox.spy(preferencesController._validateERC20AssetParams) try { - validateSpyDecimals({rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC'}) + validateSpyDecimals({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC' }) } catch (e) {} assert.equal(validateSpyDecimals.threw(), true, 'options object with no decimals') const validateSpyInvalidSymbol = sandbox.spy(preferencesController._validateERC20AssetParams) try { - validateSpyInvalidSymbol({rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABCDEFGHI', decimals: 0}) + validateSpyInvalidSymbol({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABCDEFGHI', decimals: 0 }) } catch (e) {} assert.equal(validateSpyInvalidSymbol.threw(), true, 'options object with invalid symbol') const validateSpyInvalidDecimals1 = sandbox.spy(preferencesController._validateERC20AssetParams) try { - validateSpyInvalidDecimals1({rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABCDEFGHI', decimals: -1}) + validateSpyInvalidDecimals1({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABCDEFGHI', decimals: -1 }) } catch (e) {} assert.equal(validateSpyInvalidDecimals1.threw(), true, 'options object with decimals less than zero') const validateSpyInvalidDecimals2 = sandbox.spy(preferencesController._validateERC20AssetParams) try { - validateSpyInvalidDecimals2({rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABCDEFGHI', decimals: 38}) + validateSpyInvalidDecimals2({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABCDEFGHI', decimals: 38 }) } catch (e) {} assert.equal(validateSpyInvalidDecimals2.threw(), true, 'options object with decimals more than 36') const validateSpyInvalidAddress = sandbox.spy(preferencesController._validateERC20AssetParams) try { - validateSpyInvalidAddress({rawAddress: '0x123', symbol: 'ABC', decimals: 0}) + validateSpyInvalidAddress({ rawAddress: '0x123', symbol: 'ABC', decimals: 0 }) } catch (e) {} assert.equal(validateSpyInvalidAddress.threw(), true, 'options object with address invalid') }) @@ -515,7 +515,7 @@ describe('preferences controller', function () { describe('#updateRpc', function () { it('should update the rpcDetails properly', () => { - preferencesController.store.updateState({frequentRpcListDetail: [{}, { rpcUrl: 'test' }, {}]}) + preferencesController.store.updateState({ frequentRpcListDetail: [{}, { rpcUrl: 'test' }, {}] }) preferencesController.updateRpc({ rpcUrl: 'test', chainId: 1 }) preferencesController.updateRpc({ rpcUrl: 'test/1', chainId: 1 }) preferencesController.updateRpc({ rpcUrl: 'test/2', chainId: 1 }) diff --git a/test/unit/app/controllers/transactions/pending-tx-test.js b/test/unit/app/controllers/transactions/pending-tx-test.js index 622a53b18..59b80bda5 100644 --- a/test/unit/app/controllers/transactions/pending-tx-test.js +++ b/test/unit/app/controllers/transactions/pending-tx-test.js @@ -27,7 +27,7 @@ describe('PendingTransactionTracker', function () { id: 2, history: [{}], status: 'submitted', - txParams: { from: '0x1678a085c290ebd122dc42cba69373b5953b831d'}, + txParams: { from: '0x1678a085c290ebd122dc42cba69373b5953b831d' }, } providerResultStub = {} @@ -51,7 +51,7 @@ describe('PendingTransactionTracker', function () { }) pendingTxTracker._getBlock = (blockNumber) => { - return {number: blockNumber, transactions: []} + return { number: blockNumber, transactions: [] } } }) diff --git a/test/unit/app/controllers/transactions/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js index d398c7e04..819965424 100644 --- a/test/unit/app/controllers/transactions/tx-controller-test.js +++ b/test/unit/app/controllers/transactions/tx-controller-test.js @@ -96,15 +96,15 @@ describe('Transaction Controller', function () { 'to': '0xc684832530fcbddae4b4230a47e991ddcec2831d', } txController.txStateManager._saveTxList([ - {id: 0, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, - {id: 1, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, - {id: 2, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, - {id: 3, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, - {id: 4, status: 'rejected', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, - {id: 5, status: 'approved', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, - {id: 6, status: 'signed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, - {id: 7, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, - {id: 8, status: 'failed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, + { id: 0, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, + { id: 1, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, + { id: 2, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, + { id: 3, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, + { id: 4, status: 'rejected', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, + { id: 5, status: 'approved', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, + { id: 6, status: 'signed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, + { id: 7, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, + { id: 8, status: 'failed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, ]) }) @@ -226,7 +226,7 @@ describe('Transaction Controller', function () { }) it('should fail if the from address isn\'t the selected address', function (done) { - txController.addUnapprovedTransaction({from: '0x0d1d4e623D10F9FBA5Db95830F7d3839406C6AF2'}) + txController.addUnapprovedTransaction({ from: '0x0d1d4e623D10F9FBA5Db95830F7d3839406C6AF2' }) .then(function () { assert.fail('transaction should not have been added') done() @@ -448,7 +448,7 @@ describe('Transaction Controller', function () { { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, ]) - expectedTxParams = Object.assign({}, txParams, { gasPrice: '0xb'}) + expectedTxParams = Object.assign({}, txParams, { gasPrice: '0xb' }) }) afterEach(() => { diff --git a/test/unit/app/controllers/transactions/tx-state-manager-test.js b/test/unit/app/controllers/transactions/tx-state-manager-test.js index 02d6199e9..1d975fcad 100644 --- a/test/unit/app/controllers/transactions/tx-state-manager-test.js +++ b/test/unit/app/controllers/transactions/tx-state-manager-test.js @@ -354,13 +354,13 @@ describe('TransactionStateManager', function () { describe('#_removeTx', function () { it('should remove the transaction from the storage', () => { - txStateManager._saveTxList([ {id: 1} ]) + txStateManager._saveTxList([ { id: 1 } ]) txStateManager._removeTx(1) assert(!txStateManager.getFullTxList().length, 'txList should be empty') }) it('should only remove the transaction with ID 1 from the storage', () => { - txStateManager._saveTxList([ {id: 1}, {id: 2} ]) + txStateManager._saveTxList([ { id: 1 }, { id: 2 } ]) txStateManager._removeTx(1) assert.equal(txStateManager.getFullTxList()[0].id, 2, 'txList should have a id of 2') }) diff --git a/test/unit/app/typed-message-manager.spec.js b/test/unit/app/typed-message-manager.spec.js index 959662b91..f408530a6 100644 --- a/test/unit/app/typed-message-manager.spec.js +++ b/test/unit/app/typed-message-manager.spec.js @@ -28,19 +28,19 @@ describe('Typed Message Manager', () => { data: JSON.stringify({ 'types': { 'EIP712Domain': [ - {'name': 'name', 'type': 'string' }, - {'name': 'version', 'type': 'string' }, - {'name': 'chainId', 'type': 'uint256' }, - {'name': 'verifyingContract', 'type': 'address' }, + { 'name': 'name', 'type': 'string' }, + { 'name': 'version', 'type': 'string' }, + { 'name': 'chainId', 'type': 'uint256' }, + { 'name': 'verifyingContract', 'type': 'address' }, ], 'Person': [ - {'name': 'name', 'type': 'string' }, - {'name': 'wallet', 'type': 'address' }, + { 'name': 'name', 'type': 'string' }, + { 'name': 'wallet', 'type': 'address' }, ], 'Mail': [ - {'name': 'from', 'type': 'Person' }, - {'name': 'to', 'type': 'Person' }, - {'name': 'contents', 'type': 'string' }, + { 'name': 'from', 'type': 'Person' }, + { 'name': 'to', 'type': 'Person' }, + { 'name': 'contents', 'type': 'string' }, ], }, 'primaryType': 'Mail', diff --git a/test/unit/migrations/022-test.js b/test/unit/migrations/022-test.js index f7dd35b08..d6dfdf3ab 100644 --- a/test/unit/migrations/022-test.js +++ b/test/unit/migrations/022-test.js @@ -8,7 +8,7 @@ const storage = { 'transactions': [ { 'status': 'submitted' }, { 'status': 'submitted', 'submittedTime': properTime }, - {'status': 'confirmed'}, + { 'status': 'confirmed' }, ], }, }, diff --git a/test/unit/migrations/023-test.js b/test/unit/migrations/023-test.js index 7c93feefe..59b41a1ef 100644 --- a/test/unit/migrations/023-test.js +++ b/test/unit/migrations/023-test.js @@ -40,17 +40,17 @@ while (transactions.length <= 100) { if (!deletableTxStates.find((s) => s === status)) { nonDeletableCount++ } - transactions.push({status}) + transactions.push({ status }) } while (transactions40.length < 40) { status = txStates[Math.floor(Math.random() * Math.floor(txStates.length - 1))] - transactions40.push({status}) + transactions40.push({ status }) } while (transactions20.length < 20) { status = txStates[Math.floor(Math.random() * Math.floor(txStates.length - 1))] - transactions20.push({status}) + transactions20.push({ status }) } diff --git a/test/unit/migrations/026-test.js b/test/unit/migrations/026-test.js index b3f5470cf..77053357e 100644 --- a/test/unit/migrations/026-test.js +++ b/test/unit/migrations/026-test.js @@ -1,7 +1,7 @@ const assert = require('assert') const migration26 = require('../../../app/scripts/migrations/026') const oldStorage = { - 'meta': {'version': 25}, + 'meta': { 'version': 25 }, 'data': { 'PreferencesController': {}, 'KeyringController': { @@ -19,8 +19,8 @@ describe('migration #26', () => { .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'}, + '0x1e77e2': { name: 'Test Account 1', address: '0x1e77e2' }, + '0x7e57e2': { name: 'Test Account 2', address: '0x7e57e2' }, }) assert.strictEqual(newStorage.data.KeyringController.walletNicknames, undefined) done() diff --git a/test/unit/migrations/027-test.js b/test/unit/migrations/027-test.js index 767243a25..04c450ff6 100644 --- a/test/unit/migrations/027-test.js +++ b/test/unit/migrations/027-test.js @@ -15,9 +15,9 @@ const transactions = [] while (transactions.length < 9) { - transactions.push({status: 'rejected'}) - transactions.push({status: 'unapproved'}) - transactions.push({status: 'approved'}) + transactions.push({ status: 'rejected' }) + transactions.push({ status: 'unapproved' }) + transactions.push({ status: 'approved' }) } diff --git a/test/unit/migrations/028-test.js b/test/unit/migrations/028-test.js index a9c7dcdf1..cd0fa0b89 100644 --- a/test/unit/migrations/028-test.js +++ b/test/unit/migrations/028-test.js @@ -5,7 +5,7 @@ const oldStorage = { 'meta': {}, 'data': { 'PreferencesController': { - 'tokens': [{address: '0xa', symbol: 'A', decimals: 4}, {address: '0xb', symbol: 'B', decimals: 4}], + 'tokens': [{ address: '0xa', symbol: 'A', decimals: 4 }, { address: '0xb', symbol: 'B', decimals: 4 }], 'identities': { '0x6d14': {}, '0x3695': {}, @@ -21,7 +21,7 @@ describe('migration #28', () => { const newTokens = newStorage.data.PreferencesController.tokens const newAccountTokens = newStorage.data.PreferencesController.accountTokens - const testTokens = [{address: '0xa', symbol: 'A', decimals: 4}, {address: '0xb', symbol: 'B', decimals: 4}] + const testTokens = [{ address: '0xa', symbol: 'A', decimals: 4 }, { address: '0xb', symbol: 'B', decimals: 4 }] assert.equal(newTokens.length, 0, 'tokens is expected to have the length of 0') assert.equal(newAccountTokens['0x6d14']['mainnet'].length, 2, 'tokens for address is expected to have the length of 2') assert.equal(newAccountTokens['0x3695']['mainnet'].length, 2, 'tokens for address is expected to have the length of 2') diff --git a/test/unit/migrations/030-test.js b/test/unit/migrations/030-test.js index a8e7b4b32..9a41cacb4 100644 --- a/test/unit/migrations/030-test.js +++ b/test/unit/migrations/030-test.js @@ -15,8 +15,8 @@ const storage = { }, PreferencesController: { frequentRpcListDetail: [ - {chainId: 'fail', nickname: '', rpcUrl: 'http://127.0.0.1:8545', ticker: ''}, - {chainId: '1', nickname: '', rpcUrl: 'https://api.myetherwallet.com/eth', ticker: 'ETH'}, + { chainId: 'fail', nickname: '', rpcUrl: 'http://127.0.0.1:8545', ticker: '' }, + { chainId: '1', nickname: '', rpcUrl: 'https://api.myetherwallet.com/eth', ticker: 'ETH' }, ], }, }, diff --git a/test/unit/migrations/031-test.js b/test/unit/migrations/031-test.js index 4fcd8b9a5..ef101bdcd 100644 --- a/test/unit/migrations/031-test.js +++ b/test/unit/migrations/031-test.js @@ -7,7 +7,7 @@ describe('migration #31', () => { 'meta': {}, 'data': { 'PreferencesController': { - 'tokens': [{address: '0xa', symbol: 'A', decimals: 4}, {address: '0xb', symbol: 'B', decimals: 4}], + 'tokens': [{ address: '0xa', symbol: 'A', decimals: 4 }, { address: '0xb', symbol: 'B', decimals: 4 }], 'identities': { '0x6d14': {}, '0x3695': {}, @@ -36,7 +36,7 @@ describe('migration #31', () => { 'meta': {}, 'data': { 'PreferencesController': { - 'tokens': [{address: '0xa', symbol: 'A', decimals: 4}, {address: '0xb', symbol: 'B', decimals: 4}], + 'tokens': [{ address: '0xa', symbol: 'A', decimals: 4 }, { address: '0xb', symbol: 'B', decimals: 4 }], 'identities': { '0x6d14': {}, '0x3695': {}, diff --git a/test/unit/migrations/migrator-test.js b/test/unit/migrations/migrator-test.js index 9a949def4..0a16282a4 100644 --- a/test/unit/migrations/migrator-test.js +++ b/test/unit/migrations/migrator-test.js @@ -29,7 +29,7 @@ const stubMigrations = [ }, }, ] -const versionedData = {meta: {version: 0}, data: {hello: 'world'}} +const versionedData = { meta: { version: 0 }, data: { hello: 'world' } } const firstTimeState = { meta: { version: 0 }, @@ -62,7 +62,7 @@ describe('Migrator', () => { throw new Error('test') } } ] }) migrator.on('error', () => done()) - migrator.migrateData({ meta: {version: 0} }) + migrator.migrateData({ meta: { version: 0 } }) .then(() => { }).catch(done) }) diff --git a/test/unit/ui/app/reducers/app.spec.js b/test/unit/ui/app/reducers/app.spec.js index 6f8dd920c..58d7983a4 100644 --- a/test/unit/ui/app/reducers/app.spec.js +++ b/test/unit/ui/app/reducers/app.spec.js @@ -32,7 +32,7 @@ describe('App State', () => { it('sets networkd dropdown to false', () => { const dropdown = { networkDropdowopen: true } - const state = {...metamaskState, ...dropdown} + const state = { ...metamaskState, ...dropdown } const newState = reduceApp(state, { type: actions.NETWORK_DROPDOWN_CLOSE, }) @@ -55,8 +55,8 @@ describe('App State', () => { }) it('closes sidebar', () => { - const openSidebar = { sidebar: { isOpen: true }} - const state = {...metamaskState, ...openSidebar} + const openSidebar = { sidebar: { isOpen: true } } + const state = { ...metamaskState, ...openSidebar } const newState = reduceApp(state, { type: actions.SIDEBAR_CLOSE, @@ -77,7 +77,7 @@ describe('App State', () => { it('closes alert', () => { const alert = { alertOpen: true, alertMessage: 'test message' } - const state = {...metamaskState, ...alert} + const state = { ...metamaskState, ...alert } const newState = reduceApp(state, { type: actions.ALERT_CLOSE, }) @@ -451,7 +451,7 @@ describe('App State', () => { }, } const oldState = { - metamask: {...metamaskState.metamask, ...txs}, + metamask: { ...metamaskState.metamask, ...txs }, } const state = reduceApp(oldState, { type: actions.SHOW_CONF_TX_PAGE, @@ -480,7 +480,7 @@ describe('App State', () => { } const oldState = { - metamask: {...metamaskState, ...msgs}, + metamask: { ...metamaskState, ...msgs }, } const state = reduceApp(oldState, { @@ -508,7 +508,7 @@ describe('App State', () => { } const oldState = { - metamask: {...metamaskState, ...txs}, + metamask: { ...metamaskState, ...txs }, } const state = reduceApp(oldState, { @@ -538,8 +538,8 @@ describe('App State', () => { it('proceeds to change current view context in confTx', () => { const oldState = { - metamask: {metamaskState}, - appState: {currentView: {context: 0}}, + metamask: { metamaskState }, + appState: { currentView: { context: 0 } }, } const state = reduceApp(oldState, { @@ -565,7 +565,7 @@ describe('App State', () => { const oldState = { - metamask: {...metamaskState, ...txs}, + metamask: { ...metamaskState, ...txs }, } const state = reduceApp(oldState, { @@ -592,7 +592,7 @@ describe('App State', () => { const oldState = { - metamask: {...metamaskState, ...txs}, + metamask: { ...metamaskState, ...txs }, } const state = reduceApp(oldState, { @@ -633,7 +633,7 @@ describe('App State', () => { it('sets warning to empty string when unlock succeeds', () => { const errorState = { warning: 'errors' } - const oldState = {...metamaskState, ...errorState} + const oldState = { ...metamaskState, ...errorState } const state = reduceApp(oldState, { type: actions.UNLOCK_SUCCEEDED, }) @@ -668,8 +668,8 @@ describe('App State', () => { }) it('hides loading message', () => { - const loadingState = { isLoading: true} - const oldState = {...metamaskState, ...loadingState} + const loadingState = { isLoading: true } + const oldState = { ...metamaskState, ...loadingState } const state = reduceApp(oldState, { type: actions.HIDE_LOADING, @@ -687,7 +687,7 @@ describe('App State', () => { }) it('hides sub loading indicator', () => { - const oldState = {...metamaskState, isSubLoading: true } + const oldState = { ...metamaskState, isSubLoading: true } const state = reduceApp(oldState, { type: actions.HIDE_SUB_LOADING_INDICATION, }) @@ -706,8 +706,8 @@ describe('App State', () => { }) it('hides warning', () => { - const displayWarningState = { warning: 'warning'} - const oldState = {...metamaskState, ...displayWarningState} + const displayWarningState = { warning: 'warning' } + const oldState = { ...metamaskState, ...displayWarningState } const state = reduceApp(oldState, { type: actions.HIDE_WARNING, }) @@ -732,7 +732,7 @@ describe('App State', () => { accountExport: 'progress', }, } - const oldState = {...metamaskState, ...requestAccountExportState} + const oldState = { ...metamaskState, ...requestAccountExportState } const state = reduceApp(oldState, { type: actions.EXPORT_ACCOUNT, }) @@ -789,7 +789,7 @@ describe('App State', () => { }, }, } - const oldState = {...metamaskState, ...appState} + const oldState = { ...metamaskState, ...appState } const state = reduceApp(oldState, { type: actions.COINBASE_SUBVIEW, }) @@ -830,7 +830,7 @@ describe('App State', () => { }, } - const oldState = {...metamaskState, ...appState} + const oldState = { ...metamaskState, ...appState } const state = reduceApp(oldState, { type: actions.SHAPESHIFT_SUBVIEW, @@ -881,7 +881,7 @@ describe('App State', () => { maxLimit: 0.76617432, } - const oldState = {...metamaskState, ...appState} + const oldState = { ...metamaskState, ...appState } const state = reduceApp(oldState, { type: actions.PAIR_UPDATE, @@ -922,7 +922,7 @@ describe('App State', () => { }, } - const oldState = {...metamaskState, ...appState} + const oldState = { ...metamaskState, ...appState } const state = reduceApp(oldState, { type: actions.SHOW_QR_VIEW, value: { @@ -957,7 +957,7 @@ describe('App State', () => { it('unsets gas loading', () => { const gasLoadingState = { gasIsLoading: true } - const oldState = {...metamaskState, ...gasLoadingState} + const oldState = { ...metamaskState, ...gasLoadingState } const state = reduceApp(oldState, { type: actions.GAS_LOADING_FINISHED, }) diff --git a/test/unit/ui/app/reducers/metamask.spec.js b/test/unit/ui/app/reducers/metamask.spec.js index 6b3dd7193..ef28de5cf 100644 --- a/test/unit/ui/app/reducers/metamask.spec.js +++ b/test/unit/ui/app/reducers/metamask.spec.js @@ -5,7 +5,7 @@ import * as actions from '../../../../../ui/app/store/actions' describe('MetaMask Reducers', () => { it('init state', () => { - const initState = reduceMetamask({metamask: {}}, {}) + const initState = reduceMetamask({ metamask: {} }, {}) assert(initState) }) diff --git a/test/unit/ui/app/selectors.spec.js b/test/unit/ui/app/selectors.spec.js index cc8e3e9f1..caa040c64 100644 --- a/test/unit/ui/app/selectors.spec.js +++ b/test/unit/ui/app/selectors.spec.js @@ -4,7 +4,7 @@ const mockState = require('../../../data/mock-state.json') const Eth = require('ethjs') const { createTestProviderTools } = require('../../../stub/provider') -const provider = createTestProviderTools({ scaffold: {}}).provider +const provider = createTestProviderTools({ scaffold: {} }).provider describe('Selectors', function () { diff --git a/test/web3/schema.js b/test/web3/schema.js index 9dc528a57..54a6ff1a9 100644 --- a/test/web3/schema.js +++ b/test/web3/schema.js @@ -30,7 +30,7 @@ const params = { value: '0x9184e72a', data: '0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675', }, - filterGetLogs: [{'blockHash': '0x7c5a35e9cb3e8ae0e221ab470abae9d446c3a5626ce6689fc777dcffcab52c70', 'topics': ['0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80']}], + filterGetLogs: [{ 'blockHash': '0x7c5a35e9cb3e8ae0e221ab470abae9d446c3a5626ce6689fc777dcffcab52c70', 'topics': ['0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80'] }], block: { __required: [], number: 'Q', diff --git a/ui/app/components/app/add-token-button/add-token-button.component.js b/ui/app/components/app/add-token-button/add-token-button.component.js index 10887aed8..7a8e75304 100644 --- a/ui/app/components/app/add-token-button/add-token-button.component.js +++ b/ui/app/components/app/add-token-button/add-token-button.component.js @@ -1,5 +1,5 @@ import PropTypes from 'prop-types' -import React, {PureComponent} from 'react' +import React, { PureComponent } from 'react' export default class AddTokenButton extends PureComponent { static contextTypes = { diff --git a/ui/app/components/app/customize-gas-modal/gas-modal-card.js b/ui/app/components/app/customize-gas-modal/gas-modal-card.js index 5ba96dd82..117e92c5b 100644 --- a/ui/app/components/app/customize-gas-modal/gas-modal-card.js +++ b/ui/app/components/app/customize-gas-modal/gas-modal-card.js @@ -1,4 +1,4 @@ -import React, {Component} from 'react' +import React, { Component } from 'react' const inherits = require('util').inherits const InputNumber = require('../input-number.js') diff --git a/ui/app/components/app/dropdowns/network-dropdown.js b/ui/app/components/app/dropdowns/network-dropdown.js index cf56919c4..12a51ee7d 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.js +++ b/ui/app/components/app/dropdowns/network-dropdown.js @@ -1,5 +1,5 @@ import PropTypes from 'prop-types' -import React, {Component} from 'react' +import React, { Component } from 'react' const inherits = require('util').inherits const connect = require('react-redux').connect const { withRouter } = require('react-router-dom') diff --git a/ui/app/components/app/dropdowns/tests/dropdown.test.js b/ui/app/components/app/dropdowns/tests/dropdown.test.js index f7c1e31b1..4eb26ec59 100644 --- a/ui/app/components/app/dropdowns/tests/dropdown.test.js +++ b/ui/app/components/app/dropdowns/tests/dropdown.test.js @@ -13,7 +13,7 @@ describe('Dropdown', () => { wrapper = shallow( diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js b/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js index 4fa0d4d94..6b547abc6 100644 --- a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js +++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js @@ -23,7 +23,7 @@ const mapDispatchToProps = dispatch => { } const mergeProps = (stateProps, dispatchProps, ownProps) => { - const {customGasPrice, customGasLimit, updateCustomGasPrice, updateCustomGasLimit} = ownProps + const { customGasPrice, customGasLimit, updateCustomGasPrice, updateCustomGasLimit } = ownProps return { ...ownProps, ...stateProps, diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js index 8e3d14ea4..aa9e64eaf 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js @@ -249,7 +249,7 @@ describe('gas-modal-page-container container', () => { ] let result - tests.forEach(({ mockState, mockOwnProps, expectedResult}) => { + tests.forEach(({ mockState, mockOwnProps, expectedResult }) => { result = mapStateToProps(mockState, mockOwnProps) assert.deepEqual(result, expectedResult) }) diff --git a/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js b/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js index 452544abe..02f018995 100644 --- a/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js +++ b/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js @@ -190,7 +190,7 @@ export function generateChart (gasPrices, estimatedTimes, gasPricesMax, estimate transition: { duration: 0, }, - padding: {left: 20, right: 15, top: 6, bottom: 10}, + padding: { left: 20, right: 15, top: 6, bottom: 10 }, data: { x: 'x', columns: [ @@ -218,14 +218,14 @@ export function generateChart (gasPrices, estimatedTimes, gasPricesMax, estimate return val + ' GWEI' }, }, - padding: {left: gasPricesMax / 50, right: gasPricesMax / 50}, + padding: { left: gasPricesMax / 50, right: gasPricesMax / 50 }, label: { text: 'Gas Price ($)', position: 'outer-center', }, }, y: { - padding: {top: 7, bottom: 7}, + padding: { top: 7, bottom: 7 }, tick: { values: [Math.floor(estimatedTimesMax * 0.05), Math.ceil(estimatedTimesMax * 0.97)], outer: false, diff --git a/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js b/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js index c960f49a7..9ac60770a 100644 --- a/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js +++ b/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js @@ -97,7 +97,7 @@ describe('GasPriceChart Component', function () { assert(GasPriceChart.prototype.renderChart.callCount, 1) wrapper.instance().componentDidMount() assert(GasPriceChart.prototype.renderChart.callCount, 2) - assert.deepEqual(GasPriceChart.prototype.renderChart.getCall(1).args, [{...testProps}]) + assert.deepEqual(GasPriceChart.prototype.renderChart.getCall(1).args, [{ ...testProps }]) }) }) diff --git a/ui/app/components/app/home-notification/home-notification.component.js b/ui/app/components/app/home-notification/home-notification.component.js index d3d0a0961..b17622e79 100644 --- a/ui/app/components/app/home-notification/home-notification.component.js +++ b/ui/app/components/app/home-notification/home-notification.component.js @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react' import classnames from 'classnames' -import {Tooltip as ReactTippy} from 'react-tippy' +import { Tooltip as ReactTippy } from 'react-tippy' import PropTypes from 'prop-types' import Button from '../../ui/button' diff --git a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js index b2ed1a8cc..d47401fb6 100644 --- a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js +++ b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js @@ -1,4 +1,4 @@ -import React, { Component} from 'react' +import React, { Component } from 'react' import PropTypes from 'prop-types' import AccountModalContainer from '../account-modal-container' import genAccountLink from '../../../../../lib/account-link.js' diff --git a/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js b/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js index 345951b0f..6c3d118ee 100644 --- a/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js +++ b/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js @@ -14,7 +14,7 @@ describe('CancelTransaction Component', () => { , - { context: { t }} + { context: { t } } ) assert.ok(wrapper) @@ -36,7 +36,7 @@ describe('CancelTransaction Component', () => { hideModal={hideModalSpy} showTransactionConfirmedModal={() => {}} />, - { context: { t }} + { context: { t } } ) assert.equal(wrapper.find(Modal).length, 1) diff --git a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js index d503d950e..1e6715ef8 100644 --- a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js +++ b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js @@ -1,6 +1,6 @@ import PropTypes from 'prop-types' -import React, {Component} from 'react' -import {getNetworkDisplayName} from '../../../../../../app/scripts/controllers/network/util' +import React, { Component } from 'react' +import { getNetworkDisplayName } from '../../../../../../app/scripts/controllers/network/util' import Button from '../../../ui/button' export default class DepositEtherModal extends Component { diff --git a/ui/app/components/app/modals/notification-modal.js b/ui/app/components/app/modals/notification-modal.js index 800cd4f2f..ac7af6140 100644 --- a/ui/app/components/app/modals/notification-modal.js +++ b/ui/app/components/app/modals/notification-modal.js @@ -1,6 +1,6 @@ import PropTypes from 'prop-types' -import React, {Component} from 'react' -import {connect} from 'react-redux' +import React, { Component } from 'react' +import { connect } from 'react-redux' import { hideModal } from '../../../store/actions' class NotificationModal extends Component { diff --git a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js b/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js index 7accf0e58..3fd08d906 100644 --- a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js +++ b/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js @@ -81,12 +81,12 @@ export default class QrScanner extends Component { this.props.qrCodeDetected(result) this.stopAndClose() } else { - this.setState({msg: this.context.t('unknownQrCode')}) + this.setState({ msg: this.context.t('unknownQrCode') }) } }) .catch(err => { if (err && err.name === 'NotAllowedError') { - this.setState({msg: this.context.t('youNeedToAllowCameraAccess')}) + this.setState({ msg: this.context.t('youNeedToAllowCameraAccess') }) clearTimeout(this.permissionChecker) this.needsToReinit = true this.checkPermisisions() @@ -110,16 +110,16 @@ export default class QrScanner extends Component { if (content.split('ethereum:').length > 1) { type = 'address' - values = {'address': content.split('ethereum:')[1] } + values = { 'address': content.split('ethereum:')[1] } // Regular ethereum addresses - fox ex. 0x.....1111 } else if (content.substring(0, 2).toLowerCase() === '0x') { type = 'address' - values = {'address': content } + values = { 'address': content } } - return {type, values} + return { type, values } } diff --git a/ui/app/components/app/network.js b/ui/app/components/app/network.js index 88204aef7..62251dcfc 100644 --- a/ui/app/components/app/network.js +++ b/ui/app/components/app/network.js @@ -1,5 +1,5 @@ import PropTypes from 'prop-types' -import React, {Component} from 'react' +import React, { Component } from 'react' const classnames = require('classnames') const inherits = require('util').inherits diff --git a/ui/app/components/app/permission-page-container/index.js b/ui/app/components/app/permission-page-container/index.js index ea3b8daaa..63e8265c2 100644 --- a/ui/app/components/app/permission-page-container/index.js +++ b/ui/app/components/app/permission-page-container/index.js @@ -1,3 +1,3 @@ -export {default} from './permission-page-container.container' -export {default as PermissionPageContainerContent} from './permission-page-container-content' -export {default as PermissionPageContainerHeader} from './permission-page-container-header' +export { default } from './permission-page-container.container' +export { default as PermissionPageContainerContent } from './permission-page-container-content' +export { default as PermissionPageContainerHeader } from './permission-page-container-header' diff --git a/ui/app/components/app/permission-page-container/permission-page-container-content/index.js b/ui/app/components/app/permission-page-container/permission-page-container-content/index.js index 899d168f9..014e4ff59 100644 --- a/ui/app/components/app/permission-page-container/permission-page-container-content/index.js +++ b/ui/app/components/app/permission-page-container/permission-page-container-content/index.js @@ -1 +1 @@ -export {default} from './permission-page-container-content.component' +export { default } from './permission-page-container-content.component' diff --git a/ui/app/components/app/permission-page-container/permission-page-container-header/index.js b/ui/app/components/app/permission-page-container/permission-page-container-header/index.js index 45ef9036b..d57a5370b 100644 --- a/ui/app/components/app/permission-page-container/permission-page-container-header/index.js +++ b/ui/app/components/app/permission-page-container/permission-page-container-header/index.js @@ -1 +1 @@ -export {default} from './permission-page-container-header.component' +export { default } from './permission-page-container-header.component' diff --git a/ui/app/components/app/permission-page-container/permission-page-container-header/permission-page-container-header.component.js b/ui/app/components/app/permission-page-container/permission-page-container-header/permission-page-container-header.component.js index 8ba3444ba..bf314b994 100644 --- a/ui/app/components/app/permission-page-container/permission-page-container-header/permission-page-container-header.component.js +++ b/ui/app/components/app/permission-page-container/permission-page-container-header/permission-page-container-header.component.js @@ -1,4 +1,4 @@ -import React, {PureComponent} from 'react' +import React, { PureComponent } from 'react' import NetworkDisplay from '../../network-display' export default class PermissionPageContainerHeader extends PureComponent { diff --git a/ui/app/components/app/selected-account/tests/selected-account-component.test.js b/ui/app/components/app/selected-account/tests/selected-account-component.test.js index 42e5c8f1b..7db5c7202 100644 --- a/ui/app/components/app/selected-account/tests/selected-account-component.test.js +++ b/ui/app/components/app/selected-account/tests/selected-account-component.test.js @@ -10,7 +10,7 @@ describe('SelectedAccount Component', () => { selectedAddress="0x1b82543566f41a7db9a9a75fc933c340ffb55c9d" selectedIdentity={{ name: 'testName' }} /> - ), { context: { t: () => {}}}) + ), { context: { t: () => {} } }) // Checksummed version of address is displayed assert.equal(wrapper.find('.selected-account__address').text(), '0x1B82...5C9D') assert.equal(wrapper.find('.selected-account__name').text(), 'testName') diff --git a/ui/app/components/app/shift-list-item/shift-list-item.container.js b/ui/app/components/app/shift-list-item/shift-list-item.container.js index 1d7645dfd..6dcfab844 100644 --- a/ui/app/components/app/shift-list-item/shift-list-item.container.js +++ b/ui/app/components/app/shift-list-item/shift-list-item.container.js @@ -1,4 +1,4 @@ -import {connect} from 'react-redux' +import { connect } from 'react-redux' import ShiftListItem from './shift-list-item.component' function mapStateToProps (state) { diff --git a/ui/app/components/app/signature-request/signature-request.component.js b/ui/app/components/app/signature-request/signature-request.component.js index b108c02c4..3abfbd770 100644 --- a/ui/app/components/app/signature-request/signature-request.component.js +++ b/ui/app/components/app/signature-request/signature-request.component.js @@ -51,7 +51,7 @@ export default class SignatureRequest extends PureComponent { render () { const { selectedAccount, - txData: { msgParams: { data, origin, from: senderWallet }}, + txData: { msgParams: { data, origin, from: senderWallet } }, cancel, sign, } = this.props diff --git a/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js b/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js index f97e81d15..636fcfdcd 100644 --- a/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js +++ b/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js @@ -41,7 +41,7 @@ describe('TransactionAction Component', () => { transaction={transaction} className="transaction-action" /> - ), { context: { t }}) + ), { context: { t } }) assert.equal(wrapper.find('.transaction-action').length, 1) wrapper.setState({ transactionAction: 'sentEther' }) @@ -108,7 +108,7 @@ describe('TransactionAction Component', () => { transaction={transaction} className="test-class" />, - { context: { t }} + { context: { t } } ) assert.ok(wrapper) diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js b/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js index b74513879..b1ab275ed 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js +++ b/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js @@ -55,7 +55,7 @@ export function getActivities (transaction, isFirstTransaction = false) { id, hash, history = [], - txParams: { gas: paramsGasLimit, gasPrice: paramsGasPrice}, + txParams: { gas: paramsGasLimit, gasPrice: paramsGasPrice }, xReceipt: { status } = {}, type, } = transaction diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js index 82f377358..689a60208 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux' import TransactionBreakdown from './transaction-breakdown.component' -import {getIsMainnet, getNativeCurrency, preferencesSelector} from '../../../selectors/selectors' +import { getIsMainnet, getNativeCurrency, preferencesSelector } from '../../../selectors/selectors' import { getHexGasTotal } from '../../../helpers/utils/confirm-tx.util' import { sumHexes } from '../../../helpers/utils/transactions.util' diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js index f3bd51b93..29634e023 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js +++ b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js @@ -71,7 +71,7 @@ export default class TransactionListItemDetails extends PureComponent { } handleCopyTxId = () => { - const { transactionGroup} = this.props + const { transactionGroup } = this.props const { primaryTransaction: transaction } = transactionGroup const { hash } = transaction diff --git a/ui/app/components/app/wallet-view/wallet-view.container.js b/ui/app/components/app/wallet-view/wallet-view.container.js index 1e37bc2a8..29790f9a3 100644 --- a/ui/app/components/app/wallet-view/wallet-view.container.js +++ b/ui/app/components/app/wallet-view/wallet-view.container.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' import { compose } from 'recompose' import WalletView from './wallet-view.component' -import {showSendPage, hideSidebar, setSelectedToken, showAddTokenPage} from '../../../store/actions' +import { showSendPage, hideSidebar, setSelectedToken, showAddTokenPage } from '../../../store/actions' import { getMetaMaskAccounts, getSelectedAddress, getSelectedAccount } from '../../../selectors/selectors' function mapStateToProps (state) { diff --git a/ui/app/components/ui/alert/index.js b/ui/app/components/ui/alert/index.js index 7d09de3cb..63b537484 100644 --- a/ui/app/components/ui/alert/index.js +++ b/ui/app/components/ui/alert/index.js @@ -32,7 +32,7 @@ class Alert extends Component { }) setTimeout(_ => { - this.setState({visible: false}) + this.setState({ visible: false }) }, 500) } diff --git a/ui/app/components/ui/breadcrumbs/breadcrumbs.component.js b/ui/app/components/ui/breadcrumbs/breadcrumbs.component.js index 6644836db..c407e4ead 100644 --- a/ui/app/components/ui/breadcrumbs/breadcrumbs.component.js +++ b/ui/app/components/ui/breadcrumbs/breadcrumbs.component.js @@ -19,7 +19,7 @@ export default class Breadcrumbs extends PureComponent {
)) } diff --git a/ui/app/components/ui/currency-input/currency-input.component.js b/ui/app/components/ui/currency-input/currency-input.component.js index f7db2b829..18289d4e4 100644 --- a/ui/app/components/ui/currency-input/currency-input.component.js +++ b/ui/app/components/ui/currency-input/currency-input.component.js @@ -79,7 +79,7 @@ export default class CurrencyInput extends PureComponent { swap = () => { const { isSwapped, decimalValue } = this.state - this.setState({isSwapped: !isSwapped}, () => { + this.setState({ isSwapped: !isSwapped }, () => { this.handleChange(decimalValue) }) } diff --git a/ui/app/components/ui/currency-input/currency-input.container.js b/ui/app/components/ui/currency-input/currency-input.container.js index 46e70bace..0c76d6ce5 100644 --- a/ui/app/components/ui/currency-input/currency-input.container.js +++ b/ui/app/components/ui/currency-input/currency-input.container.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux' import CurrencyInput from './currency-input.component' import { ETH } from '../../../helpers/constants/common' import { getMaxModeOn } from '../../../pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.selectors' -import {getIsMainnet, preferencesSelector} from '../../../selectors/selectors' +import { getIsMainnet, preferencesSelector } from '../../../selectors/selectors' const mapStateToProps = state => { const { metamask: { nativeCurrency, currentCurrency, conversionRate } } = state diff --git a/ui/app/components/ui/error-message/tests/error-message.component.test.js b/ui/app/components/ui/error-message/tests/error-message.component.test.js index 8c5347173..b4dcbde32 100644 --- a/ui/app/components/ui/error-message/tests/error-message.component.test.js +++ b/ui/app/components/ui/error-message/tests/error-message.component.test.js @@ -11,7 +11,7 @@ describe('ErrorMessage Component', () => { , - { context: { t }} + { context: { t } } ) assert.ok(wrapper) @@ -25,7 +25,7 @@ describe('ErrorMessage Component', () => { , - { context: { t }} + { context: { t } } ) assert.ok(wrapper) diff --git a/ui/app/components/ui/eth-balance/eth-balance.component.js b/ui/app/components/ui/eth-balance/eth-balance.component.js index 925395602..a79b7a198 100644 --- a/ui/app/components/ui/eth-balance/eth-balance.component.js +++ b/ui/app/components/ui/eth-balance/eth-balance.component.js @@ -1,5 +1,5 @@ import PropTypes from 'prop-types' -import React, {Component} from 'react' +import React, { Component } from 'react' const { formatBalance, diff --git a/ui/app/components/ui/loading-screen/loading-screen.component.js b/ui/app/components/ui/loading-screen/loading-screen.component.js index b3fb3308d..ec8fb1d33 100644 --- a/ui/app/components/ui/loading-screen/loading-screen.component.js +++ b/ui/app/components/ui/loading-screen/loading-screen.component.js @@ -1,4 +1,4 @@ -import React, {Component} from 'react' +import React, { Component } from 'react' const PropTypes = require('prop-types') const Spinner = require('../spinner') diff --git a/ui/app/components/ui/lock-icon/lock-icon.component.js b/ui/app/components/ui/lock-icon/lock-icon.component.js index d010cb6b2..7724b75dd 100644 --- a/ui/app/components/ui/lock-icon/lock-icon.component.js +++ b/ui/app/components/ui/lock-icon/lock-icon.component.js @@ -12,7 +12,7 @@ export default function LockIcon (props) { width="401.998px" height="401.998px" viewBox="0 0 401.998 401.998" - style={{enableBackground: 'new 0 0 401.998 401.998'}} + style={{ enableBackground: 'new 0 0 401.998 401.998' }} xmlSpace="preserve" {...props} > diff --git a/ui/app/components/ui/mascot.js b/ui/app/components/ui/mascot.js index f84961745..368e10634 100644 --- a/ui/app/components/ui/mascot.js +++ b/ui/app/components/ui/mascot.js @@ -6,7 +6,7 @@ const debounce = require('debounce') module.exports = Mascot inherits(Mascot, Component) -function Mascot ({width = '200', height = '200'}) { +function Mascot ({ width = '200', height = '200' }) { Component.call(this) this.logo = metamaskLogo({ followMouse: true, diff --git a/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js b/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js index c3a43b91d..625dcb890 100644 --- a/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js +++ b/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js @@ -8,7 +8,7 @@ describe('Page Container Header', () => { let wrapper, style, onBackButtonClick, onClose beforeEach(() => { - style = {test: 'style'} + style = { test: 'style' } onBackButtonClick = sinon.spy() onClose = sinon.spy() diff --git a/ui/app/components/ui/spinner/spinner.component.js b/ui/app/components/ui/spinner/spinner.component.js index b9a2eb52a..2936287de 100644 --- a/ui/app/components/ui/spinner/spinner.component.js +++ b/ui/app/components/ui/spinner/spinner.component.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types' const Spinner = ({ className = '', color = '#000000' }) => { return (
- + diff --git a/ui/app/components/ui/token-input/token-input.container.js b/ui/app/components/ui/token-input/token-input.container.js index 981cb3598..8c867e8e6 100644 --- a/ui/app/components/ui/token-input/token-input.container.js +++ b/ui/app/components/ui/token-input/token-input.container.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux' import TokenInput from './token-input.component' -import {getIsMainnet, getSelectedToken, getSelectedTokenExchangeRate, preferencesSelector} from '../../../selectors/selectors' +import { getIsMainnet, getSelectedToken, getSelectedTokenExchangeRate, preferencesSelector } from '../../../selectors/selectors' const mapStateToProps = state => { const { metamask: { currentCurrency } } = state diff --git a/ui/app/components/ui/tooltip-v2.js b/ui/app/components/ui/tooltip-v2.js index c7f94506c..24518d392 100644 --- a/ui/app/components/ui/tooltip-v2.js +++ b/ui/app/components/ui/tooltip-v2.js @@ -1,6 +1,6 @@ import PropTypes from 'prop-types' -import React, {PureComponent} from 'react' -import {Tooltip as ReactTippy} from 'react-tippy' +import React, { PureComponent } from 'react' +import { Tooltip as ReactTippy } from 'react-tippy' export default class Tooltip extends PureComponent { static defaultProps = { @@ -39,7 +39,7 @@ export default class Tooltip extends PureComponent { } render () { - const {arrow, children, containerClassName, disabled, position, html, size, title, trigger, onHidden, wrapperClassName, style } = this.props + const { arrow, children, containerClassName, disabled, position, html, size, title, trigger, onHidden, wrapperClassName, style } = this.props if (!title && !html) { return ( diff --git a/ui/app/ducks/app/app.js b/ui/app/ducks/app/app.js index b877cefb4..7049ad904 100644 --- a/ui/app/ducks/app/app.js +++ b/ui/app/ducks/app/app.js @@ -150,7 +150,7 @@ export default function reduceApp (state, action) { state.appState.modal, { open: false }, { modalState: { name: null, props: {} } }, - { previousModalState: appState.modal.modalState}, + { previousModalState: appState.modal.modalState }, ), }) @@ -536,7 +536,7 @@ export default function reduceApp (state, action) { case actions.SET_HARDWARE_WALLET_DEFAULT_HD_PATH: const { device, path } = action.value - const newDefaults = {...appState.defaultHdPaths} + const newDefaults = { ...appState.defaultHdPaths } newDefaults[device] = path return extend(appState, { diff --git a/ui/app/ducks/gas/gas-duck.test.js b/ui/app/ducks/gas/gas-duck.test.js index 85450489d..0ae68628e 100644 --- a/ui/app/ducks/gas/gas-duck.test.js +++ b/ui/app/ducks/gas/gas-duck.test.js @@ -161,7 +161,7 @@ describe('Gas Duck', () => { GasReducer(mockState, { type: BASIC_GAS_ESTIMATE_LOADING_STARTED, }), - Object.assign({basicEstimateIsLoading: true}, mockState.gas) + Object.assign({ basicEstimateIsLoading: true }, mockState.gas) ) }) @@ -170,7 +170,7 @@ describe('Gas Duck', () => { GasReducer(mockState, { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED, }), - Object.assign({basicEstimateIsLoading: false}, mockState.gas) + Object.assign({ basicEstimateIsLoading: false }, mockState.gas) ) }) @@ -179,7 +179,7 @@ describe('Gas Duck', () => { GasReducer(mockState, { type: GAS_ESTIMATE_LOADING_STARTED, }), - Object.assign({gasEstimatesLoading: true}, mockState.gas) + Object.assign({ gasEstimatesLoading: true }, mockState.gas) ) }) @@ -188,7 +188,7 @@ describe('Gas Duck', () => { GasReducer(mockState, { type: GAS_ESTIMATE_LOADING_FINISHED, }), - Object.assign({gasEstimatesLoading: false}, mockState.gas) + Object.assign({ gasEstimatesLoading: false }, mockState.gas) ) }) @@ -203,7 +203,7 @@ describe('Gas Duck', () => { type: SET_BASIC_GAS_ESTIMATE_DATA, value: { someProp: 'someData123' }, }), - Object.assign({basicEstimates: {someProp: 'someData123'} }, mockState.gas) + Object.assign({ basicEstimates: { someProp: 'someData123' } }, mockState.gas) ) }) @@ -213,7 +213,7 @@ describe('Gas Duck', () => { type: SET_PRICE_AND_TIME_ESTIMATES, value: { someProp: 'someData123' }, }), - Object.assign({priceAndTimeEstimates: {someProp: 'someData123'} }, mockState.gas) + Object.assign({ priceAndTimeEstimates: { someProp: 'someData123' } }, mockState.gas) ) }) @@ -223,7 +223,7 @@ describe('Gas Duck', () => { type: SET_CUSTOM_GAS_PRICE, value: 4321, }), - Object.assign({customData: {price: 4321} }, mockState.gas) + Object.assign({ customData: { price: 4321 } }, mockState.gas) ) }) @@ -233,7 +233,7 @@ describe('Gas Duck', () => { type: SET_CUSTOM_GAS_LIMIT, value: 9876, }), - Object.assign({customData: {limit: 9876} }, mockState.gas) + Object.assign({ customData: { limit: 9876 } }, mockState.gas) ) }) @@ -243,7 +243,7 @@ describe('Gas Duck', () => { type: SET_CUSTOM_GAS_TOTAL, value: 10000, }), - Object.assign({customData: {total: 10000} }, mockState.gas) + Object.assign({ customData: { total: 10000 } }, mockState.gas) ) }) @@ -273,7 +273,7 @@ describe('Gas Duck', () => { type: SET_CUSTOM_GAS_ERRORS, value: { someError: 'error_error' }, }), - Object.assign({errors: {someError: 'error_error'} }, mockState.gas) + Object.assign({ errors: { someError: 'error_error' } }, mockState.gas) ) }) @@ -316,7 +316,7 @@ describe('Gas Duck', () => { ) })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED} ] + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ] ) assert.deepEqual( global.fetch.getCall(0).args, @@ -379,7 +379,7 @@ describe('Gas Duck', () => { ) })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED} ] + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ] ) assert.ok(global.fetch.notCalled) assert.deepEqual( @@ -415,7 +415,7 @@ describe('Gas Duck', () => { ) })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED} ] + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ] ) assert.deepEqual( global.fetch.getCall(0).args, @@ -469,7 +469,7 @@ describe('Gas Duck', () => { })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED} ] + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ] ) assert.deepEqual( global.fetch.getCall(0).args, @@ -546,7 +546,7 @@ describe('Gas Duck', () => { })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED} ] + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ] ) assert.ok(global.fetch.notCalled) @@ -590,7 +590,7 @@ describe('Gas Duck', () => { })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED} ] + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ] ) assert.deepEqual( global.fetch.getCall(0).args, @@ -651,7 +651,7 @@ describe('Gas Duck', () => { })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: GAS_ESTIMATE_LOADING_STARTED} ] + [{ type: GAS_ESTIMATE_LOADING_STARTED } ] ) assert.deepEqual( global.fetch.getCall(0).args, @@ -705,7 +705,7 @@ describe('Gas Duck', () => { })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: GAS_ESTIMATE_LOADING_STARTED} ] + [{ type: GAS_ESTIMATE_LOADING_STARTED } ] ) assert.equal(global.fetch.callCount, 0) diff --git a/ui/app/ducks/gas/gas.duck.js b/ui/app/ducks/gas/gas.duck.js index 700fec6b0..e5c53c570 100644 --- a/ui/app/ducks/gas/gas.duck.js +++ b/ui/app/ducks/gas/gas.duck.js @@ -386,7 +386,7 @@ export function fetchGasEstimates (blockTime) { 'referrerPolicy': 'no-referrer-when-downgrade', 'body': null, 'method': 'GET', - 'mode': 'cors'} + 'mode': 'cors' } ) .then(r => r.json()) .then(r => { diff --git a/ui/app/ducks/send/send-duck.test.js b/ui/app/ducks/send/send-duck.test.js index 8248ba032..418707518 100644 --- a/ui/app/ducks/send/send-duck.test.js +++ b/ui/app/ducks/send/send-duck.test.js @@ -52,7 +52,7 @@ describe('Send Duck', () => { SendReducer(mockState, { type: OPEN_FROM_DROPDOWN, }), - Object.assign({fromDropdownOpen: true}, mockState.send) + Object.assign({ fromDropdownOpen: true }, mockState.send) ) }) @@ -66,7 +66,7 @@ describe('Send Duck', () => { SendReducer(mockState, { type: CLOSE_FROM_DROPDOWN, }), - Object.assign({fromDropdownOpen: false}, mockState.send) + Object.assign({ fromDropdownOpen: false }, mockState.send) ) }) @@ -75,7 +75,7 @@ describe('Send Duck', () => { SendReducer(mockState, { type: OPEN_TO_DROPDOWN, }), - Object.assign({toDropdownOpen: true}, mockState.send) + Object.assign({ toDropdownOpen: true }, mockState.send) ) }) @@ -84,7 +84,7 @@ describe('Send Duck', () => { SendReducer(mockState, { type: CLOSE_TO_DROPDOWN, }), - Object.assign({toDropdownOpen: false}, mockState.send) + Object.assign({ toDropdownOpen: false }, mockState.send) ) }) @@ -93,7 +93,7 @@ describe('Send Duck', () => { SendReducer(Object.assign({}, mockState, { gasButtonGroupShown: false }), { type: SHOW_GAS_BUTTON_GROUP, }), - Object.assign({gasButtonGroupShown: true}, mockState.send) + Object.assign({ gasButtonGroupShown: true }, mockState.send) ) }) @@ -102,7 +102,7 @@ describe('Send Duck', () => { SendReducer(mockState, { type: HIDE_GAS_BUTTON_GROUP, }), - Object.assign({gasButtonGroupShown: false}, mockState.send) + Object.assign({ gasButtonGroupShown: false }, mockState.send) ) }) diff --git a/ui/app/helpers/utils/conversion-util.test.js b/ui/app/helpers/utils/conversion-util.test.js index 368ce3bba..4420f9b4d 100644 --- a/ui/app/helpers/utils/conversion-util.test.js +++ b/ui/app/helpers/utils/conversion-util.test.js @@ -1,5 +1,5 @@ import assert from 'assert' -import {addCurrencies} from './conversion-util' +import { addCurrencies } from './conversion-util' describe('conversion utils', () => { diff --git a/ui/app/helpers/utils/util.js b/ui/app/helpers/utils/util.js index 75ba15410..3f412b2e3 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/app/helpers/utils/util.js @@ -304,7 +304,7 @@ function getContractAtAddress (tokenAddress) { function exportAsFile (filename, data, type = 'text/csv') { // source: https://stackoverflow.com/a/33542499 by Ludovic Feltz - const blob = new Blob([data], {type}) + const blob = new Blob([data], { type }) if (window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveBlob(blob, filename) } else { diff --git a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js index cc73b2ea7..90bfe1449 100644 --- a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js +++ b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js @@ -18,7 +18,7 @@ const mapStateToProps = ({ metamask }) => { const mapDispatchToProps = dispatch => { return { - addToken: ({address, symbol, decimals, image}) => dispatch(addToken(address, symbol, Number(decimals), image)), + addToken: ({ address, symbol, decimals, image }) => dispatch(addToken(address, symbol, Number(decimals), image)), removeSuggestedTokens: () => dispatch(removeSuggestedTokens()), } } diff --git a/ui/app/pages/confirm-transaction/conf-tx.js b/ui/app/pages/confirm-transaction/conf-tx.js index 91ff4b9e4..6ace92259 100644 --- a/ui/app/pages/confirm-transaction/conf-tx.js +++ b/ui/app/pages/confirm-transaction/conf-tx.js @@ -1,4 +1,4 @@ -import React, {Component} from 'react' +import React, { Component } from 'react' const inherits = require('util').inherits const connect = require('react-redux').connect const { withRouter } = require('react-router-dom') diff --git a/ui/app/pages/create-account/connect-hardware/connect-screen.js b/ui/app/pages/create-account/connect-hardware/connect-screen.js index 6be85f5b7..7c3c0f39b 100644 --- a/ui/app/pages/create-account/connect-hardware/connect-screen.js +++ b/ui/app/pages/create-account/connect-hardware/connect-screen.js @@ -30,7 +30,7 @@ class ConnectScreen extends Component { className={classnames('hw-connect__btn', { 'selected': this.state.selectedDevice === 'trezor', })} - onClick={_ => this.setState({selectedDevice: 'trezor'})} + onClick={_ => this.setState({ selectedDevice: 'trezor' })} > this.setState({selectedDevice: 'ledger'})} + onClick={_ => this.setState({ selectedDevice: 'ledger' })} > ) } @@ -136,7 +136,7 @@ class ConnectScreen extends Component { scrollToTutorial = () => { if (this.referenceNode) { - this.referenceNode.scrollIntoView({behavior: 'smooth'}) + this.referenceNode.scrollIntoView({ behavior: 'smooth' }) } } @@ -153,19 +153,19 @@ class ConnectScreen extends Component { const steps = [ { asset: 'hardware-wallet-step-1', - dimensions: {width: '225px', height: '75px'}, + dimensions: { width: '225px', height: '75px' }, title: this.context.t('step1HardwareWallet'), message: this.context.t('step1HardwareWalletMsg'), }, { asset: 'hardware-wallet-step-2', - dimensions: {width: '300px', height: '100px'}, + dimensions: { width: '300px', height: '100px' }, title: this.context.t('step2HardwareWallet'), message: this.context.t('step2HardwareWalletMsg'), }, { asset: 'hardware-wallet-step-3', - dimensions: {width: '120px', height: '90px'}, + dimensions: { width: '120px', height: '90px' }, title: this.context.t('step3HardwareWallet'), message: this.context.t('step3HardwareWalletMsg'), }, diff --git a/ui/app/pages/create-account/connect-hardware/index.js b/ui/app/pages/create-account/connect-hardware/index.js index 351699e8a..a1e1b62ce 100644 --- a/ui/app/pages/create-account/connect-hardware/index.js +++ b/ui/app/pages/create-account/connect-hardware/index.js @@ -29,7 +29,7 @@ class ConnectHardwareForm extends Component { a.balance = balanceValue ? formatBalance(balanceValue, 6) : '...' return a }) - this.setState({accounts: newAccounts}) + this.setState({ accounts: newAccounts }) } @@ -41,7 +41,7 @@ class ConnectHardwareForm extends Component { ['trezor', 'ledger'].forEach(async device => { const unlocked = await this.props.checkHardwareStatus(device, this.props.defaultHdPaths[device]) if (unlocked) { - this.setState({unlocked: true}) + this.setState({ unlocked: true }) this.getPage(device, 0, this.props.defaultHdPaths[device]) } }) @@ -57,16 +57,16 @@ class ConnectHardwareForm extends Component { } onPathChange = (path) => { - this.props.setHardwareWalletDefaultHdPath({device: this.state.device, path}) + this.props.setHardwareWalletDefaultHdPath({ device: this.state.device, path }) this.getPage(this.state.device, 0, path) } onAccountChange = (account) => { - this.setState({selectedAccount: account.toString(), error: null}) + this.setState({ selectedAccount: account.toString(), error: null }) } onAccountRestriction = () => { - this.setState({error: this.context.t('ledgerAccountRestriction') }) + this.setState({ error: this.context.t('ledgerAccountRestriction') }) } showTemporaryAlert () { @@ -117,7 +117,7 @@ class ConnectHardwareForm extends Component { .catch(e => { const errorMessage = e.message if (errorMessage === 'Window blocked') { - this.setState({ browserSupported: false, error: null}) + this.setState({ browserSupported: false, error: null }) } else if (errorMessage !== 'Window closed' && errorMessage !== 'Popup closed') { this.setState({ error: errorMessage }) } @@ -266,8 +266,8 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => { return { - setHardwareWalletDefaultHdPath: ({device, path}) => { - return dispatch(actions.setHardwareWalletDefaultHdPath({device, path})) + setHardwareWalletDefaultHdPath: ({ device, path }) => { + return dispatch(actions.setHardwareWalletDefaultHdPath({ device, path })) }, connectHardware: (deviceName, page, hdPath) => { return dispatch(actions.connectHardware(deviceName, page, hdPath)) diff --git a/ui/app/pages/create-account/create-account.component.js b/ui/app/pages/create-account/create-account.component.js index 1f8bc0cc5..90c9105b7 100644 --- a/ui/app/pages/create-account/create-account.component.js +++ b/ui/app/pages/create-account/create-account.component.js @@ -13,7 +13,7 @@ import { export default class CreateAccountPage extends Component { renderTabs () { - const { history, location: { pathname }} = this.props + const { history, location: { pathname } } = this.props const getClassNames = path => classnames('new-account__tabs__tab', { 'new-account__tabs__selected': matchPath(pathname, { path, diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js index 53d4614ad..c93588875 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js @@ -1,4 +1,4 @@ -import {validateMnemonic} from 'bip39' +import { validateMnemonic } from 'bip39' import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import TextField from '../../../../components/ui/text-field' @@ -175,7 +175,7 @@ export default class ImportWithSeedPhrase extends PureComponent { return !passwordError && !confirmPasswordError && !seedPhraseError } - onTermsKeyPress = ({key}) => { + onTermsKeyPress = ({ key }) => { if (key === ' ' || key === 'Enter') { this.toggleTermsCheck() } diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js index 7960d17b2..f6a2ad8ca 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js @@ -29,7 +29,7 @@ describe('ImportWithSeedPhrase Component', () => { onSubmit: sinon.spy(), }) - const {parseSeedPhrase} = root.instance() + const { parseSeedPhrase } = root.instance() assert.deepEqual(parseSeedPhrase('foo bar baz'), 'foo bar baz') }) @@ -39,7 +39,7 @@ describe('ImportWithSeedPhrase Component', () => { onSubmit: sinon.spy(), }) - const {parseSeedPhrase} = root.instance() + const { parseSeedPhrase } = root.instance() assert.deepEqual(parseSeedPhrase(' foo bar baz '), 'foo bar baz') }) @@ -49,7 +49,7 @@ describe('ImportWithSeedPhrase Component', () => { onSubmit: sinon.spy(), }) - const {parseSeedPhrase} = root.instance() + const { parseSeedPhrase } = root.instance() assert.deepEqual(parseSeedPhrase(' '), '') }) @@ -59,7 +59,7 @@ describe('ImportWithSeedPhrase Component', () => { onSubmit: sinon.spy(), }) - const {parseSeedPhrase} = root.instance() + const { parseSeedPhrase } = root.instance() assert.deepEqual(parseSeedPhrase('$'), '') }) @@ -69,7 +69,7 @@ describe('ImportWithSeedPhrase Component', () => { onSubmit: sinon.spy(), }) - const {parseSeedPhrase} = root.instance() + const { parseSeedPhrase } = root.instance() assert.deepEqual(parseSeedPhrase(undefined), '') assert.deepEqual(parseSeedPhrase(null), '') diff --git a/ui/app/pages/first-time-flow/create-password/new-account/new-account.component.js b/ui/app/pages/first-time-flow/create-password/new-account/new-account.component.js index a8445474b..2da9d62e0 100644 --- a/ui/app/pages/first-time-flow/create-password/new-account/new-account.component.js +++ b/ui/app/pages/first-time-flow/create-password/new-account/new-account.component.js @@ -128,7 +128,7 @@ export default class NewAccount extends PureComponent { })) } - onTermsKeyPress = ({key}) => { + onTermsKeyPress = ({ key }) => { if (key === ' ' || key === 'Enter') { this.toggleTermsCheck() } diff --git a/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js index ae38757d9..329b472a9 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js @@ -10,7 +10,7 @@ import { DEFAULT_ROUTE, } from '../../../helpers/constants/routes' import HTML5Backend from 'react-dnd-html5-backend' -import {DragDropContextProvider} from 'react-dnd' +import { DragDropContextProvider } from 'react-dnd' import MetaFoxLogo from '../../../components/ui/metafox-logo' export default class SeedPhrase extends PureComponent { diff --git a/ui/app/pages/keychains/restore-vault.js b/ui/app/pages/keychains/restore-vault.js index 93c2975bb..8f7f399b0 100644 --- a/ui/app/pages/keychains/restore-vault.js +++ b/ui/app/pages/keychains/restore-vault.js @@ -1,6 +1,6 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' -import {connect} from 'react-redux' +import { connect } from 'react-redux' import { createNewVaultAndRestore, unMarkPasswordForgotten, diff --git a/ui/app/pages/mobile-sync/mobile-sync.component.js b/ui/app/pages/mobile-sync/mobile-sync.component.js index 9510afa80..85aad062a 100644 --- a/ui/app/pages/mobile-sync/mobile-sync.component.js +++ b/ui/app/pages/mobile-sync/mobile-sync.component.js @@ -72,7 +72,7 @@ export default class MobileSyncPage extends Component { generateCipherKeyAndChannelName () { this.cipherKey = `${this.props.selectedAddress.substr(-4)}-${PubNub.generateUUID()}` this.channelName = `mm-${PubNub.generateUUID()}` - this.setState({cipherKey: this.cipherKey, channelName: this.channelName}) + this.setState({ cipherKey: this.cipherKey, channelName: this.channelName }) } initWithCipherKeyAndChannelName (cipherKey, channelName) { @@ -93,7 +93,7 @@ export default class MobileSyncPage extends Component { this.pubnubListener = { message: (data) => { - const {channel, message} = data + const { channel, message } = data // handle message if (channel !== this.channelName || !message) { return false @@ -108,7 +108,7 @@ export default class MobileSyncPage extends Component { this.initWebsockets() } else if (message.event === 'end-sync') { this.disconnectWebsockets() - this.setState({syncing: false, completed: true}) + this.setState({ syncing: false, completed: true }) } }, } @@ -171,7 +171,7 @@ export default class MobileSyncPage extends Component { return false } this.syncing = true - this.setState({syncing: true}) + this.setState({ syncing: true }) const { accounts, network, preferences, transactions } = await this.props.fetchInfoToSync() @@ -194,7 +194,7 @@ export default class MobileSyncPage extends Component { } } catch (e) { this.props.displayWarning('Sync failed :(') - this.setState({syncing: false}) + this.setState({ syncing: false }) this.syncing = false this.notifyError(e.toString()) } diff --git a/ui/app/pages/routes/index.js b/ui/app/pages/routes/index.js index b2a2ced68..fe27dfb5b 100644 --- a/ui/app/pages/routes/index.js +++ b/ui/app/pages/routes/index.js @@ -240,7 +240,7 @@ class Routes extends Component { return (
setMouseUserState(true)} onKeyDown={e => { diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js b/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js index a2e6b49db..40382cdd5 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js +++ b/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js @@ -2,11 +2,11 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import Fuse from 'fuse.js' import Identicon from '../../../../components/ui/identicon' -import {isValidAddress} from '../../../../helpers/utils/util' +import { isValidAddress } from '../../../../helpers/utils/util' import Dialog from '../../../../components/ui/dialog' import ContactList from '../../../../components/app/contact-list' import RecipientGroup from '../../../../components/app/contact-list/recipient-group/recipient-group.component' -import {ellipsify} from '../../send.utils' +import { ellipsify } from '../../send.utils' export default class AddRecipient extends Component { diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js index a4b5c8810..4f342d857 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js +++ b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js @@ -2,7 +2,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import c from 'classnames' import { isValidENSAddress, isValidAddress, isValidAddressHead } from '../../../../helpers/utils/util' -import {ellipsify} from '../../send.utils' +import { ellipsify } from '../../send.utils' import debounce from 'debounce' import copyToClipboard from 'copy-to-clipboard/index' diff --git a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js index 182504c5d..5549c2503 100644 --- a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js +++ b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js @@ -56,24 +56,24 @@ describe('add-recipient utils', () => { }) it('should return null if to is truthy but part of state tokens', () => { - assert.deepEqual(getToErrorObject('0xabc123', undefined, false, [{'address': '0xabc123'}], {'address': '0xabc123'}), { + assert.deepEqual(getToErrorObject('0xabc123', undefined, false, [{ 'address': '0xabc123' }], { 'address': '0xabc123' }), { to: null, }) }) it('should null if to is truthy part of tokens but selectedToken falsy', () => { - assert.deepEqual(getToErrorObject('0xabc123', undefined, false, [{'address': '0xabc123'}]), { + assert.deepEqual(getToErrorObject('0xabc123', undefined, false, [{ 'address': '0xabc123' }]), { to: null, }) }) it('should return null if to is truthy but part of contract metadata', () => { - assert.deepEqual(getToErrorObject('0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', undefined, false, [{'address': '0xabc123'}], {'address': '0xabc123'}), { + assert.deepEqual(getToErrorObject('0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', undefined, false, [{ 'address': '0xabc123' }], { 'address': '0xabc123' }), { to: null, }) }) it('should null if to is truthy part of contract metadata but selectedToken falsy', () => { - assert.deepEqual(getToErrorObject('0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', undefined, false, [{'address': '0xabc123'}], {'address': '0xabc123'}), { + assert.deepEqual(getToErrorObject('0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', undefined, false, [{ 'address': '0xabc123' }], { 'address': '0xabc123' }), { to: null, }) }) @@ -81,24 +81,24 @@ describe('add-recipient utils', () => { describe('getToWarningObject()', () => { it('should return a known address recipient if to is truthy but part of state tokens', () => { - assert.deepEqual(getToWarningObject('0xabc123', undefined, [{'address': '0xabc123'}], {'address': '0xabc123'}), { + assert.deepEqual(getToWarningObject('0xabc123', undefined, [{ 'address': '0xabc123' }], { 'address': '0xabc123' }), { to: KNOWN_RECIPIENT_ADDRESS_ERROR, }) }) it('should null if to is truthy part of tokens but selectedToken falsy', () => { - assert.deepEqual(getToWarningObject('0xabc123', undefined, [{'address': '0xabc123'}]), { + assert.deepEqual(getToWarningObject('0xabc123', undefined, [{ 'address': '0xabc123' }]), { to: null, }) }) it('should return a known address recipient if to is truthy but part of contract metadata', () => { - assert.deepEqual(getToWarningObject('0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', undefined, [{'address': '0xabc123'}], {'address': '0xabc123'}), { + assert.deepEqual(getToWarningObject('0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', undefined, [{ 'address': '0xabc123' }], { 'address': '0xabc123' }), { to: KNOWN_RECIPIENT_ADDRESS_ERROR, }) }) it('should null if to is truthy part of contract metadata but selectedToken falsy', () => { - assert.deepEqual(getToWarningObject('0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', undefined, [{'address': '0xabc123'}], {'address': '0xabc123'}), { + assert.deepEqual(getToWarningObject('0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', undefined, [{ 'address': '0xabc123' }], { 'address': '0xabc123' }), { to: KNOWN_RECIPIENT_ADDRESS_ERROR, }) }) diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-container.test.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-container.test.js index dcee8fda0..0307388d7 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-container.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-container.test.js @@ -29,7 +29,7 @@ proxyquire('../amount-max-button.container.js', { }, './amount-max-button.selectors.js': { getMaxModeOn: (s) => `mockMaxModeOn:${s}` }, './amount-max-button.utils.js': { calcMaxAmount: (mockObj) => mockObj.val + 1 }, - '../../../../../selectors/custom-gas': { getBasicGasEstimateLoadingStatus: (s) => `mockButtonDataLoading:${s}`}, + '../../../../../selectors/custom-gas': { getBasicGasEstimateLoadingStatus: (s) => `mockButtonDataLoading:${s}` }, '../../../../../store/actions': actionSpies, '../../../../../ducks/send/send.duck': duckActionSpies, }) diff --git a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js index c0b604505..d0a44d0ae 100644 --- a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js +++ b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js @@ -4,7 +4,7 @@ import SendRowWrapper from '../send-row-wrapper' import Identicon from '../../../../components/ui/identicon/identicon.component' import TokenBalance from '../../../../components/ui/token-balance' import UserPreferencedCurrencyDisplay from '../../../../components/app/user-preferenced-currency-display' -import {PRIMARY} from '../../../../helpers/constants/common' +import { PRIMARY } from '../../../../helpers/constants/common' export default class SendAssetRow extends Component { static propTypes = { diff --git a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js index 57b62fba1..1722e2a47 100644 --- a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js +++ b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux' import SendAssetRow from './send-asset-row.component' -import {getMetaMaskAccounts} from '../../../../selectors/selectors' +import { getMetaMaskAccounts } from '../../../../selectors/selectors' import { setSelectedToken } from '../../../../store/actions' function mapStateToProps (state) { diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js index 473dbb0b1..b69ddba0f 100644 --- a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js +++ b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js @@ -1,4 +1,4 @@ -import React, {Component} from 'react' +import React, { Component } from 'react' import PropTypes from 'prop-types' import UserPreferencedCurrencyDisplay from '../../../../../components/app/user-preferenced-currency-display' import { PRIMARY, SECONDARY } from '../../../../../helpers/constants/common' diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/test/gas-fee-display.component.test.js b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/test/gas-fee-display.component.test.js index 1dd34a25a..3ff2ddec2 100644 --- a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/test/gas-fee-display.component.test.js +++ b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/test/gas-fee-display.component.test.js @@ -1,6 +1,6 @@ import React from 'react' import assert from 'assert' -import {shallow} from 'enzyme' +import { shallow } from 'enzyme' import GasFeeDisplay from '../gas-fee-display.component' import UserPreferencedCurrencyDisplay from '../../../../../../components/app/user-preferenced-currency-display' import sinon from 'sinon' @@ -24,7 +24,7 @@ describe('GasFeeDisplay Component', function () { showGasButtonGroup={propsMethodSpies.showCustomizeGasModal} onReset={propsMethodSpies.onReset} /> - ), {context: {t: str => str + '_t'}}) + ), { context: { t: str => str + '_t' } }) }) afterEach(() => { diff --git a/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js b/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js index 152c59db9..ce9bd3a22 100644 --- a/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js +++ b/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js @@ -15,15 +15,15 @@ export default class SendHexDataRow extends Component { }; onInput = (event) => { - const {updateSendHexData, updateGas} = this.props + const { updateSendHexData, updateGas } = this.props const data = event.target.value.replace(/\n/g, '') || null updateSendHexData(data) updateGas({ data }) } render () { - const {inError} = this.props - const {t} = this.context + const { inError } = this.props + const { t } = this.context return ( {this.context.t(errorMessage)}
+ ?
{this.context.t(errorMessage)}
: null ) } diff --git a/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js b/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js index 5f575a60e..c992d97e2 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js @@ -43,7 +43,7 @@ describe('SendContent Component', function () { }) it('should render a SendRowErrorMessage with and errorType props if showError is true', () => { - wrapper.setProps({showError: true}) + wrapper.setProps({ showError: true }) assert.equal(wrapper.find(SendRowErrorMessage).length, 1) const expectedSendRowErrorMessage = wrapper.find('.send-v2__form-row > .send-v2__form-label').childAt(1) diff --git a/ui/app/pages/send/send-footer/send-footer.component.js b/ui/app/pages/send/send-footer/send-footer.component.js index f637fb8c7..73a3d3256 100644 --- a/ui/app/pages/send/send-footer/send-footer.component.js +++ b/ui/app/pages/send/send-footer/send-footer.component.js @@ -47,7 +47,7 @@ export default class SendFooter extends Component { amount, data, editingTransactionId, - from: {address: from}, + from: { address: from }, gasLimit: gas, gasPrice, selectedToken, diff --git a/ui/app/pages/send/send-footer/tests/send-footer-selectors.test.js b/ui/app/pages/send/send-footer/tests/send-footer-selectors.test.js index 8de032f57..36f3a809f 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-selectors.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-selectors.test.js @@ -13,11 +13,11 @@ describe('send-footer selectors', () => { describe('getTitleKey()', () => { it('should return true if any of the values of the object returned by getSendErrors are truthy', () => { - assert.equal(isSendFormInError({ errors: { a: 'abc', b: false} }), true) + assert.equal(isSendFormInError({ errors: { a: 'abc', b: false } }), true) }) it('should return false if all of the values of the object returned by getSendErrors are falsy', () => { - assert.equal(isSendFormInError({ errors: { a: false, b: null} }), false) + assert.equal(isSendFormInError({ errors: { a: false, b: null } }), false) }) }) diff --git a/ui/app/pages/send/send.container.js b/ui/app/pages/send/send.container.js index 2350712f3..cb3261403 100644 --- a/ui/app/pages/send/send.container.js +++ b/ui/app/pages/send/send.container.js @@ -127,7 +127,7 @@ function mapDispatchToProps (dispatch) { updateSendEnsResolutionError: (message) => dispatch(updateSendEnsResolutionError(message)), updateToNicknameIfNecessary: (to, toNickname, addressBook) => { if (isValidENSAddress(toNickname)) { - const addressBookEntry = addressBook.find(({ address}) => to === address) || {} + const addressBookEntry = addressBook.find(({ address }) => to === address) || {} if (!addressBookEntry.name !== toNickname) { dispatch(updateSendTo(to, addressBookEntry.name || '')) } diff --git a/ui/app/pages/send/tests/send-component.test.js b/ui/app/pages/send/tests/send-component.test.js index bac01cf25..6e6fbe1a5 100644 --- a/ui/app/pages/send/tests/send-component.test.js +++ b/ui/app/pages/send/tests/send-component.test.js @@ -53,7 +53,7 @@ describe('Send Component', function () { gasLimit="mockGasLimit" gasPrice="mockGasPrice" gasTotal="mockGasTotal" - history={{ mockProp: 'history-abc'}} + history={{ mockProp: 'history-abc' }} network="3" primaryCurrency="mockPrimaryCurrency" recentBlocks={['mockBlock']} @@ -228,7 +228,7 @@ describe('Send Component', function () { it('should call updateSendErrors with the expected params if selectedToken is truthy', () => { propsMethodSpies.updateSendErrors.resetHistory() - wrapper.setProps({ selectedToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' }}) + wrapper.setProps({ selectedToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' } }) wrapper.instance().componentDidUpdate({ from: { balance: 'balanceChanged', diff --git a/ui/app/pages/send/tests/send-container.test.js b/ui/app/pages/send/tests/send-container.test.js index f4142bc2d..5afec0148 100644 --- a/ui/app/pages/send/tests/send-container.test.js +++ b/ui/app/pages/send/tests/send-container.test.js @@ -135,7 +135,7 @@ describe('send container', () => { it('should dispatch an updateGasData action when editingTransactionId is falsy', () => { const { gasPrice, selectedAddress, selectedToken, recentBlocks, blockGasLimit, to, value, data } = mockProps mapDispatchToPropsObject.updateAndSetGasLimit( - Object.assign({}, mockProps, {editingTransactionId: false}) + Object.assign({}, mockProps, { editingTransactionId: false }) ) assert(dispatchSpy.calledOnce) assert.deepEqual( @@ -149,7 +149,7 @@ describe('send container', () => { const mockProps = { address: '0x10', tokenContract: '0x00a', - selectedToken: {address: '0x1'}, + selectedToken: { address: '0x1' }, } it('should dispatch an action', () => { diff --git a/ui/app/pages/send/tests/send-selectors-test-data.js b/ui/app/pages/send/tests/send-selectors-test-data.js index de078c03e..91b96dd98 100644 --- a/ui/app/pages/send/tests/send-selectors-test-data.js +++ b/ui/app/pages/send/tests/send-selectors-test-data.js @@ -2,7 +2,7 @@ module.exports = { 'metamask': { 'isInitialized': true, 'isUnlocked': true, - 'featureFlags': {'sendHexData': true}, + 'featureFlags': { 'sendHexData': true }, 'rpcTarget': 'https://rawtestrpc.metamask.io/', 'identities': { '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825': { diff --git a/ui/app/pages/send/tests/send-utils.test.js b/ui/app/pages/send/tests/send-utils.test.js index 9f6a01ad5..f6556de06 100644 --- a/ui/app/pages/send/tests/send-utils.test.js +++ b/ui/app/pages/send/tests/send-utils.test.js @@ -122,12 +122,12 @@ describe('send utils', () => { describe('generateTokenTransferData()', () => { it('should return undefined if not passed a selected token', () => { - assert.equal(generateTokenTransferData({ toAddress: 'mockAddress', amount: '0xa', selectedToken: false}), undefined) + assert.equal(generateTokenTransferData({ toAddress: 'mockAddress', amount: '0xa', selectedToken: false }), undefined) }) it('should call abi.rawEncode with the correct params', () => { stubs.rawEncode.resetHistory() - generateTokenTransferData({ toAddress: 'mockAddress', amount: 'ab', selectedToken: true}) + generateTokenTransferData({ toAddress: 'mockAddress', amount: 'ab', selectedToken: true }) assert.deepEqual( stubs.rawEncode.getCall(0).args, [['address', 'uint256'], ['mockAddress', '0xab']] @@ -136,7 +136,7 @@ describe('send utils', () => { it('should return encoded token transfer data', () => { assert.equal( - generateTokenTransferData({ toAddress: 'mockAddress', amount: '0xa', selectedToken: true}), + generateTokenTransferData({ toAddress: 'mockAddress', amount: '0xa', selectedToken: true }), '0xa9059cbb104c' ) }) @@ -307,7 +307,7 @@ describe('send utils', () => { selectedAddress: 'mockAddress', to: '0xisContract', estimateGasMethod: sinon.stub().callsFake( - ({to}, cb) => { + ({ to }, cb) => { const err = typeof to === 'string' && to.match(/willFailBecauseOf:/) ? new Error(to.match(/:(.+)$/)[1]) : null @@ -374,11 +374,11 @@ describe('send utils', () => { it('should call ethQuery.estimateGas without a recipient if the recipient is empty and data passed', async () => { const data = 'mockData' const to = '' - const result = await estimateGas({...baseMockParams, data, to}) + const result = await estimateGas({ ...baseMockParams, data, to }) assert.equal(baseMockParams.estimateGasMethod.callCount, 1) assert.deepEqual( baseMockParams.estimateGasMethod.getCall(0).args[0], - { gasPrice: undefined, value: '0xff', data, from: baseExpectedCall.from, gas: baseExpectedCall.gas}, + { gasPrice: undefined, value: '0xff', data, from: baseExpectedCall.from, gas: baseExpectedCall.gas }, ) assert.equal(result, '0xabc16') }) diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.container.js b/ui/app/pages/settings/advanced-tab/advanced-tab.container.js index 8b64e864f..876b1fd40 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.container.js +++ b/ui/app/pages/settings/advanced-tab/advanced-tab.container.js @@ -13,7 +13,7 @@ import { turnThreeBoxSyncingOnAndInitialize, setUseNonceField, } from '../../../store/actions' -import {preferencesSelector} from '../../../selectors/selectors' +import { preferencesSelector } from '../../../selectors/selectors' export const mapStateToProps = state => { const { appState: { warning }, metamask } = state diff --git a/ui/app/selectors/selectors.js b/ui/app/selectors/selectors.js index bcd21d107..5903bbf27 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/app/selectors/selectors.js @@ -179,7 +179,7 @@ export function getAddressBookEntryName (state, address) { export function getDaiV1Token (state) { const OLD_DAI_CONTRACT_ADDRESS = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359' const tokens = state.metamask.tokens || [] - return tokens.find(({address}) => checksumAddress(address) === OLD_DAI_CONTRACT_ADDRESS) + return tokens.find(({ address }) => checksumAddress(address) === OLD_DAI_CONTRACT_ADDRESS) } export function accountsWithSendEtherInfoSelector (state) { diff --git a/ui/app/selectors/tests/selectors-test-data.js b/ui/app/selectors/tests/selectors-test-data.js index 12828dd05..4e0a06e3f 100644 --- a/ui/app/selectors/tests/selectors-test-data.js +++ b/ui/app/selectors/tests/selectors-test-data.js @@ -2,7 +2,7 @@ module.exports = { 'metamask': { 'isInitialized': true, 'isUnlocked': true, - 'featureFlags': {'sendHexData': true}, + 'featureFlags': { 'sendHexData': true }, 'rpcTarget': 'https://rawtestrpc.metamask.io/', 'identities': { '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825': { diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index a09548f0f..93480bca8 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -731,7 +731,7 @@ function addNewAccount () { const oldIdentities = getState().metamask.identities dispatch(actions.showLoadingIndication()) return new Promise((resolve, reject) => { - background.addNewAccount((err, { identities: newIdentities}) => { + background.addNewAccount((err, { identities: newIdentities }) => { if (err) { dispatch(actions.displayWarning(err.message)) return reject(err) @@ -1378,7 +1378,7 @@ function cancelTx (txData) { function cancelTxs (txDataList) { return async (dispatch) => { dispatch(actions.showLoadingIndication()) - const txIds = txDataList.map(({id}) => id) + const txIds = txDataList.map(({ id }) => id) const cancellations = txIds.map((id) => new Promise((resolve, reject) => { background.cancelTransaction(id, (err) => { if (err) { @@ -1648,7 +1648,7 @@ function showAccountsPage () { } } -function showConfTxPage ({transForward = true, id}) { +function showConfTxPage ({ transForward = true, id }) { return { type: actions.SHOW_CONF_TX_PAGE, transForward, @@ -1774,7 +1774,7 @@ function removeSuggestedTokens () { }) }) .then(() => updateMetamaskStateFromBackground()) - .then(suggestedTokens => dispatch(actions.updateMetamaskState({...suggestedTokens}))) + .then(suggestedTokens => dispatch(actions.updateMetamaskState({ ...suggestedTokens }))) } } @@ -2138,7 +2138,7 @@ function showLoadingIndication (message) { function setHardwareWalletDefaultHdPath ({ device, path }) { return { type: actions.SET_HARDWARE_WALLET_DEFAULT_HD_PATH, - value: {device, path}, + value: { device, path }, } } @@ -2298,7 +2298,7 @@ function pairUpdate (coin) { return (dispatch) => { dispatch(actions.showSubLoadingIndication()) dispatch(actions.hideWarning()) - shapeShiftRequest('marketinfo', {pair: `${coin.toLowerCase()}_eth`}, (mktResponse) => { + shapeShiftRequest('marketinfo', { pair: `${coin.toLowerCase()}_eth` }, (mktResponse) => { dispatch(actions.hideSubLoadingIndication()) if (mktResponse.error) { return dispatch(actions.displayWarning(mktResponse.error)) @@ -2317,7 +2317,7 @@ function shapeShiftSubview () { const pair = 'btc_eth' return (dispatch) => { dispatch(actions.showSubLoadingIndication()) - shapeShiftRequest('marketinfo', {pair}, (mktResponse) => { + shapeShiftRequest('marketinfo', { pair }, (mktResponse) => { shapeShiftRequest('getcoins', {}, (response) => { dispatch(actions.hideSubLoadingIndication()) if (mktResponse.error) { @@ -2338,7 +2338,7 @@ function shapeShiftSubview () { function coinShiftRquest (data, marketData) { return (dispatch) => { dispatch(actions.showLoadingIndication()) - shapeShiftRequest('shift', { method: 'POST', data}, (response) => { + shapeShiftRequest('shift', { method: 'POST', data }, (response) => { dispatch(actions.hideLoadingIndication()) if (response.error) { return dispatch(actions.displayWarning(response.error)) @@ -2354,7 +2354,7 @@ function coinShiftRquest (data, marketData) { function buyWithShapeShift (data) { return () => new Promise((resolve, reject) => { - shapeShiftRequest('shift', { method: 'POST', data}, (response) => { + shapeShiftRequest('shift', { method: 'POST', data }, (response) => { if (response.error) { return reject(response.error) } @@ -2376,7 +2376,7 @@ function showQrView (data, message) { function reshowQrCode (data, coin) { return (dispatch) => { dispatch(actions.showLoadingIndication()) - shapeShiftRequest('marketinfo', {pair: `${coin.toLowerCase()}_eth`}, (mktResponse) => { + shapeShiftRequest('marketinfo', { pair: `${coin.toLowerCase()}_eth` }, (mktResponse) => { if (mktResponse.error) { return dispatch(actions.displayWarning(mktResponse.error)) } @@ -2406,7 +2406,7 @@ function shapeShiftRequest (query, options = {}, cb) { return queryResponse } catch (e) { if (cb) { - cb({error: e}) + cb({ error: e }) } return e } diff --git a/ui/index.js b/ui/index.js index 6f7a43963..028aa3d05 100644 --- a/ui/index.js +++ b/ui/index.js @@ -13,7 +13,7 @@ module.exports = launchMetamaskUi log.setLevel(global.METAMASK_DEBUG ? 'debug' : 'warn') function launchMetamaskUi (opts, cb) { - const {backgroundConnection} = opts + const { backgroundConnection } = opts actions._setBackgroundConnection(backgroundConnection) // check if we are unlocked first backgroundConnection.getState(function (err, metamaskState) { diff --git a/ui/lib/feature-toggle-utils.js b/ui/lib/feature-toggle-utils.js index 6d4e461ca..ed0844d2e 100644 --- a/ui/lib/feature-toggle-utils.js +++ b/ui/lib/feature-toggle-utils.js @@ -1,7 +1,7 @@ function checkFeatureToggle (name) { const queryPairMap = window.location.search.substr(1).split('&') .map(pair => pair.split('=')) - .reduce((pairs, [key, value]) => ({...pairs, [key]: value }), {}) + .reduce((pairs, [key, value]) => ({ ...pairs, [key]: value }), {}) const featureToggles = queryPairMap['ft'] ? queryPairMap['ft'].split(',') : [] return Boolean(featureToggles.find(ft => ft === name)) } diff --git a/ui/lib/webcam-utils.js b/ui/lib/webcam-utils.js index bd7a5a0e0..0a6fe27f7 100644 --- a/ui/lib/webcam-utils.js +++ b/ui/lib/webcam-utils.js @@ -23,11 +23,11 @@ class WebcamUtils { environmentReady, }) } else { - reject({type: 'NO_WEBCAM_FOUND'}) + reject({ type: 'NO_WEBCAM_FOUND' }) } }) } catch (e) { - reject({type: 'UNKNOWN_ERROR'}) + reject({ type: 'UNKNOWN_ERROR' }) } }) } From b8e3957542f1805eb762a2acb62acf31c74e2dce Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 3 Dec 2019 17:34:16 -0330 Subject: [PATCH 015/689] Remove unneeded store connections (#7625) --- ui/app/components/ui/copyButton.js | 3 +-- ui/app/pages/create-account/import-account/index.js | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/ui/app/components/ui/copyButton.js b/ui/app/components/ui/copyButton.js index d235fea04..14b54517b 100644 --- a/ui/app/components/ui/copyButton.js +++ b/ui/app/components/ui/copyButton.js @@ -1,6 +1,5 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' -import { connect } from 'react-redux' const copyToClipboard = require('copy-to-clipboard') const Tooltip = require('./tooltip') @@ -63,4 +62,4 @@ class CopyButton extends Component { } } -module.exports = connect()(CopyButton) +module.exports = CopyButton diff --git a/ui/app/pages/create-account/import-account/index.js b/ui/app/pages/create-account/import-account/index.js index 5ef837715..2d66c9601 100644 --- a/ui/app/pages/create-account/import-account/index.js +++ b/ui/app/pages/create-account/import-account/index.js @@ -1,7 +1,6 @@ import React, { Component } from 'react' const inherits = require('util').inherits const PropTypes = require('prop-types') -const connect = require('react-redux').connect import Select from 'react-select' // Subviews @@ -13,7 +12,7 @@ AccountImportSubview.contextTypes = { t: PropTypes.func, } -module.exports = connect()(AccountImportSubview) +module.exports = AccountImportSubview inherits(AccountImportSubview, Component) From 4ec92ceed3c8472833b5a58e9cb9121ca41b1898 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 3 Dec 2019 17:44:19 -0330 Subject: [PATCH 016/689] Fix SimpleDropdown event bubbling (#7627) --- ui/app/components/app/dropdowns/simple-dropdown.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/app/components/app/dropdowns/simple-dropdown.js b/ui/app/components/app/dropdowns/simple-dropdown.js index 081674397..96c31ac82 100644 --- a/ui/app/components/app/dropdowns/simple-dropdown.js +++ b/ui/app/components/app/dropdowns/simple-dropdown.js @@ -53,7 +53,8 @@ class SimpleDropdown extends Component { 'simple-dropdown__option--selected': option.value === selectedOption, })} key={option.value} - onClick={() => { + onClick={(event) => { + event.stopPropagation() if (option.value !== selectedOption) { onSelect(option.value) } From 31a4788bf91312722d5242468e3e087df6f9338f Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 3 Dec 2019 19:39:26 -0400 Subject: [PATCH 017/689] Fix private key export (#7632) There were a few older actions that were written such that they assumed `this` referred to the `actions` object. That assumption no longer held as of #7561. These actions have been updated to refer directly to the actions object instead. --- ui/app/store/actions.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index a09548f0f..d81769f01 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -1955,7 +1955,7 @@ function editRpc (oldRpc, newRpc, chainId, ticker = 'ETH', nickname, rpcPrefs) { background.delCustomRpc(oldRpc, (err) => { if (err) { log.error(err) - return dispatch(self.displayWarning('Had a problem removing network!')) + return dispatch(actions.displayWarning('Had a problem removing network!')) } dispatch(actions.setSelectedToken()) background.updateAndSetCustomRpc(newRpc, chainId, ticker, nickname || newRpc, rpcPrefs, (err) => { @@ -1992,7 +1992,7 @@ function delRpcTarget (oldRpc) { background.delCustomRpc(oldRpc, (err) => { if (err) { log.error(err) - dispatch(self.displayWarning('Had a problem removing network!')) + dispatch(actions.displayWarning('Had a problem removing network!')) return reject(err) } dispatch(actions.setSelectedToken()) @@ -2180,32 +2180,29 @@ function requestExportAccount () { } function exportAccount (password, address) { - const self = this - return function (dispatch) { - dispatch(self.showLoadingIndication()) + dispatch(actions.showLoadingIndication()) log.debug(`background.submitPassword`) return new Promise((resolve, reject) => { background.submitPassword(password, function (err) { if (err) { log.error('Error in submiting password.') - dispatch(self.hideLoadingIndication()) - dispatch(self.displayWarning('Incorrect Password.')) + dispatch(actions.hideLoadingIndication()) + dispatch(actions.displayWarning('Incorrect Password.')) return reject(err) } log.debug(`background.exportAccount`) return background.exportAccount(address, function (err, result) { - dispatch(self.hideLoadingIndication()) + dispatch(actions.hideLoadingIndication()) if (err) { log.error(err) - dispatch(self.displayWarning('Had a problem exporting the account.')) + dispatch(actions.displayWarning('Had a problem exporting the account.')) return reject(err) } - // dispatch(self.exportAccountComplete()) - dispatch(self.showPrivateKey(result)) + dispatch(actions.showPrivateKey(result)) return resolve(result) }) From bc67d1eecabb123bf21445e604780d2454d52d3e Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Tue, 3 Dec 2019 17:12:14 -0800 Subject: [PATCH 018/689] Revert "Update Wyre ETH purchase url" (#7631) * Revert "Update Wyre buy ETH URL (#7482)" This reverts commit 015ba83c6e69dcca676d626f70ef887a38ce01b9. * Change test description from coinbase to wyre --- app/scripts/lib/buy-eth-url.js | 2 +- test/unit/app/buy-eth-url.spec.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/scripts/lib/buy-eth-url.js b/app/scripts/lib/buy-eth-url.js index 6892364ca..153a266fa 100644 --- a/app/scripts/lib/buy-eth-url.js +++ b/app/scripts/lib/buy-eth-url.js @@ -19,7 +19,7 @@ function getBuyEthUrl ({ network, amount, address, service }) { switch (service) { case 'wyre': - return `https://pay.sendwyre.com/?dest=ethereum:${address}&destCurrency=ETH&accountId=AC-7AG3W4XH4N2` + return `https://dash.sendwyre.com/sign-up` case 'coinswitch': return `https://metamask.coinswitch.co/?address=${address}&to=eth` case 'coinbase': diff --git a/test/unit/app/buy-eth-url.spec.js b/test/unit/app/buy-eth-url.spec.js index 96814c59d..d6234c1b3 100644 --- a/test/unit/app/buy-eth-url.spec.js +++ b/test/unit/app/buy-eth-url.spec.js @@ -20,7 +20,7 @@ describe('buy-eth-url', function () { it('returns wyre url with address for network 1', function () { const wyreUrl = getBuyEthUrl(mainnet) - assert.equal(wyreUrl, 'https://pay.sendwyre.com/?dest=ethereum:0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc&destCurrency=ETH&accountId=AC-7AG3W4XH4N2') + assert.equal(wyreUrl, 'https://dash.sendwyre.com/sign-up') }) @@ -40,4 +40,3 @@ describe('buy-eth-url', function () { }) }) - From 638e242ce672177eea255d3df62647b6f0313476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Lula?= Date: Wed, 4 Dec 2019 03:21:55 +0100 Subject: [PATCH 019/689] Search accounts by name (#7261) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Paweł Lula Co-Authored-By: Mark Stacey --- app/_locales/en/messages.json | 6 + .../account-menu/account-menu.component.js | 138 ++++++++++++++---- .../account-menu/account-menu.container.js | 24 +-- ui/app/components/app/account-menu/index.scss | 25 +++- .../transaction-breakdown.container.js | 2 +- ui/app/components/ui/search-icon/index.js | 1 + .../ui/search-icon/search-icon.component.js | 12 ++ .../ui/text-field/text-field.component.js | 133 +++++++++++++---- .../ui/text-field/text-field.stories.js | 6 +- .../token-search/token-search.component.js | 8 +- .../unlock-page/unlock-page.component.js | 2 +- ui/app/selectors/selectors.js | 69 ++++++--- ui/app/selectors/tests/selectors.test.js | 5 +- 13 files changed, 330 insertions(+), 101 deletions(-) create mode 100644 ui/app/components/ui/search-icon/index.js create mode 100644 ui/app/components/ui/search-icon/search-icon.component.js diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index b61349894..e9581e5cf 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1199,6 +1199,12 @@ "searchTokens": { "message": "Search Tokens" }, + "searchAccounts": { + "message": "Search Accounts" + }, + "noAccountsFound": { + "message": "No accounts found for the given search query" + }, "selectAnAccount": { "message": "Select an Account" }, diff --git a/ui/app/components/app/account-menu/account-menu.component.js b/ui/app/components/app/account-menu/account-menu.component.js index 0b241fba3..1a7bdf87f 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/app/components/app/account-menu/account-menu.component.js @@ -1,6 +1,9 @@ -import React, { PureComponent } from 'react' +import React, { Component } from 'react' import PropTypes from 'prop-types' import debounce from 'lodash.debounce' +import Fuse from 'fuse.js' +import InputAdornment from '@material-ui/core/InputAdornment' + import { Menu, Item, Divider, CloseArea } from '../dropdowns/components/menu' import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' @@ -17,17 +20,19 @@ import { CONNECT_HARDWARE_ROUTE, DEFAULT_ROUTE, } from '../../../helpers/constants/routes' +import TextField from '../../ui/text-field' +import SearchIcon from '../../ui/search-icon' -export default class AccountMenu extends PureComponent { +export default class AccountMenu extends Component { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, } static propTypes = { - accounts: PropTypes.object, + shouldShowAccountsSearch: PropTypes.bool, + accounts: PropTypes.array, history: PropTypes.object, - identities: PropTypes.object, isAccountMenuOpen: PropTypes.bool, keyrings: PropTypes.array, lockMetamask: PropTypes.func, @@ -39,22 +44,76 @@ export default class AccountMenu extends PureComponent { originOfCurrentTab: PropTypes.string, } + accountsRef; + state = { - atAccountListBottom: false, + shouldShowScrollButton: false, + searchQuery: '', } - componentDidUpdate (prevProps) { + addressFuse = new Fuse([], { + shouldSort: false, + threshold: 0.45, + location: 0, + distance: 100, + maxPatternLength: 32, + minMatchCharLength: 1, + keys: [ + { name: 'name', weight: 0.5 }, + { name: 'address', weight: 0.5 }, + ], + }) + + componentDidUpdate (prevProps, prevState) { const { isAccountMenuOpen: prevIsAccountMenuOpen } = prevProps + const { searchQuery: prevSearchQuery } = prevState const { isAccountMenuOpen } = this.props + const { searchQuery } = this.state if (!prevIsAccountMenuOpen && isAccountMenuOpen) { - this.setAtAccountListBottom() + this.setShouldShowScrollButton() + this.resetSearchQuery() + } + + // recalculate on each search query change + // whether we can show scroll down button + if (isAccountMenuOpen && prevSearchQuery !== searchQuery) { + this.setShouldShowScrollButton() } } + renderAccountsSearch () { + const inputAdornment = ( + + + + ) + + return [ + this.setSearchQuery(e.target.value)} + startAdornment={inputAdornment} + fullWidth + theme="material-white-padded" + />, + , + ] + } + renderAccounts () { const { - identities, accounts, selectedAddress, keyrings, @@ -62,14 +121,21 @@ export default class AccountMenu extends PureComponent { addressConnectedDomainMap, originOfCurrentTab, } = this.props + const { searchQuery } = this.state - const accountOrder = keyrings.reduce((list, keyring) => list.concat(keyring.accounts), []) + let filteredIdentities = accounts + if (searchQuery) { + this.addressFuse.setCollection(accounts) + filteredIdentities = this.addressFuse.search(searchQuery) + } + + if (filteredIdentities.length === 0) { + return

{this.context.t('noAccountsFound')}

+ } - return accountOrder.filter(address => !!identities[address]).map(address => { - const identity = identities[address] + return filteredIdentities.map(identity => { const isSelected = identity.address === selectedAddress - const balanceValue = accounts[address] ? accounts[address].balance : '' const simpleAddress = identity.address.substring(2).toLowerCase() const keyring = keyrings.find(kr => { @@ -106,7 +172,7 @@ export default class AccountMenu extends PureComponent {
@@ -181,28 +247,41 @@ export default class AccountMenu extends PureComponent { ) } - setAtAccountListBottom = () => { - const target = document.querySelector('.account-menu__accounts') - const { scrollTop, offsetHeight, scrollHeight } = target + resetSearchQuery () { + this.setSearchQuery('') + } + + setSearchQuery (searchQuery) { + this.setState({ searchQuery }) + } + + setShouldShowScrollButton = () => { + const { scrollTop, offsetHeight, scrollHeight } = this.accountsRef + + const canScroll = scrollHeight > offsetHeight + const atAccountListBottom = scrollTop + offsetHeight >= scrollHeight - this.setState({ atAccountListBottom }) + + const shouldShowScrollButton = canScroll && !atAccountListBottom + + this.setState({ shouldShowScrollButton}) } - onScroll = debounce(this.setAtAccountListBottom, 25) + onScroll = debounce(this.setShouldShowScrollButton, 25) handleScrollDown = e => { e.stopPropagation() - const target = document.querySelector('.account-menu__accounts') - const { scrollHeight } = target - target.scroll({ left: 0, top: scrollHeight, behavior: 'smooth' }) - this.setAtAccountListBottom() + + const { scrollHeight } = this.accountsRef + this.accountsRef.scroll({ left: 0, top: scrollHeight, behavior: 'smooth' }) + + this.setShouldShowScrollButton() } renderScrollButton () { - const { accounts } = this.props - const { atAccountListBottom } = this.state + const { shouldShowScrollButton } = this.state - return !atAccountListBottom && Object.keys(accounts).length > 3 && ( + return shouldShowScrollButton && (
) } render () { - const { t } = this.context + const { t, metricsEvent } = this.context const { + shouldShowAccountsSearch, isAccountMenuOpen, toggleAccountMenu, lockMetamask, history, } = this.props - const { metricsEvent } = this.context return (
+ {shouldShowAccountsSearch ? this.renderAccountsSearch() : null}
{ + this.accountsRef = ref + }} > { this.renderAccounts() }
diff --git a/ui/app/components/app/account-menu/account-menu.container.js b/ui/app/components/app/account-menu/account-menu.container.js index 00a0666ec..2823a474d 100644 --- a/ui/app/components/app/account-menu/account-menu.container.js +++ b/ui/app/components/app/account-menu/account-menu.container.js @@ -1,5 +1,5 @@ import { connect } from 'react-redux' -import { compose } from 'recompose' +import { compose, withProps } from 'recompose' import { withRouter } from 'react-router-dom' import { toggleAccountMenu, @@ -13,23 +13,28 @@ import { } from '../../../store/actions' import { getAddressConnectedDomainMap, - getMetaMaskAccounts, + getMetaMaskAccountsOrdered, + getMetaMaskKeyrings, getOriginOfCurrentTab, + getSelectedAddress, } from '../../../selectors/selectors' - import AccountMenu from './account-menu.component' +/** + * The min amount of accounts to show search field + */ +const SHOW_SEARCH_ACCOUNTS_MIN_COUNT = 5 + function mapStateToProps (state) { - const { metamask: { selectedAddress, isAccountMenuOpen, keyrings, identities } } = state + const { metamask: { isAccountMenuOpen } } = state return { - selectedAddress, isAccountMenuOpen, - keyrings, - identities, - accounts: getMetaMaskAccounts(state), addressConnectedDomainMap: getAddressConnectedDomainMap(state), originOfCurrentTab: getOriginOfCurrentTab(state), + selectedAddress: getSelectedAddress(state), + keyrings: getMetaMaskKeyrings(state), + accounts: getMetaMaskAccountsOrdered(state), } } @@ -65,5 +70,6 @@ function mapDispatchToProps (dispatch) { export default compose( withRouter, - connect(mapStateToProps, mapDispatchToProps) + connect(mapStateToProps, mapDispatchToProps), + withProps(({ accounts }) => ({ shouldShowAccountsSearch: accounts.length >= SHOW_SEARCH_ACCOUNTS_MIN_COUNT})) )(AccountMenu) diff --git a/ui/app/components/app/account-menu/index.scss b/ui/app/components/app/account-menu/index.scss index 93b9766d3..c8385b5e7 100644 --- a/ui/app/components/app/account-menu/index.scss +++ b/ui/app/components/app/account-menu/index.scss @@ -51,22 +51,26 @@ height: 16px; } - &__accounts { + &__accounts-container { display: flex; - flex-flow: column nowrap; - overflow-y: auto; - max-height: 256px; - position: relative; + flex-direction: column; z-index: 200; scrollbar-width: none; - &::-webkit-scrollbar { - display: none; - } + max-height: 256px; @media screen and (max-width: 575px) { max-height: 228px; } + } + + &__accounts { + overflow-y: auto; + position: relative; + + &::-webkit-scrollbar { + display: none; + } .keyring-label { margin-top: 5px; @@ -77,6 +81,11 @@ } } + &__no-accounts { + font-size: 0.8em; + padding: 16px 14px; + } + &__account { display: flex; flex-flow: row nowrap; diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js index 82f377358..689a60208 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux' import TransactionBreakdown from './transaction-breakdown.component' -import {getIsMainnet, getNativeCurrency, preferencesSelector} from '../../../selectors/selectors' +import { getIsMainnet, getNativeCurrency, preferencesSelector } from '../../../selectors/selectors' import { getHexGasTotal } from '../../../helpers/utils/confirm-tx.util' import { sumHexes } from '../../../helpers/utils/transactions.util' diff --git a/ui/app/components/ui/search-icon/index.js b/ui/app/components/ui/search-icon/index.js new file mode 100644 index 000000000..f6078b7be --- /dev/null +++ b/ui/app/components/ui/search-icon/index.js @@ -0,0 +1 @@ +export { default } from './search-icon.component' diff --git a/ui/app/components/ui/search-icon/search-icon.component.js b/ui/app/components/ui/search-icon/search-icon.component.js new file mode 100644 index 000000000..b793518a4 --- /dev/null +++ b/ui/app/components/ui/search-icon/search-icon.component.js @@ -0,0 +1,12 @@ +import React from 'react' + +export default function SearchIcon () { + return ( + + + + + + + ) +} diff --git a/ui/app/components/ui/text-field/text-field.component.js b/ui/app/components/ui/text-field/text-field.component.js index 12a97ee4d..557e547c5 100644 --- a/ui/app/components/ui/text-field/text-field.component.js +++ b/ui/app/components/ui/text-field/text-field.component.js @@ -28,6 +28,24 @@ const styles = { }, }, materialError: {}, + materialWhitePaddedRoot: { + color: '#aeaeae', + }, + materialWhitePaddedInput: { + padding: '8px', + + '&::placeholder': { + color: '#aeaeae', + }, + }, + materialWhitePaddedFocused: { + color: '#fff', + }, + materialWhitePaddedUnderline: { + '&:after': { + borderBottom: '2px solid #fff', + }, + }, // Non-material styles formLabel: { '&$formLabelFocused': { @@ -66,35 +84,99 @@ const styles = { }, } -const TextField = props => { - const { error, classes, material, startAdornment, largeLabel, dir, ...textFieldProps } = props +const getMaterialThemeInputProps = ({ + dir, + classes: { materialLabel, materialFocused, materialError, materialUnderline }, + startAdornment, +}) => ({ + InputLabelProps: { + FormLabelClasses: { + root: materialLabel, + focused: materialFocused, + error: materialError, + }, + }, + InputProps: { + startAdornment, + classes: { + underline: materialUnderline, + }, + inputProps: { + dir, + }, + }, +}) + +const getMaterialWhitePaddedThemeInputProps = ({ + dir, + classes: { materialWhitePaddedRoot, materialWhitePaddedFocused, materialWhitePaddedInput, materialWhitePaddedUnderline }, + startAdornment, +}) => ({ + InputProps: { + startAdornment, + classes: { + root: materialWhitePaddedRoot, + focused: materialWhitePaddedFocused, + input: materialWhitePaddedInput, + underline: materialWhitePaddedUnderline, + }, + inputProps: { + dir, + }, + }, +}) + +const getBorderedThemeInputProps = ({ + dir, + classes: { formLabel, formLabelFocused, materialError, largeInputLabel, inputLabel, inputRoot, input, inputFocused }, + largeLabel, + startAdornment, +}) => ({ + InputLabelProps: { + shrink: true, + className: largeLabel ? largeInputLabel : inputLabel, + FormLabelClasses: { + root: formLabel, + focused: formLabelFocused, + error: materialError, + }, + }, + InputProps: { + startAdornment, + disableUnderline: true, + classes: { + root: inputRoot, + input: input, + focused: inputFocused, + }, + inputProps: { + dir, + }, + }, +}) + +const themeToInputProps = { + 'material': getMaterialThemeInputProps, + 'bordered': getBorderedThemeInputProps, + 'material-white-padded': getMaterialWhitePaddedThemeInputProps, +} + +const TextField = ({ + error, + classes, + theme, + startAdornment, + largeLabel, + dir, + ...textFieldProps +}) => { + const inputProps = themeToInputProps[theme]({ classes, startAdornment, largeLabel, dir }) return ( ) @@ -103,13 +185,14 @@ const TextField = props => { TextField.defaultProps = { error: null, dir: 'auto', + theme: 'bordered', } TextField.propTypes = { error: PropTypes.string, classes: PropTypes.object, dir: PropTypes.string, - material: PropTypes.bool, + theme: PropTypes.oneOf(['bordered', 'material', 'material-white-padded']), startAdornment: PropTypes.element, largeLabel: PropTypes.bool, } diff --git a/ui/app/components/ui/text-field/text-field.stories.js b/ui/app/components/ui/text-field/text-field.stories.js index d68f24362..9ef76d1d3 100644 --- a/ui/app/components/ui/text-field/text-field.stories.js +++ b/ui/app/components/ui/text-field/text-field.stories.js @@ -33,14 +33,14 @@ storiesOf('TextField', module) )) .add('Material password', () => ( )) .add('Material error', () => ( @@ -48,6 +48,6 @@ storiesOf('TextField', module) type="text" label="Name" error="Invalid value" - material + theme="material" /> )) diff --git a/ui/app/pages/add-token/token-search/token-search.component.js b/ui/app/pages/add-token/token-search/token-search.component.js index 5542a19ff..eee841654 100644 --- a/ui/app/pages/add-token/token-search/token-search.component.js +++ b/ui/app/pages/add-token/token-search/token-search.component.js @@ -36,12 +36,8 @@ export default class TokenSearch extends Component { error: PropTypes.string, } - constructor (props) { - super(props) - - this.state = { - searchQuery: '', - } + state = { + searchQuery: '', } handleSearch (searchQuery) { diff --git a/ui/app/pages/unlock-page/unlock-page.component.js b/ui/app/pages/unlock-page/unlock-page.component.js index 3aeb2a59b..8620b53f9 100644 --- a/ui/app/pages/unlock-page/unlock-page.component.js +++ b/ui/app/pages/unlock-page/unlock-page.component.js @@ -165,7 +165,7 @@ export default class UnlockPage extends Component { error={error} autoFocus autoComplete="current-password" - material + theme="material" fullWidth /> diff --git a/ui/app/selectors/selectors.js b/ui/app/selectors/selectors.js index bcd21d107..3077421ac 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/app/selectors/selectors.js @@ -1,6 +1,7 @@ import { NETWORK_TYPES } from '../helpers/constants/common' import { mapObjectValues } from '../../../app/scripts/lib/util' import { stripHexPrefix, addHexPrefix } from 'ethereumjs-util' +import { createSelector } from 'reselect' import abi from 'human-standard-token-abi' import { multiplyCurrencies } from '../helpers/utils/conversion-util' @@ -58,6 +59,28 @@ export function getCurrentNetworkId (state) { return state.metamask.network } +export const getMetaMaskAccounts = createSelector( + getMetaMaskAccountsRaw, + getMetaMaskCachedBalances, + (currentAccounts, cachedBalances) => Object.entries(currentAccounts).reduce((selectedAccounts, [accountID, account]) => { + if (account.balance === null || account.balance === undefined) { + return { + ...selectedAccounts, + [accountID]: { + ...account, + balance: cachedBalances && cachedBalances[accountID], + }, + + } + } else { + return { + ...selectedAccounts, + [accountID]: account, + } + } + }, {}) +) + export function getSelectedAddress (state) { const selectedAddress = state.metamask.selectedAddress || Object.keys(getMetaMaskAccounts(state))[0] @@ -80,25 +103,37 @@ export function getNumberOfTokens (state) { return tokens ? tokens.length : 0 } -export function getMetaMaskAccounts (state) { - const currentAccounts = state.metamask.accounts - const cachedBalances = state.metamask.cachedBalances[state.metamask.network] - const selectedAccounts = {} - - Object.keys(currentAccounts).forEach(accountID => { - const account = currentAccounts[accountID] - if (account && account.balance === null || account.balance === undefined) { - selectedAccounts[accountID] = { - ...account, - balance: cachedBalances && cachedBalances[accountID], - } - } else { - selectedAccounts[accountID] = account - } - }) - return selectedAccounts +export function getMetaMaskKeyrings (state) { + return state.metamask.keyrings +} + +export function getMetaMaskIdentities (state) { + return state.metamask.identities +} + +export function getMetaMaskAccountsRaw (state) { + return state.metamask.accounts } +export function getMetaMaskCachedBalances (state) { + const network = getCurrentNetworkId(state) + + return state.metamask.cachedBalances[network] +} + +/** + * Get ordered (by keyrings) accounts with identity and balance + */ +export const getMetaMaskAccountsOrdered = createSelector( + getMetaMaskKeyrings, + getMetaMaskIdentities, + getMetaMaskAccounts, + (keyrings, identities, accounts) => keyrings + .reduce((list, keyring) => list.concat(keyring.accounts), []) + .filter(address => !!identities[address]) + .map(address => ({ ...identities[address], ...accounts[address]})) +) + export function isBalanceCached (state) { const selectedAccountBalance = state.metamask.accounts[getSelectedAddress(state)].balance const cachedBalance = getSelectedAccountCachedBalance(state) diff --git a/ui/app/selectors/tests/selectors.test.js b/ui/app/selectors/tests/selectors.test.js index 813628968..16170bc6b 100644 --- a/ui/app/selectors/tests/selectors.test.js +++ b/ui/app/selectors/tests/selectors.test.js @@ -1,8 +1,5 @@ import assert from 'assert' -import * as selectors from '../selectors' -const { - getAddressBook, -} = selectors +import { getAddressBook } from '../selectors.js' import mockState from './selectors-test-data' describe('selectors', () => { From 2d6ad7f6ca38eca8d30d046a4f548e1ae7dfed3b Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 3 Dec 2019 22:52:14 -0400 Subject: [PATCH 020/689] Update permissions request parameter names and docs (#7636) The parameter names and JSDoc comments for `approvePermissionsRequest` and `rejectPermissionsRequest` were incorrect in a few places. --- app/scripts/controllers/permissions/index.js | 3 ++- .../permissions-connect.component.js | 4 ++-- .../permissions-connect.container.js | 2 +- ui/app/store/actions.js | 12 ++++++------ 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/app/scripts/controllers/permissions/index.js b/app/scripts/controllers/permissions/index.js index 899044b13..de1c472e4 100644 --- a/app/scripts/controllers/permissions/index.js +++ b/app/scripts/controllers/permissions/index.js @@ -133,7 +133,8 @@ class PermissionsController { /** * User approval callback. The request can fail if the request is invalid. * - * @param {object} approved the approved request object + * @param {object} approved - the approved request object + * @param {Array} accounts - The accounts to expose, if any */ async approvePermissionsRequest (approved, accounts) { diff --git a/ui/app/pages/permissions-connect/permissions-connect.component.js b/ui/app/pages/permissions-connect/permissions-connect.component.js index 69dcbd390..e09fe5fab 100644 --- a/ui/app/pages/permissions-connect/permissions-connect.component.js +++ b/ui/app/pages/permissions-connect/permissions-connect.component.js @@ -186,8 +186,8 @@ export default class PermissionConnect extends Component {
{ - approvePermissionsRequest(requestId, accounts) + approvePermissionsRequest={(request, accounts) => { + approvePermissionsRequest(request, accounts) this.redirectFlow(true) }} rejectPermissionsRequest={requestId => { diff --git a/ui/app/pages/permissions-connect/permissions-connect.container.js b/ui/app/pages/permissions-connect/permissions-connect.container.js index 1209bd9cc..143cc6fbc 100644 --- a/ui/app/pages/permissions-connect/permissions-connect.container.js +++ b/ui/app/pages/permissions-connect/permissions-connect.container.js @@ -46,7 +46,7 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => { return { - approvePermissionsRequest: (requestId, accounts) => dispatch(approvePermissionsRequest(requestId, accounts)), + approvePermissionsRequest: (request, accounts) => dispatch(approvePermissionsRequest(request, accounts)), rejectPermissionsRequest: requestId => dispatch(rejectPermissionsRequest(requestId)), showNewAccountModal: ({ onCreateNewAccount, newAccountNumber }) => { return dispatch(showModal({ diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index d81769f01..e29bb57b7 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -2718,19 +2718,19 @@ function setPendingTokens (pendingTokens) { // Permissions /** - * Approves the permission requests with the given IDs. - * @param {string} requestId - The id of the permissions request. + * Approves the permissions request. + * @param {Object} request - The permissions request to approve * @param {string[]} accounts - The accounts to expose, if any. */ -function approvePermissionsRequest (requestId, accounts) { +function approvePermissionsRequest (request, accounts) { return () => { - background.approvePermissionsRequest(requestId, accounts) + background.approvePermissionsRequest(request, accounts) } } /** - * Rejects the permission requests with the given IDs. - * @param {Array} requestId + * Rejects the permissions request with the given ID. + * @param {string} requestId - The id of the request to be rejected */ function rejectPermissionsRequest (requestId) { return () => { From 03f53df3f372ef9df8d9ddfee96952265fc76bac Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 3 Dec 2019 23:25:00 -0330 Subject: [PATCH 021/689] Updates to account search functionality (#7637) --- app/scripts/controllers/permissions/index.js | 2 +- .../components/app/account-menu/account-menu.component.js | 2 +- .../components/app/account-menu/account-menu.container.js | 7 ++++--- ui/app/selectors/selectors.js | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/scripts/controllers/permissions/index.js b/app/scripts/controllers/permissions/index.js index de1c472e4..4a5b82cae 100644 --- a/app/scripts/controllers/permissions/index.js +++ b/app/scripts/controllers/permissions/index.js @@ -188,7 +188,7 @@ class PermissionsController { let error try { await new Promise((resolve, reject) => { - this.permissions.grantNewPermissions(origin, permissions, {}, err => err ? resolve() : reject(err)) + this.permissions.grantNewPermissions(origin, permissions, {}, err => (err ? resolve() : reject(err))) }) } catch (err) { error = err diff --git a/ui/app/components/app/account-menu/account-menu.component.js b/ui/app/components/app/account-menu/account-menu.component.js index 1a7bdf87f..f5217606f 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/app/components/app/account-menu/account-menu.component.js @@ -264,7 +264,7 @@ export default class AccountMenu extends Component { const shouldShowScrollButton = canScroll && !atAccountListBottom - this.setState({ shouldShowScrollButton}) + this.setState({ shouldShowScrollButton }) } onScroll = debounce(this.setShouldShowScrollButton, 25) diff --git a/ui/app/components/app/account-menu/account-menu.container.js b/ui/app/components/app/account-menu/account-menu.container.js index 2823a474d..7182550a5 100644 --- a/ui/app/components/app/account-menu/account-menu.container.js +++ b/ui/app/components/app/account-menu/account-menu.container.js @@ -1,5 +1,5 @@ import { connect } from 'react-redux' -import { compose, withProps } from 'recompose' +import { compose } from 'recompose' import { withRouter } from 'react-router-dom' import { toggleAccountMenu, @@ -27,6 +27,7 @@ const SHOW_SEARCH_ACCOUNTS_MIN_COUNT = 5 function mapStateToProps (state) { const { metamask: { isAccountMenuOpen } } = state + const accounts = getMetaMaskAccountsOrdered(state) return { isAccountMenuOpen, @@ -34,7 +35,8 @@ function mapStateToProps (state) { originOfCurrentTab: getOriginOfCurrentTab(state), selectedAddress: getSelectedAddress(state), keyrings: getMetaMaskKeyrings(state), - accounts: getMetaMaskAccountsOrdered(state), + accounts, + shouldShowAccountsSearch: accounts.length >= SHOW_SEARCH_ACCOUNTS_MIN_COUNT, } } @@ -71,5 +73,4 @@ function mapDispatchToProps (dispatch) { export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), - withProps(({ accounts }) => ({ shouldShowAccountsSearch: accounts.length >= SHOW_SEARCH_ACCOUNTS_MIN_COUNT})) )(AccountMenu) diff --git a/ui/app/selectors/selectors.js b/ui/app/selectors/selectors.js index 3077421ac..7c91ea770 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/app/selectors/selectors.js @@ -131,7 +131,7 @@ export const getMetaMaskAccountsOrdered = createSelector( (keyrings, identities, accounts) => keyrings .reduce((list, keyring) => list.concat(keyring.accounts), []) .filter(address => !!identities[address]) - .map(address => ({ ...identities[address], ...accounts[address]})) + .map(address => ({ ...identities[address], ...accounts[address] })) ) export function isBalanceCached (state) { From 5c5c90e70afcf48c082c49123d38c57a21f64615 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 3 Dec 2019 23:13:47 -0400 Subject: [PATCH 022/689] Ignore permission approval/rejection if request is missing (#7638) Attempts to approve or reject a permissions request that is no longer pending will now emit a warning instead of throwing an exception. I _think_ this can happen by clicking 'Submit' on the Permission Connect screen twice, though I've been unable to reproduce that. I know that it can be done if using multiple windows though. While it is possible we have a UI bug somewhere (e.g. maybe we're not preventing 'Submit' from being clicked twice), I don't think it's possible to eliminate the chance of this happening altogether, so we'd best prepare for it. --- app/scripts/controllers/permissions/index.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/scripts/controllers/permissions/index.js b/app/scripts/controllers/permissions/index.js index 4a5b82cae..40a5b0944 100644 --- a/app/scripts/controllers/permissions/index.js +++ b/app/scripts/controllers/permissions/index.js @@ -1,6 +1,7 @@ const JsonRpcEngine = require('json-rpc-engine') const asMiddleware = require('json-rpc-engine/src/asMiddleware') const ObservableStore = require('obs-store') +const log = require('loglevel') const RpcCap = require('rpc-cap').CapabilitiesController const { ethErrors } = require('eth-json-rpc-errors') @@ -141,6 +142,11 @@ class PermissionsController { const { id } = approved.metadata const approval = this.pendingApprovals[id] + if (!approval) { + log.warn(`Permissions request with id '${id}' not found`) + return + } + try { // attempt to finalize the request and resolve it @@ -165,6 +171,12 @@ class PermissionsController { */ async rejectPermissionsRequest (id) { const approval = this.pendingApprovals[id] + + if (!approval) { + log.warn(`Permissions request with id '${id}' not found`) + return + } + approval.reject(ethErrors.provider.userRejectedRequest()) delete this.pendingApprovals[id] } From 0b8f74ede51ce70da69e7582a445f603eb0c2099 Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Tue, 3 Dec 2019 21:35:44 -0800 Subject: [PATCH 023/689] Remove random comma (#7639) --- .../signature-request-original.component.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/components/app/signature-request-original/signature-request-original.component.js b/ui/app/components/app/signature-request-original/signature-request-original.component.js index 9a92ba5fb..4dbb95bd3 100644 --- a/ui/app/components/app/signature-request-original/signature-request-original.component.js +++ b/ui/app/components/app/signature-request-original/signature-request-original.component.js @@ -287,7 +287,7 @@ export default class SignatureRequestOriginal extends Component { }} > { this.context.t('cancel') } - , + - + return ( +
+
+
+ {this.context.t('hideTokenPrompt')} +
+ +
{symbol}
+
+ {this.context.t('readdToken')} +
+
+ + +
-
- ) + ) + } } + +export default connect(mapStateToProps, mapDispatchToProps)(HideTokenConfirmationModal) From 0d61f78379629a7e761f775e3b9bd3e638c3935b Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 10 Jan 2020 11:55:27 -0400 Subject: [PATCH 100/689] Remove unused PersistentForm (#7770) This component used to persist form contents to LocalStorage. This was especially useful for the popup UI, as each time the mouse left the popup, the UI was completely torn down and state was lost. This component was only being referenced by one form, and it wasn't even being used there (e.g. no fields were labelled appropriately to be persisted). This was a useful component, and it seems this feature was lost somewhere in the past couple of years. It was tempting to re-instate it rather than delete it, but I decided not to because I'd likely approach the problem differently if we wanted to reinstate it again today (maybe by using a React Hook, or storing the state in Redux and persisting a subset of the Redux store instead). --- docs/form_persisting_architecture.md | 28 ------------- ui/app/pages/send/send.component.js | 5 +-- ui/lib/persistent-form.js | 62 ---------------------------- 3 files changed, 2 insertions(+), 93 deletions(-) delete mode 100644 docs/form_persisting_architecture.md delete mode 100644 ui/lib/persistent-form.js diff --git a/docs/form_persisting_architecture.md b/docs/form_persisting_architecture.md deleted file mode 100644 index e2d766ccc..000000000 --- a/docs/form_persisting_architecture.md +++ /dev/null @@ -1,28 +0,0 @@ -# Form Persisting Architecture - -Since: - - The popup is torn down completely on every click outside of it. - - We have forms with multiple fields (like passwords & seed phrases) that might encourage a user to leave our panel to refer to a password manager. - - We cause user friction when we lose the contents of certain forms. - - This calls for an architecture of a form component that can completely persist its values to LocalStorage on every relevant change, and restore those values on reopening. - - To achieve this, we have defined a class, a subclass of `React.Component`, called `PersistentForm`, and it's stored at `ui/lib/persistent-form.js`. - -To use this class, simply take your form component (the component that renders `input`, `select`, or `textarea` elements), and make it subclass from `PersistentForm` instead of `React.Component`. - -You can see an example of this in use in `ui/app/first-time/restore-vault.js`. - -Additionally, any field whose value should be persisted, should have a `persistentFormId` attribute, which needs to be assigned under a `dataset` key on the main `attributes` hash. For example: - -```javascript - return h('textarea.twelve-word-phrase.letter-spacey', { - dataset: { - persistentFormId: 'wallet-seed', - }, - }) -``` - -That's it! This field should be persisted to `localStorage` on each `keyUp`, those values should be restored on view load, and the cached values should be cleared when navigating deliberately away from the form. - diff --git a/ui/app/pages/send/send.component.js b/ui/app/pages/send/send.component.js index bb8c9c9f1..3507c1cf1 100644 --- a/ui/app/pages/send/send.component.js +++ b/ui/app/pages/send/send.component.js @@ -1,6 +1,5 @@ -import React from 'react' +import React, { Component } from 'react' import PropTypes from 'prop-types' -import PersistentForm from '../../../lib/persistent-form' import { getAmountErrorObject, getGasFeeErrorObject, @@ -16,7 +15,7 @@ import SendFooter from './send-footer' import EnsInput from './send-content/add-recipient/ens-input' -export default class SendTransactionScreen extends PersistentForm { +export default class SendTransactionScreen extends Component { static propTypes = { addressBook: PropTypes.arrayOf(PropTypes.object), diff --git a/ui/lib/persistent-form.js b/ui/lib/persistent-form.js deleted file mode 100644 index b26cfac38..000000000 --- a/ui/lib/persistent-form.js +++ /dev/null @@ -1,62 +0,0 @@ -import { inherits } from 'util' -import { Component } from 'react' - -const defaultKey = 'persistent-form-default' -const eventName = 'keyup' - -export default PersistentForm - -function PersistentForm () { - Component.call(this) -} - -inherits(PersistentForm, Component) - -PersistentForm.prototype.componentDidMount = function () { - const fields = document.querySelectorAll('[data-persistent-formid]') - const store = this.getPersistentStore() - - for (let i = 0; i < fields.length; i++) { - const field = fields[i] - const key = field.getAttribute('data-persistent-formid') - const cached = store[key] - if (cached !== undefined) { - field.value = cached - } - - field.addEventListener(eventName, this.persistentFieldDidUpdate.bind(this)) - } -} - -PersistentForm.prototype.getPersistentStore = function () { - let store = window.localStorage[this.persistentFormParentId || defaultKey] - if (store && store !== 'null') { - store = JSON.parse(store) - } else { - store = {} - } - return store -} - -PersistentForm.prototype.setPersistentStore = function (newStore) { - window.localStorage[this.persistentFormParentId || defaultKey] = JSON.stringify(newStore) -} - -PersistentForm.prototype.persistentFieldDidUpdate = function (event) { - const field = event.target - const store = this.getPersistentStore() - const key = field.getAttribute('data-persistent-formid') - const val = field.value - store[key] = val - this.setPersistentStore(store) -} - -PersistentForm.prototype.componentWillUnmount = function () { - const fields = document.querySelectorAll('[data-persistent-formid]') - for (let i = 0; i < fields.length; i++) { - const field = fields[i] - field.removeEventListener(eventName, this.persistentFieldDidUpdate.bind(this)) - } - this.setPersistentStore({}) -} - From 52a38de567a47072ab6ba793dd651655588e936c Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 10 Jan 2020 15:27:48 -0330 Subject: [PATCH 101/689] Remove unused components (#7802) --- app/_locales/am/messages.json | 12 - app/_locales/ar/messages.json | 12 - app/_locales/bg/messages.json | 12 - app/_locales/bn/messages.json | 12 - app/_locales/ca/messages.json | 12 - app/_locales/cs/messages.json | 12 - app/_locales/da/messages.json | 12 - app/_locales/de/messages.json | 12 - app/_locales/el/messages.json | 12 - app/_locales/en/messages.json | 14 +- app/_locales/es/messages.json | 12 - app/_locales/es_419/messages.json | 12 - app/_locales/et/messages.json | 12 - app/_locales/fa/messages.json | 12 - app/_locales/fi/messages.json | 12 - app/_locales/fil/messages.json | 12 - app/_locales/fr/messages.json | 12 - app/_locales/he/messages.json | 12 - app/_locales/hi/messages.json | 12 - app/_locales/hn/messages.json | 12 - app/_locales/hr/messages.json | 12 - app/_locales/ht/messages.json | 12 - app/_locales/hu/messages.json | 12 - app/_locales/id/messages.json | 12 - app/_locales/it/messages.json | 12 - app/_locales/ja/messages.json | 12 - app/_locales/kn/messages.json | 12 - app/_locales/ko/messages.json | 12 - app/_locales/lt/messages.json | 12 - app/_locales/lv/messages.json | 12 - app/_locales/ms/messages.json | 12 - app/_locales/nl/messages.json | 12 - app/_locales/no/messages.json | 12 - app/_locales/ph/messages.json | 12 - app/_locales/pl/messages.json | 12 - app/_locales/pt/messages.json | 12 - app/_locales/pt_BR/messages.json | 12 - app/_locales/ro/messages.json | 12 - app/_locales/ru/messages.json | 12 - app/_locales/sk/messages.json | 12 - app/_locales/sl/messages.json | 12 - app/_locales/sr/messages.json | 12 - app/_locales/sv/messages.json | 12 - app/_locales/sw/messages.json | 12 - app/_locales/ta/messages.json | 12 - app/_locales/th/messages.json | 12 - app/_locales/tr/messages.json | 12 - app/_locales/uk/messages.json | 12 - app/_locales/vi/messages.json | 12 - app/_locales/zh_CN/messages.json | 12 - app/_locales/zh_TW/messages.json | 12 - .../app/customize-gas-modal/gas-modal-card.js | 38 -- .../app/customize-gas-modal/index.js | 388 ------------------ ui/app/components/app/input-number.js | 81 ---- 54 files changed, 1 insertion(+), 1120 deletions(-) delete mode 100644 ui/app/components/app/customize-gas-modal/gas-modal-card.js delete mode 100644 ui/app/components/app/customize-gas-modal/index.js delete mode 100644 ui/app/components/app/input-number.js diff --git a/app/_locales/am/messages.json b/app/_locales/am/messages.json index afb2bc0d0..ad584f304 100644 --- a/app/_locales/am/messages.json +++ b/app/_locales/am/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "ቀሪ ሂሳብ ጊዜው ያለፈበት ሊሆን ይችላል" }, - "balanceIsInsufficientGas": { - "message": "አሁን ላለው አጠቃላይ ነዳጅ የማይበቃ ቀሪ ሂሳብ" - }, "basic": { "message": "መሠረታዊ" }, @@ -472,9 +469,6 @@ "gasLimit": { "message": "የነዳጅ ገደብ" }, - "gasLimitCalculation": { - "message": "የተጠቆመውን የነዳጅ ገደብ በአውታረ መረብ የስኬት መጠን ላይ ተመስርተን እናሰላለን።" - }, "gasLimitInfoModalContent": { "message": "የነዳጅ ገደብ እርስዎ ወጪ ለማድረግ ዝግጁ የሆኑት ከፍተኛው የነዳጅ መጠን ማለት ነው።" }, @@ -496,9 +490,6 @@ "gasPriceNoDenom": { "message": "የነዳጅ ዋጋ" }, - "gasPriceCalculation": { - "message": "የተጠቆመውን የነዳጅ ዋጋ በአውታረ መረብ የስኬት መጠን ላይ ተመስርተን እናሰላለን።" - }, "general": { "message": "አጠቃላይ" }, @@ -940,9 +931,6 @@ "revealSeedWordsWarning": { "message": "እነዚህ ቃላት ሁሉንም መለያዎችዎን ለመስረቅ ሊውሉ ይችላሉ።" }, - "revert": { - "message": "አድህር" - }, "remove": { "message": "አስወግድ" }, diff --git a/app/_locales/ar/messages.json b/app/_locales/ar/messages.json index 491d21d6f..464dbf22f 100644 --- a/app/_locales/ar/messages.json +++ b/app/_locales/ar/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "قد يكون الرصيد لاغياً" }, - "balanceIsInsufficientGas": { - "message": "لا يكفي الرصيد الحالي لإجمالي الغاز" - }, "basic": { "message": "الأساسية" }, @@ -468,9 +465,6 @@ "gasLimit": { "message": "الحد الأقصى لوحدات جاس" }, - "gasLimitCalculation": { - "message": "نحسب حد الغاز المقترح بناءً على معدلات نجاح الشبكة." - }, "gasLimitInfoModalContent": { "message": "حد عملة جاس هو الحد الأقصى لمقدار وحدات جاس التي ترغب في إنفاقها." }, @@ -492,9 +486,6 @@ "gasPriceNoDenom": { "message": "سعر عملة جاس" }, - "gasPriceCalculation": { - "message": "نحسب أسعار جاس المقترحة على أساس معدلات نجاح الشبكة." - }, "general": { "message": "عام" }, @@ -936,9 +927,6 @@ "revealSeedWordsWarning": { "message": "يمكن استخدام هذه الكلمات لسرقة جميع حساباتك." }, - "revert": { - "message": "الرجوع" - }, "remove": { "message": "إزالة" }, diff --git a/app/_locales/bg/messages.json b/app/_locales/bg/messages.json index ddbd6360e..620660809 100644 --- a/app/_locales/bg/messages.json +++ b/app/_locales/bg/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Балансът може да е остарял" }, - "balanceIsInsufficientGas": { - "message": "Недостатъчен баланс за текущия общ газ" - }, "basic": { "message": "Основни" }, @@ -468,9 +465,6 @@ "gasLimit": { "message": "Ограничение на газ" }, - "gasLimitCalculation": { - "message": "Изчисляваме препоръчителния лимит за газ въз основа на степента на успех на мрежата." - }, "gasLimitInfoModalContent": { "message": "Ограничението за газ е максималното количество единици газ, което сте готови да похарчите." }, @@ -492,9 +486,6 @@ "gasPriceNoDenom": { "message": "Цена на газа" }, - "gasPriceCalculation": { - "message": "Изчисляваме предложените цени на газ въз основа на успеваемостта на мрежата." - }, "general": { "message": "Общ" }, @@ -939,9 +930,6 @@ "revealSeedWordsWarning": { "message": "Тези думи могат да бъдат използвани за кражба на всички ваши акаунти." }, - "revert": { - "message": "Обръщане" - }, "remove": { "message": "Премахване" }, diff --git a/app/_locales/bn/messages.json b/app/_locales/bn/messages.json index 5aeda3c52..a5aa8f366 100644 --- a/app/_locales/bn/messages.json +++ b/app/_locales/bn/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "ব্যালেন্স অনেক পুরানো হতে পারে" }, - "balanceIsInsufficientGas": { - "message": "বর্তমান গ্যাস সমষ্টির জন্য অপর্যাপ্ত ব্যালেন্স" - }, "basic": { "message": "প্রাথমিক" }, @@ -472,9 +469,6 @@ "gasLimit": { "message": "গ্যাসের সীমা" }, - "gasLimitCalculation": { - "message": "নেটওয়ার্কের সাফল্যের হারগুলির উপর ভিত্তি করে আমরা প্রস্তাবিত গ্যাসের সীমা গণনা করি।" - }, "gasLimitInfoModalContent": { "message": "গ্যাসের সীমা হল আপনি যে পরিমাণ গ্যাস খরচ করতে চান তার সর্বোচ্চ ইউনিটের পরিমাণ।" }, @@ -496,9 +490,6 @@ "gasPriceNoDenom": { "message": "গ্যাসের মূল্য" }, - "gasPriceCalculation": { - "message": "নেটওয়ার্কের সাফল্যের হারগুলির উপর ভিত্তি করে আমরা প্রস্তাবিত গ্যাসের মূল্যগুলি গণনা করি।" - }, "general": { "message": "সাধারণ" }, @@ -943,9 +934,6 @@ "revealSeedWordsWarning": { "message": "আপনার সমস্ত অ্যাকাউন্ট চুরি করতে এই শব্দগুলি ব্যবহার করা যাবে।" }, - "revert": { - "message": "আগের অবস্থায় ফিরে আসুন" - }, "remove": { "message": "সরান" }, diff --git a/app/_locales/ca/messages.json b/app/_locales/ca/messages.json index 45bf26996..042e4b258 100644 --- a/app/_locales/ca/messages.json +++ b/app/_locales/ca/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "El balanç pot ser obsolet" }, - "balanceIsInsufficientGas": { - "message": "Saldo insuficient per al total de gas actual" - }, "basic": { "message": "Opcions bàsiques" }, @@ -465,9 +462,6 @@ "gasLimit": { "message": "Límit de gas" }, - "gasLimitCalculation": { - "message": "Calculem el límit suggerit del gas basant-nos en les taxes d'èxit de la xarxa." - }, "gasLimitInfoModalContent": { "message": "El límit de gas és la màxima quantitat d'unitats de gas que estàs disposat a gastar." }, @@ -489,9 +483,6 @@ "gasPriceNoDenom": { "message": "Preu del Gas" }, - "gasPriceCalculation": { - "message": "Calculem els preus suggerits del gas basant-nos en les taxes d'èxit de la xarxa." - }, "generalSettingsDescription": { "message": "Conversió de divises, divisa principal, idioma, icones d'identificació única" }, @@ -921,9 +912,6 @@ "revealSeedWordsWarning": { "message": "Aquestes paraules poden ser utilitzades per a robar tots els teus comptes." }, - "revert": { - "message": "Revertir" - }, "remove": { "message": "Suprimeix" }, diff --git a/app/_locales/cs/messages.json b/app/_locales/cs/messages.json index 489c8911a..3df744de1 100644 --- a/app/_locales/cs/messages.json +++ b/app/_locales/cs/messages.json @@ -46,9 +46,6 @@ "balance": { "message": "Zůstatek:" }, - "balanceIsInsufficientGas": { - "message": "Nedostatek prostředků pro aktuální množství paliva" - }, "blockiesIdenticon": { "message": "Použít Blockies Identicon" }, @@ -192,18 +189,12 @@ "gasLimit": { "message": "Limit paliva" }, - "gasLimitCalculation": { - "message": "Počítáme doporučený limit paliva na základě úspěšnosti v síti." - }, "gasLimitTooLow": { "message": "Limit paliva musí být alespoň 21000" }, "gasPrice": { "message": "Cena paliva (GWEI)" }, - "gasPriceCalculation": { - "message": "Počítáme doporučenou cenu paliva na základě úspěšnosti v síti." - }, "getEther": { "message": "Získejte Ether" }, @@ -386,9 +377,6 @@ "revealSeedWordsWarning": { "message": "Nebnovujte slova klíčové fráze na veřejnosti! Tato slova mohou být použita k odcizení veškerých vyašich účtů." }, - "revert": { - "message": "Zvrátit" - }, "save": { "message": "Uložit" }, diff --git a/app/_locales/da/messages.json b/app/_locales/da/messages.json index 798add363..c4e5105ff 100644 --- a/app/_locales/da/messages.json +++ b/app/_locales/da/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Saldoen kan være forældet" }, - "balanceIsInsufficientGas": { - "message": "Utilstrækkelig saldo for nuværende brændstoftotalbeløb" - }, "basic": { "message": "Grundlæggende oplysninger" }, @@ -468,9 +465,6 @@ "gasLimit": { "message": "Gas-grænse" }, - "gasLimitCalculation": { - "message": "Vi beregner den foreslåede gasgrænse baseret på netværkssuccesrater." - }, "gasLimitInfoModalContent": { "message": "Gasgrænse er den maksimale mængde gasenheder, du er villig til at bruge." }, @@ -492,9 +486,6 @@ "gasPriceNoDenom": { "message": "Brændstofpris" }, - "gasPriceCalculation": { - "message": "Vi beregner de anbefalede brændstofpriser baseret på netværkernes succesrater." - }, "general": { "message": "Generelt" }, @@ -921,9 +912,6 @@ "revealSeedWordsWarning": { "message": "Disse ord kan bruges til at stjæle alle dine konti." }, - "revert": { - "message": "Vend tilbage" - }, "remove": { "message": "Fjern" }, diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index 454e51fa6..3d7ec6194 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -136,9 +136,6 @@ "balanceOutdated": { "message": "Kontostand könnte überholt sein" }, - "balanceIsInsufficientGas": { - "message": "Guthaben unzureichend für den aktuellen gesamten Gasbetrag" - }, "basic": { "message": "Grundlegend" }, @@ -457,9 +454,6 @@ "gasLimit": { "message": "Gaslimit" }, - "gasLimitCalculation": { - "message": "Wir berechnen das empfohlene Gaslimit basierend auf der Erfolgsrate des Netzwerks." - }, "gasLimitInfoModalContent": { "message": "Die Gasgrenze ist die Höchstmenge an Gaseinheiten, die Sie auszugeben bereit sind." }, @@ -481,9 +475,6 @@ "gasPriceNoDenom": { "message": "Gaspreis" }, - "gasPriceCalculation": { - "message": "Wir berechnen den empfohlenen Gaspreis basierend auf der Erfolgsrate des Netzwerks." - }, "general": { "message": "Allgemein" }, @@ -909,9 +900,6 @@ "revealSeedWordsWarning": { "message": "Bitte niemals deine Seed-Wörterfolge an einem öffentlichen Ort kenntlich machen. Mit diesen Wörtern können alle deine Accounts gestohlen werden." }, - "revert": { - "message": "Rückgängig machen" - }, "remove": { "message": "Entfernen" }, diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index 56af2b04e..3f152fc6a 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Το υπόλοιπο μπορεί να μην είναι ενημερωμένο" }, - "balanceIsInsufficientGas": { - "message": "Ανεπαρκές υπόλοιπο για το τρέχον σύνολο καυσίμου" - }, "basic": { "message": "Βασικά" }, @@ -469,9 +466,6 @@ "gasLimit": { "message": "Όριο Καυσίμου" }, - "gasLimitCalculation": { - "message": "Υπολογίζουμε το προτεινόμενο όριο καυσίμου με βάση τα ποσοστά επιτυχίας του δικτύου." - }, "gasLimitInfoModalContent": { "message": "Το όριο αερίου είναι το μέγιστο ποσό μονάδων αερίου τι οποίες είστε διατεθειμένοι να δαπανήσετε." }, @@ -493,9 +487,6 @@ "gasPriceNoDenom": { "message": "Τιμή Gas" }, - "gasPriceCalculation": { - "message": "Υπολογίζουμε τις προτεινόμενες τιμές αερίου με βάση τα ποσοστά επιτυχίας του δικτύου." - }, "general": { "message": "Γενικά" }, @@ -940,9 +931,6 @@ "revealSeedWordsWarning": { "message": "Αυτές οι λέξεις μπορούν να χρησιμοποιηθούν για να κλαπούν όλοι οι λογαριασμοί σας." }, - "revert": { - "message": "Αναστροφή" - }, "remove": { "message": "Κατάργηση" }, diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index eeed11d89..2c98ed485 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -185,9 +185,6 @@ "balanceOutdated": { "message": "Balance may be outdated" }, - "balanceIsInsufficientGas": { - "message": "Insufficient balance for current gas total" - }, "basic": { "message": "Basic" }, @@ -587,9 +584,6 @@ "gasLimit": { "message": "Gas Limit" }, - "gasLimitCalculation": { - "message": "We calculate the suggested gas limit based on network success rates." - }, "gasLimitInfoModalContent": { "message": "Gas limit is the maximum amount of units of gas you are willing to spend." }, @@ -611,9 +605,6 @@ "gasPriceNoDenom": { "message": "Gas Price" }, - "gasPriceCalculation": { - "message": "We calculate the suggested gas prices based on network success rates." - }, "general": { "message": "General" }, @@ -1100,9 +1091,6 @@ "revealSeedWordsWarning": { "message": "These words can be used to steal all your accounts." }, - "revert": { - "message": "Revert" - }, "remove": { "message": "Remove" }, @@ -1386,7 +1374,7 @@ }, "thisWillAllowExternalExtension": { "message": "This will allow an external extension with id $1 to:", - "description": "$1 is a string of random letters that are the id of another extension connecting to MetaMask" + "description": "$1 is a string of random letters that are the id of another extension connecting to MetaMask" }, "thisWillCreate": { "message": "This will create a new wallet and seed phrase" diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index aba8a8790..9e83d05d9 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -127,9 +127,6 @@ "balance": { "message": "Saldo" }, - "balanceIsInsufficientGas": { - "message": "Saldo de gas insuficiente" - }, "basic": { "message": "Básico" }, @@ -390,9 +387,6 @@ "gasLimit": { "message": "Límite de gas" }, - "gasLimitCalculation": { - "message": "Calculamos el límite de gas sugerido en función de las tasas de éxito de la red" - }, "gasLimitTooLow": { "message": "El límite de gas debe ser de al menos 21000" }, @@ -408,9 +402,6 @@ "gasPriceNoDenom": { "message": "Precio de Gas" }, - "gasPriceCalculation": { - "message": "Calculamos los precios sugeridos del gas en función de las tasas de éxito de la red" - }, "generalSettingsDescription": { "message": "Conversión de divisas, divisa principal, idioma, blockies identicon" }, @@ -759,9 +750,6 @@ "revealSeedWordsWarning": { "message": "¡No recuperes tu semilla en un lugar pública! Esas palabras pueden ser usadas para robarte todas tus cuentas" }, - "revert": { - "message": "Revertir" - }, "remove": { "message": "borrar" }, diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index 7aa5e38b1..b6ab61496 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "El saldo puede estar anticuado" }, - "balanceIsInsufficientGas": { - "message": "Saldo insuficiente para el total actual de gas" - }, "basic": { "message": "Básicas" }, @@ -469,9 +466,6 @@ "gasLimit": { "message": "Limite de gas" }, - "gasLimitCalculation": { - "message": "Calculamos el límite de gas sugerido según las tasas de éxito en la red." - }, "gasLimitInfoModalContent": { "message": "El límite de gas es la cantidad máxima de unidades de gas que estás dispuesto a gastar." }, @@ -493,9 +487,6 @@ "gasPriceNoDenom": { "message": "Precio del gas" }, - "gasPriceCalculation": { - "message": "Calculamos los precios de gas sugeridos según las tasas de ganancia en la red." - }, "generalSettingsDescription": { "message": "Conversión de moneda, moneda principal, idioma, blockies identicon" }, @@ -928,9 +919,6 @@ "revealSeedWordsWarning": { "message": "Alguien podría utilizar estas palabras para robar todas tus cuentas." }, - "revert": { - "message": "Revertir" - }, "remove": { "message": "Quitar" }, diff --git a/app/_locales/et/messages.json b/app/_locales/et/messages.json index fea04910f..e11a90b16 100644 --- a/app/_locales/et/messages.json +++ b/app/_locales/et/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Saldo võib olla aegunud" }, - "balanceIsInsufficientGas": { - "message": "Ebapiisav kontojääk praeguse gaasi kogusumma jaoks" - }, "basic": { "message": "Põhiseaded" }, @@ -468,9 +465,6 @@ "gasLimit": { "message": "Gaasi ülemmäär" }, - "gasLimitCalculation": { - "message": "Arvutame soovituslikku gaasi ülemmäära vastavalt võrgu efektiivsusele." - }, "gasLimitInfoModalContent": { "message": "Gaasi ülemmäär on maksimaalne gaasiühikute hulk, mida olete nõus kulutama." }, @@ -492,9 +486,6 @@ "gasPriceNoDenom": { "message": "Gaasi hind" }, - "gasPriceCalculation": { - "message": "Arvutame soovituslikke gaasihindu vastavalt võrgu efektiivsusele." - }, "general": { "message": "Üldine teave" }, @@ -933,9 +924,6 @@ "revealSeedWordsWarning": { "message": "Neid sõnu saab kasutada kõigi teie kontode tühjendamiseks." }, - "revert": { - "message": "Ennista" - }, "remove": { "message": "Eemalda" }, diff --git a/app/_locales/fa/messages.json b/app/_locales/fa/messages.json index 109a29293..d12b19fb8 100644 --- a/app/_locales/fa/messages.json +++ b/app/_locales/fa/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "صورت حساب ممکن انقضاء شده باشد" }, - "balanceIsInsufficientGas": { - "message": "بیلانس ناکافی برای مجموع گاز فعلی" - }, "basic": { "message": "پایه" }, @@ -472,9 +469,6 @@ "gasLimit": { "message": "محدوده گاز" }, - "gasLimitCalculation": { - "message": "ما محدوده پیشنهادی گاز را مبتنی بر نرخ های موفقیت شبکه محاسبه مینماییم." - }, "gasLimitInfoModalContent": { "message": "محدوده گاز حد اکثر تعداد واحدات گاز است که میخواهید مصرف نمایید." }, @@ -496,9 +490,6 @@ "gasPriceNoDenom": { "message": "قیمت گاز" }, - "gasPriceCalculation": { - "message": "ما قیمت های پیشنهادی گاز را مبتنی بر نرخ های موفقیت شبکه محاسبه مینماییم." - }, "general": { "message": "عمومی" }, @@ -943,9 +934,6 @@ "revealSeedWordsWarning": { "message": "این کلمات را میتوان جهت سرقت همه حساب های تان استفاده نمود." }, - "revert": { - "message": "برگشت" - }, "remove": { "message": "پاک کردن" }, diff --git a/app/_locales/fi/messages.json b/app/_locales/fi/messages.json index 895fca6c1..5b0a5f8ed 100644 --- a/app/_locales/fi/messages.json +++ b/app/_locales/fi/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Saldo saattaa olla vanhentunut" }, - "balanceIsInsufficientGas": { - "message": "Saldo ei kata nykyistä polttoaineen kokonaismäärää" - }, "basic": { "message": "Perusvaihtoehdot" }, @@ -469,9 +466,6 @@ "gasLimit": { "message": "Gas-raja" }, - "gasLimitCalculation": { - "message": "Laskemme ehdotetun gas-arvon verkon onnistumistason perusteella." - }, "gasLimitInfoModalContent": { "message": "Polttoaineraja tarkoittaa suurinta mahdollista polttoainemäärää, jonka olet valmis kuluttamaan." }, @@ -493,9 +487,6 @@ "gasPriceNoDenom": { "message": "Bensan hinta" }, - "gasPriceCalculation": { - "message": "Laskemme ehdotetut polttoaineiden hinnat verkoston menestyksen perusteella." - }, "general": { "message": "Yleistä" }, @@ -940,9 +931,6 @@ "revealSeedWordsWarning": { "message": "Näitä sanoja voidaan käyttää kaikkien tiliesi ryöstämiseen." }, - "revert": { - "message": "Palauta" - }, "remove": { "message": "Poista" }, diff --git a/app/_locales/fil/messages.json b/app/_locales/fil/messages.json index ca1718b5d..51cb76533 100644 --- a/app/_locales/fil/messages.json +++ b/app/_locales/fil/messages.json @@ -127,9 +127,6 @@ "balanceOutdated": { "message": "Maaaring outdated na ang balanse" }, - "balanceIsInsufficientGas": { - "message": "Hindi sapat ang balanse para sa kasalukuyang total ng gas" - }, "basic": { "message": "Pangunahin" }, @@ -438,9 +435,6 @@ "gasLimit": { "message": "Limitasyon sa Gas" }, - "gasLimitCalculation": { - "message": "Nakalkula namin ang iminungkahing limitasyon sa gas batay sa mga success rate sa network." - }, "gasLimitInfoModalContent": { "message": "Ang limitasyon sa gas ay ang maximum na dami ng mga unit ng gas na handa kang gastusin." }, @@ -462,9 +456,6 @@ "gasPriceNoDenom": { "message": "Presyo ng Gas" }, - "gasPriceCalculation": { - "message": "Kinakalkula namin ang mga iminumungkahing preyso ng gas batay sa mga success rate sa network." - }, "general": { "message": "Pangkalahatan" }, @@ -864,9 +855,6 @@ "revealSeedWordsWarning": { "message": "Maaaring gamitin ang mga salitang ito para nakawin ang lahat ng iyong account." }, - "revert": { - "message": "I-revert" - }, "remove": { "message": "Alisin" }, diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index 671bee216..2f02eb8bb 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -136,9 +136,6 @@ "balanceOutdated": { "message": "Le solde peut ne pas être à jour" }, - "balanceIsInsufficientGas": { - "message": "Solde insuffisant pour le total actuel de gaz" - }, "basic": { "message": "Général" }, @@ -460,9 +457,6 @@ "gasLimit": { "message": "Quantité max. de gaz" }, - "gasLimitCalculation": { - "message": "Nous calculons la quantité max. de gaz suggérée en fonction du code exécuté." - }, "gasLimitInfoModalContent": { "message": "La limite d'essence est la quantité maximale d'unités d'essence que vous êtes prêt à dépenser." }, @@ -484,9 +478,6 @@ "gasPriceNoDenom": { "message": "Prix du gaz" }, - "gasPriceCalculation": { - "message": "Nous calculons les prix du gaz proposés en fonction des taux de réussite du réseau." - }, "general": { "message": "Général" }, @@ -922,9 +913,6 @@ "revealSeedWordsWarning": { "message": "Ces mots peuvent être utilisés pour voler tous vos comptes." }, - "revert": { - "message": "Rétablir" - }, "remove": { "message": "Supprimer" }, diff --git a/app/_locales/he/messages.json b/app/_locales/he/messages.json index 525a96bde..3ee07502b 100644 --- a/app/_locales/he/messages.json +++ b/app/_locales/he/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "ייתכן כי היתרה אינה מעודכנת" }, - "balanceIsInsufficientGas": { - "message": "יתרה לא מספיקה עבור סך דלק נוכחי" - }, "basic": { "message": "בסיסי" }, @@ -472,9 +469,6 @@ "gasLimit": { "message": "הגבלת דלק" }, - "gasLimitCalculation": { - "message": "אנו מחשבים את הגבלת הדלק המוצעת על בסיס שיעורי ההצלחה של הרשת." - }, "gasLimitInfoModalContent": { "message": "הגבלת דלק היא המספר המרבי של יחידות דלק שהנך מוכנ/ה להוציא." }, @@ -496,9 +490,6 @@ "gasPriceNoDenom": { "message": "מחיר הדלק" }, - "gasPriceCalculation": { - "message": "אנו מחשבים את מחירי הדלק המוצעים על בסיס שיעורי ההצלחה של הרשת." - }, "general": { "message": "כללי" }, @@ -940,9 +931,6 @@ "revealSeedWordsWarning": { "message": "במילים אלה עלול להיעשות שימוש כדי לגנוב את כל חשבונותיך." }, - "revert": { - "message": "חזרה" - }, "remove": { "message": "הסר" }, diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index 0d15519fe..46e3ef87a 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "शेष पुराना हो सकता है" }, - "balanceIsInsufficientGas": { - "message": "र्तमान गैस की कुल योग के लिए अपर्याप्त बैलेंस" - }, "basic": { "message": "मूलभूत" }, @@ -472,9 +469,6 @@ "gasLimit": { "message": "गैस की सीमा" }, - "gasLimitCalculation": { - "message": "हम नेटवर्क की सफलता दर के आधार पर सुझाई गई गैस सीमा की गणना करते हैं।" - }, "gasLimitInfoModalContent": { "message": "गैस की सीमा गैस के यूनिट की अधिकतम राशि है जिसे आप खर्च करना चाहते हैं।" }, @@ -496,9 +490,6 @@ "gasPriceNoDenom": { "message": "गैस का मूल्य" }, - "gasPriceCalculation": { - "message": "हम नेटवर्क की सफलता के दर के आधार पर सुझाए गए गैस की कीमतों की गणना करते हैं।" - }, "general": { "message": "सामान्य" }, @@ -940,9 +931,6 @@ "revealSeedWordsWarning": { "message": "इन शब्दों का उपयोग आपके सम्पूर्ण खातों को चुराने के लिए किया जा सकता है।" }, - "revert": { - "message": "वापस जाएँ" - }, "remove": { "message": "निकालें" }, diff --git a/app/_locales/hn/messages.json b/app/_locales/hn/messages.json index 5b391703a..a9658e3a1 100644 --- a/app/_locales/hn/messages.json +++ b/app/_locales/hn/messages.json @@ -43,9 +43,6 @@ "balance": { "message": "उपलब्ध बैलेंस।" }, - "balanceIsInsufficientGas": { - "message": "वर्तमान गैस कुल के लिए अपर्याप्त शेष" - }, "blockiesIdenticon": { "message": "ब्लॉकीज पहचान का उपयोग करें" }, @@ -168,18 +165,12 @@ "gasLimit": { "message": "गैस सीमा" }, - "gasLimitCalculation": { - "message": "हम नेटवर्क की सफलता दर के आधार पर सुझाई गई गैस सीमा की गणना करते हैं।" - }, "gasLimitTooLow": { "message": "२१००० - गैस की सीमा कम से कम 21000 होनी चाहिए" }, "gasPrice": { "message": "गैस मूल्य (जीडब्ल्यूईआई),(GWEI)" }, - "gasPriceCalculation": { - "message": "हम नेटवर्क की सफलता दर के आधार पर सुझाए गए गैस की कीमतों की गणना करते हैं।" - }, "getEther": { "message": "ईथर प्राप्त करें" }, @@ -363,9 +354,6 @@ "revealSeedWordsWarning": { "message": "किसी सार्वजनिक स्थान पर अपने बीज के शब्द ठीक नहीं करें! ये शब्द आपके सभी खातों को चोरी करने के लिए उपयोग किए जा सकते हैं।" }, - "revert": { - "message": "वापस" - }, "rinkeby": { "message": "रिचीव टेस्ट नेटवर्क" }, diff --git a/app/_locales/hr/messages.json b/app/_locales/hr/messages.json index 579e15026..535d824ab 100644 --- a/app/_locales/hr/messages.json +++ b/app/_locales/hr/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Stanje je možda zastarjelo" }, - "balanceIsInsufficientGas": { - "message": "Nedovoljno stanje za trenutačni iznos goriva" - }, "basic": { "message": "Osnovne" }, @@ -468,9 +465,6 @@ "gasLimit": { "message": "Ograničenje goriva" }, - "gasLimitCalculation": { - "message": "Izračunavamo predloženo ograničenje za gorivo na temelju postotka uspješnosti mreže." - }, "gasLimitInfoModalContent": { "message": "Ograničenje za gorivo predstavlja najveći broj jedinica goriva koje ste spremi potrošiti." }, @@ -492,9 +486,6 @@ "gasPriceNoDenom": { "message": "Cijena goriva" }, - "gasPriceCalculation": { - "message": "Izračunavamo predloženu cijenu goriva na temelju postotka uspješnosti mreže." - }, "general": { "message": "Opće" }, @@ -936,9 +927,6 @@ "revealSeedWordsWarning": { "message": "Ove se riječi mogu upotrijebiti za krađu vaših računa." }, - "revert": { - "message": "Vrati u prethodni oblik" - }, "remove": { "message": "Ukloni" }, diff --git a/app/_locales/ht/messages.json b/app/_locales/ht/messages.json index 88f1f41ae..a5ff121ad 100644 --- a/app/_locales/ht/messages.json +++ b/app/_locales/ht/messages.json @@ -67,9 +67,6 @@ "balance": { "message": "Balans" }, - "balanceIsInsufficientGas": { - "message": "Ensifizan balans pou total gaz aktyèl la" - }, "blockiesIdenticon": { "message": "Itilize Blockies Identicon" }, @@ -264,9 +261,6 @@ "gasLimit": { "message": "Limit gaz" }, - "gasLimitCalculation": { - "message": "Nou kalkile gaz limit sijere a ki baze sou pousantaj siksè rezo a." - }, "gasLimitTooLow": { "message": "Limit gaz dwe omwen 21000" }, @@ -276,9 +270,6 @@ "gasPrice": { "message": "Pri gaz (GWEI)" }, - "gasPriceCalculation": { - "message": "Nou kalkile pri yo gaz ki sijere ki baze sou pousantaj siksè rezo." - }, "getEther": { "message": "Jwenn Ether" }, @@ -588,9 +579,6 @@ "revealSeedWordsWarning": { "message": "Yo ka itilize mo sa pou vòlè kont ou." }, - "revert": { - "message": "Retounen" - }, "remove": { "message": "retire" }, diff --git a/app/_locales/hu/messages.json b/app/_locales/hu/messages.json index 33b8dac32..41e065e8b 100644 --- a/app/_locales/hu/messages.json +++ b/app/_locales/hu/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Az egyenleg elavult lehet" }, - "balanceIsInsufficientGas": { - "message": "Egyenlege nem elegendő a jelenlegi gáz végösszegéhez" - }, "basic": { "message": "Alapvető" }, @@ -468,9 +465,6 @@ "gasLimit": { "message": "Gáz határértéke" }, - "gasLimitCalculation": { - "message": "A javasolt gázhatárértéket a hálózat sikeressége alapján számoljuk ki." - }, "gasLimitInfoModalContent": { "message": "A gázkorlátozás az elkölthető gázegységek maximális mennyisége." }, @@ -492,9 +486,6 @@ "gasPriceNoDenom": { "message": "Gázár" }, - "gasPriceCalculation": { - "message": "A javasolt gázárakat a hálózat sikerességi rátája alapján számoljuk ki." - }, "general": { "message": "Általános" }, @@ -936,9 +927,6 @@ "revealSeedWordsWarning": { "message": "Ezekkel a szavakkal ellophatóak a fiókjai." }, - "revert": { - "message": "Visszatérít" - }, "remove": { "message": "Eltávolítás" }, diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index 874ca4576..dd36a4141 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Saldo mungkin kedaluwarsa" }, - "balanceIsInsufficientGas": { - "message": "Saldo tidak cukup untuk total bensin saat ini" - }, "basic": { "message": "Dasar" }, @@ -459,9 +456,6 @@ "gasLimit": { "message": "Batas Gas" }, - "gasLimitCalculation": { - "message": "Kami menghitung batas gas yang disarankan berdasarkan tingkat kesuksesan jaringan." - }, "gasLimitInfoModalContent": { "message": "Limit Bensin adalah jumlah maksimal satuan bensin yang Anda bersedia gunakan." }, @@ -483,9 +477,6 @@ "gasPriceNoDenom": { "message": "Harga Bensin" }, - "gasPriceCalculation": { - "message": "Kami menghitung harga bensin yang disarankan berdasarkan tingkat keberhasilan jaringan." - }, "general": { "message": "Umum" }, @@ -921,9 +912,6 @@ "revealSeedWordsWarning": { "message": "Kata-kata ini dapat digunakan untuk mencuri semua akun Anda." }, - "revert": { - "message": "Urungkan" - }, "remove": { "message": "Hapus" }, diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index 213407a3b..5cb30244d 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -133,9 +133,6 @@ "balanceOutdated": { "message": "Il bilancio può essere non aggiornato" }, - "balanceIsInsufficientGas": { - "message": "Bilancio insufficiente per il gas totale corrente" - }, "basic": { "message": "Base" }, @@ -451,9 +448,6 @@ "gasLimit": { "message": "Gas Limite" }, - "gasLimitCalculation": { - "message": "Calcoliamo il gas limite suggerito in base al successo delle transazioni in rete." - }, "gasLimitInfoModalContent": { "message": "Il gas limite è il massimo importo di unità di gas che sei disposto a spendere." }, @@ -475,9 +469,6 @@ "gasPriceNoDenom": { "message": "Prezzo del Gas" }, - "gasPriceCalculation": { - "message": "Calcoliamo il prezzo del gas suggerito in base al successo delle transazioni in rete." - }, "general": { "message": "Generale" }, @@ -906,9 +897,6 @@ "revealSeedWordsWarning": { "message": "Non ripristinare la tua frase seed in pubblico!. Queste parole possono essere usate per rubare il tuo account." }, - "revert": { - "message": "Ripristina" - }, "remove": { "message": "rimuovi" }, diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index 18dfb068e..91a417449 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -121,9 +121,6 @@ "balance": { "message": "残高:" }, - "balanceIsInsufficientGas": { - "message": "現在のガス総量に対して残高が不足しています" - }, "blockiesIdenticon": { "message": "Blockies Identicon を使用" }, @@ -240,18 +237,12 @@ "gasLimit": { "message": "ガスリミット" }, - "gasLimitCalculation": { - "message": "ネットワークの成功率を基にして、ガスリミットを提案しています。" - }, "gasLimitTooLow": { "message": "ガスリミットは最低21000です。" }, "gasPrice": { "message": "ガスプライス (GWEI)" }, - "gasPriceCalculation": { - "message": "ネットワークの成功率を基にして、ガスプライスを提案しています。" - }, "getEther": { "message": "Etherを取得する" }, @@ -426,9 +417,6 @@ "revealSeedWords": { "message": "パスフレーズを表示" }, - "revert": { - "message": "元に戻す" - }, "rinkeby": { "message": "Rinkebyテストネットワーク" }, diff --git a/app/_locales/kn/messages.json b/app/_locales/kn/messages.json index 7f3dd0f17..8f79e7966 100644 --- a/app/_locales/kn/messages.json +++ b/app/_locales/kn/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "ಮೊಬಲಗು ಹಳೆಯದಾಗಿರಬಹುದು" }, - "balanceIsInsufficientGas": { - "message": "ಪ್ರಸ್ತುತ ಗ್ಯಾಸ್ ಟೋಟಲ್‌ಗಾಗಿ ಸಾಕಷ್ಟು ಮೊಬಲಗು ಇಲ್ಲ" - }, "basic": { "message": "ಮೂಲ" }, @@ -472,9 +469,6 @@ "gasLimit": { "message": "ಗ್ಯಾಸ್ ಮಿತಿ" }, - "gasLimitCalculation": { - "message": "ನೆಟ್‌ವರ್ಕ್ ಯಶಸ್ಸಿನ ದರಗಳ ಆಧಾರದ ಮೇಲೆ ನಾವು ಸೂಚಿಸಲಾದ ಗ್ಯಾಸ್ ಮಿತಿಯನ್ನು ಲೆಕ್ಕಾಚಾರ ಮಾಡುತ್ತೇವೆ." - }, "gasLimitInfoModalContent": { "message": "ಗ್ಯಾಸ್‌ ಮಿತಿ ಎಂದರೆ ನೀವು ಖರ್ಚು ಮಾಡಲು ಸಿದ್ಧವಿರುವ ಗ್ಯಾಸ್‌ನ ಗರಿಷ್ಠ ಪ್ರಮಾಣ." }, @@ -496,9 +490,6 @@ "gasPriceNoDenom": { "message": "ಗ್ಯಾಸ್ ದರ" }, - "gasPriceCalculation": { - "message": "ನೆಟ್‌ವರ್ಕ್ ಯಶಸ್ಸಿನ ದರಗಳ ಆಧಾರದ ಮೇಲೆ ನಾವು ಸೂಚಿಸಿದ ಗ್ಯಾಸ್ ದರಗಳನ್ನು ಲೆಕ್ಕ ಹಾಕುತ್ತೇವೆ." - }, "general": { "message": "ಸಾಮಾನ್ಯ" }, @@ -943,9 +934,6 @@ "revealSeedWordsWarning": { "message": "ಈ ಪದಗಳನ್ನು ನಿಮ್ಮ ಎಲ್ಲಾ ಖಾತೆಗಳನ್ನು ಕದಿಯಲು ಬಳಸಬಹುದು." }, - "revert": { - "message": "ಹಿಂತಿರುಗಿಸಿ" - }, "remove": { "message": "ತೆಗೆದುಹಾಕು" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index bd412c75c..3c99005b8 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "잔액이 오래된 정보일 수 있습니다" }, - "balanceIsInsufficientGas": { - "message": "현재 가스 총합에 대해 잔액이 부족합니다" - }, "blockExplorerUrl": { "message": "익스플로러 차단" }, @@ -469,9 +466,6 @@ "gasLimit": { "message": "가스 한도" }, - "gasLimitCalculation": { - "message": "네트워크 성공률을 기반으로 적합한 가스 한도를 계산합니다." - }, "gasLimitInfoModalContent": { "message": "가스 한도는 당신이 기꺼이 소비할 수 있는 가스의 최대 수량입니다." }, @@ -493,9 +487,6 @@ "gasPriceNoDenom": { "message": "가스 가격" }, - "gasPriceCalculation": { - "message": "네트워크 성공률을 기반으로 적합한 가스 가격을 계산합니다." - }, "general": { "message": "일반" }, @@ -934,9 +925,6 @@ "revealSeedWordsWarning": { "message": "이 단어 모음은 당신의 모든 계정을 훔치는데 사용할 수 있습니다." }, - "revert": { - "message": "되돌림" - }, "remove": { "message": "제거" }, diff --git a/app/_locales/lt/messages.json b/app/_locales/lt/messages.json index 8cc785b2e..7c800d81a 100644 --- a/app/_locales/lt/messages.json +++ b/app/_locales/lt/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Likutis gali būti pasenęs" }, - "balanceIsInsufficientGas": { - "message": "Nepakankamas dabartinio bendro dujų kiekio likutis" - }, "basic": { "message": "Bendrieji" }, @@ -472,9 +469,6 @@ "gasLimit": { "message": "Dujų apribojimas" }, - "gasLimitCalculation": { - "message": "Siūlomą dujų apribojimą apskaičiuojame remdamiesi tinklo sėkmės rezultatais." - }, "gasLimitInfoModalContent": { "message": "Dujų apribojimas yra maksimalus dujų vienetų, kuriuos pageidaujate išleisti, skaičius." }, @@ -496,9 +490,6 @@ "gasPriceNoDenom": { "message": "Dujų kaina" }, - "gasPriceCalculation": { - "message": "Siūlomas dujų kainas apskaičiuojame remdamiesi tinklo sėkmės rezultatais." - }, "general": { "message": "Bendra" }, @@ -943,9 +934,6 @@ "revealSeedWordsWarning": { "message": "Šiuos žodžius galima panaudoti visoms jūsų paskyroms pavogti." }, - "revert": { - "message": "Grįžti" - }, "remove": { "message": "Pašalinti" }, diff --git a/app/_locales/lv/messages.json b/app/_locales/lv/messages.json index 91078dab4..303774c35 100644 --- a/app/_locales/lv/messages.json +++ b/app/_locales/lv/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Bilance var nebūt aktuāla" }, - "balanceIsInsufficientGas": { - "message": "Nepietiekama bilance pašreizējam Gas daudzumam" - }, "basic": { "message": "Pamata" }, @@ -468,9 +465,6 @@ "gasLimit": { "message": "Gas robežvērtība" }, - "gasLimitCalculation": { - "message": "Mēs aprēķinām ieteikto Gas robežvērtību, pamatojoties uz tīkla panākumu rādītājiem." - }, "gasLimitInfoModalContent": { "message": "Gas robežvērtība ir maksimālais Gas vienību skaits, ko vēlaties tērēt." }, @@ -492,9 +486,6 @@ "gasPriceNoDenom": { "message": "Gas cena" }, - "gasPriceCalculation": { - "message": "Mēs aprēķinām ieteiktās Gas cenas, pamatojoties uz tīkla panākumu rādītājiem." - }, "general": { "message": "Vispārīgi" }, @@ -939,9 +930,6 @@ "revealSeedWordsWarning": { "message": "Šos vārdus var izmantot visu jūsu kontu nolaupīšanai." }, - "revert": { - "message": "Atgriezt" - }, "remove": { "message": "Noņemt" }, diff --git a/app/_locales/ms/messages.json b/app/_locales/ms/messages.json index 24238f8e8..172009ec0 100644 --- a/app/_locales/ms/messages.json +++ b/app/_locales/ms/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Baki mungkin lapuk" }, - "balanceIsInsufficientGas": { - "message": "Baki tidak mencukupi untuk jumlah keseluruhan gas semasa" - }, "basic": { "message": "Asas" }, @@ -456,9 +453,6 @@ "gasLimit": { "message": "Had Gas" }, - "gasLimitCalculation": { - "message": "Kami mengira had gas yang dicadangkan berdasarkan kadar kejayaan rangkaian." - }, "gasLimitInfoModalContent": { "message": "Had gas ialah jumlah maksimum unit gas yang anda sedia belanjakan." }, @@ -480,9 +474,6 @@ "gasPriceNoDenom": { "message": "Harga Gas" }, - "gasPriceCalculation": { - "message": "Kami mengira harga gas disyorkan berdasarkan kadar kejayaan rangkaian." - }, "general": { "message": "Am" }, @@ -914,9 +905,6 @@ "revealSeedWordsWarning": { "message": "Perkataan ini boleh digunakan untuk mencuri kesemua akaun anda." }, - "revert": { - "message": "Undur" - }, "remove": { "message": "Alih keluar" }, diff --git a/app/_locales/nl/messages.json b/app/_locales/nl/messages.json index 3ff9bc734..8c5032ad3 100644 --- a/app/_locales/nl/messages.json +++ b/app/_locales/nl/messages.json @@ -40,9 +40,6 @@ "balance": { "message": "Balans:" }, - "balanceIsInsufficientGas": { - "message": "Onvoldoende saldo voor huidig ​​gastotaal" - }, "blockiesIdenticon": { "message": "Gebruik Blockies Identicon" }, @@ -162,18 +159,12 @@ "gasLimit": { "message": "Gaslimiet" }, - "gasLimitCalculation": { - "message": "We berekenen de voorgestelde gaslimiet op basis van succespercentages van het netwerk." - }, "gasLimitTooLow": { "message": "De gaslimiet moet minstens 21000 zijn" }, "gasPrice": { "message": "Gasprijs (GWEI)" }, - "gasPriceCalculation": { - "message": "We berekenen de voorgestelde gasprijzen op basis van succespercentages van het netwerk." - }, "getEther": { "message": "Krijg Ether" }, @@ -350,9 +341,6 @@ "revealSeedWordsWarning": { "message": "Zorg dat je back-up woorden niet op een openbare plaats bekijkt! Deze woorden kunnen worden gebruikt om al uw accounts opnieuw te genereren (en dus uw account te stelen)." }, - "revert": { - "message": "terugkeren" - }, "rinkeby": { "message": "Rinkeby testnetwerk" }, diff --git a/app/_locales/no/messages.json b/app/_locales/no/messages.json index 8c0b74eae..a1ec7e119 100644 --- a/app/_locales/no/messages.json +++ b/app/_locales/no/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Saldoen kan utløpe" }, - "balanceIsInsufficientGas": { - "message": "Utilstrekkelig dekning for nåværende datakrafttotal" - }, "basic": { "message": "Enkle" }, @@ -465,9 +462,6 @@ "gasLimit": { "message": "Datakraftsgrense " }, - "gasLimitCalculation": { - "message": "Vi kalkulerer den foreslåtte gassgrensen baser på nettverkets suksessrater." - }, "gasLimitInfoModalContent": { "message": "Datakraftgrense er det maksimale antall datakraft du er vilig til å benytte. " }, @@ -489,9 +483,6 @@ "gasPriceNoDenom": { "message": "Datakraft" }, - "gasPriceCalculation": { - "message": "Vi kalkulerer den foreslåtte datakraftprisen basert på sukssesspriser for nettverk. " - }, "general": { "message": "Generell" }, @@ -933,9 +924,6 @@ "revealSeedWordsWarning": { "message": "Disse ordene kan brukes for å stjele alle kontoene dine. " }, - "revert": { - "message": "Tilbakestill " - }, "remove": { "message": "Fjern" }, diff --git a/app/_locales/ph/messages.json b/app/_locales/ph/messages.json index 1a3807ad5..85ba6639d 100644 --- a/app/_locales/ph/messages.json +++ b/app/_locales/ph/messages.json @@ -34,9 +34,6 @@ "balance": { "message": "Balanse:" }, - "balanceIsInsufficientGas": { - "message": "Kulang ang balanse para sa kasalukuyang gas total" - }, "buyCoinSwitch": { "message": "Bumili sa CoinSwitch" }, @@ -135,15 +132,9 @@ "fromShapeShift": { "message": "Mula sa ShapeShift" }, - "gasLimitCalculation": { - "message": "Kinalkula namin ang iminungkahing gas limit base sa network success rates." - }, "gasLimitTooLow": { "message": "Ang gas limit ay hindi dabat bababa sa 21000" }, - "gasPriceCalculation": { - "message": "Kinalkula namin ang iminungkahing gas prices base sa network success rates." - }, "getEther": { "message": "Kumuha ng Ether" }, @@ -249,9 +240,6 @@ "required": { "message": "Kailangan" }, - "revert": { - "message": "Ibalik" - }, "save": { "message": "I-save" }, diff --git a/app/_locales/pl/messages.json b/app/_locales/pl/messages.json index c306d52a2..b53b4ebb0 100644 --- a/app/_locales/pl/messages.json +++ b/app/_locales/pl/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Saldo może być nieaktualne" }, - "balanceIsInsufficientGas": { - "message": "Niewystarczająca ilość środków na opłatę za gaz" - }, "basic": { "message": "Podstawy" }, @@ -469,9 +466,6 @@ "gasLimit": { "message": "Limit gazu" }, - "gasLimitCalculation": { - "message": "Obliczamy sugerowany limit gazu na podstawie danych z transakcji w sieci." - }, "gasLimitInfoModalContent": { "message": "Limit gazu to maksymalna ilość jednostek gazu, którą jesteś skłonny użyć w transakcji." }, @@ -493,9 +487,6 @@ "gasPriceNoDenom": { "message": "Cena gazu" }, - "gasPriceCalculation": { - "message": "Obliczamy ceny gazu na podstawie danych z transakcji w sieci." - }, "general": { "message": "Ogólne" }, @@ -934,9 +925,6 @@ "revealSeedWordsWarning": { "message": "Te słowa mogą być użyte żeby ukraść Twoje konta." }, - "revert": { - "message": "Wycofaj" - }, "remove": { "message": "usuń" }, diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index 3e19fbba1..47439021b 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -43,9 +43,6 @@ "balance": { "message": "Saldo:" }, - "balanceIsInsufficientGas": { - "message": "Saldo insuficiente para a quantidade de gas total" - }, "blockiesIdenticon": { "message": "Usar Blockies Identicon" }, @@ -168,18 +165,12 @@ "gasLimit": { "message": "Limite de Gas" }, - "gasLimitCalculation": { - "message": "Calculamos o limite sugerido do gas com base nas taxas de sucesso da rede." - }, "gasLimitTooLow": { "message": "Limite de Gas deve ser no mínimo 21000" }, "gasPrice": { "message": "Preço Gas (GWEI)" }, - "gasPriceCalculation": { - "message": "Calculamos o gas sugerido com base nas taxas de sucesso da rede." - }, "getEther": { "message": "Obter Ether" }, @@ -360,9 +351,6 @@ "revealSeedWordsWarning": { "message": "Não revele as palavras seed num espaço público! Estas palavras podem ser usadas para roubar todas as suas contas." }, - "revert": { - "message": "Reverter" - }, "rinkeby": { "message": "Rede de Teste Rinkeby" }, diff --git a/app/_locales/pt_BR/messages.json b/app/_locales/pt_BR/messages.json index 6abff008f..1f32af89c 100644 --- a/app/_locales/pt_BR/messages.json +++ b/app/_locales/pt_BR/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "O saldo pode estar desatualizado" }, - "balanceIsInsufficientGas": { - "message": "Saldo insuficiente pelo total de Gas atual" - }, "basic": { "message": "Básicas" }, @@ -466,9 +463,6 @@ "gasLimit": { "message": "Limite de Gás" }, - "gasLimitCalculation": { - "message": "Nós calculamos o limite de gás sugerido com base nas taxas de sucesso da rede." - }, "gasLimitInfoModalContent": { "message": "O limite de gás é a quantidade máxima de unidades de gás que você está disposto a gastar." }, @@ -490,9 +484,6 @@ "gasPriceNoDenom": { "message": "Preço do Gás" }, - "gasPriceCalculation": { - "message": "Nós calculamos os preços de gás sugeridos com base nas taxas de sucesso da rede." - }, "general": { "message": "Geral" }, @@ -928,9 +919,6 @@ "revealSeedWordsWarning": { "message": "Essas palavras podem ser usadas para roubar todas as suas contas." }, - "revert": { - "message": "Reverter" - }, "remove": { "message": "Remover" }, diff --git a/app/_locales/ro/messages.json b/app/_locales/ro/messages.json index faaf904b8..bad3f6293 100644 --- a/app/_locales/ro/messages.json +++ b/app/_locales/ro/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Se poate ca soldul să nu fie actualizat" }, - "balanceIsInsufficientGas": { - "message": "Sold insuficient pentru actuala valoare totală de gaz." - }, "basic": { "message": "De bază" }, @@ -468,9 +465,6 @@ "gasLimit": { "message": "Limită gas" }, - "gasLimitCalculation": { - "message": "Calculăm limita de gas sugerată pe baza ratelor de succes ale rețelei." - }, "gasLimitInfoModalContent": { "message": "Limita gaz este numărul maxim de unități de gaz pe care sunteți dispus(ă) să le cheltuiți." }, @@ -492,9 +486,6 @@ "gasPriceNoDenom": { "message": "Preț gas" }, - "gasPriceCalculation": { - "message": "Calculăm prețurile sugerate pentru gas pe baza ratelor de succes ale rețelei." - }, "generalSettingsDescription": { "message": "Schimb valutar, moneda principală, limba, blockies identicon" }, @@ -930,9 +921,6 @@ "revealSeedWordsWarning": { "message": "Aceste cuvinte pot fi folosite pentru a vă fura toate conturile." }, - "revert": { - "message": "Reveniți" - }, "remove": { "message": "Elimină" }, diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index b80f8f219..2f1302d43 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -46,9 +46,6 @@ "balance": { "message": "Баланс:" }, - "balanceIsInsufficientGas": { - "message": "Недостаточный баланс для текущего объема газа" - }, "blockiesIdenticon": { "message": "Использовать Blockies Identicon" }, @@ -195,18 +192,12 @@ "gasLimit": { "message": "Лимит газа" }, - "gasLimitCalculation": { - "message": "Мы расчитываем предлагаемый лимит газа на основании успешных ставок в сети." - }, "gasLimitTooLow": { "message": "Лимит газа должен быть как минимум 21000" }, "gasPrice": { "message": "Цена за газ (GWEI)" }, - "gasPriceCalculation": { - "message": "Мы расчитываем предлагаемые цены за газ на основании успешных ставок в сети." - }, "getEther": { "message": "Получить Ether" }, @@ -396,9 +387,6 @@ "revealSeedWordsWarning": { "message": "Не восстанавливайте ключевую фразу в общественном месте! Она может быть использована для кражи всех ваших счетов." }, - "revert": { - "message": "Восстановить" - }, "rinkeby": { "message": "Тестовая сеть Rinkeby" }, diff --git a/app/_locales/sk/messages.json b/app/_locales/sk/messages.json index d975048d8..43b235e9a 100644 --- a/app/_locales/sk/messages.json +++ b/app/_locales/sk/messages.json @@ -136,9 +136,6 @@ "balanceOutdated": { "message": "Zostatok môže byť neaktuálny" }, - "balanceIsInsufficientGas": { - "message": "Nedostatek prostředků pro aktuální množství paliva" - }, "basic": { "message": "Základné" }, @@ -463,9 +460,6 @@ "gasLimit": { "message": "Limit paliva" }, - "gasLimitCalculation": { - "message": "Počítáme doporučený limit paliva na základě úspěšnosti v síti." - }, "gasLimitInfoModalContent": { "message": "Limit GAS je maximálne množstvo jednotiek GAS, ktoré ste ochotní minúť." }, @@ -487,9 +481,6 @@ "gasPriceNoDenom": { "message": "Cena GAS" }, - "gasPriceCalculation": { - "message": "Počítáme doporučenou cenu paliva na základě úspěšnosti v síti." - }, "general": { "message": "Všeobecne" }, @@ -909,9 +900,6 @@ "revealSeedWordsWarning": { "message": "Nebnovujte slova klíčové fráze na veřejnosti! Tato slova mohou být použita k odcizení veškerých vyašich účtů." }, - "revert": { - "message": "Zvrátit" - }, "remove": { "message": "Odstrániť" }, diff --git a/app/_locales/sl/messages.json b/app/_locales/sl/messages.json index 274270903..b1e9e4dd8 100644 --- a/app/_locales/sl/messages.json +++ b/app/_locales/sl/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Stanje morda ni posodobljeno" }, - "balanceIsInsufficientGas": { - "message": "Nezadnosten znesek za trenutni gas" - }, "basic": { "message": "Osnovno" }, @@ -469,9 +466,6 @@ "functionType": { "message": "Vrsta funkcije" }, - "gasLimitCalculation": { - "message": "Priporočen gas limit je izračunan glede na omrežje." - }, "gasLimitInfoModalContent": { "message": "Omejitev plina je največja količina enot plina, ki ste jo pripravljeni porabiti." }, @@ -493,9 +487,6 @@ "gasPriceNoDenom": { "message": "Gas price" }, - "gasPriceCalculation": { - "message": "Priporočen gas price je izračunan glede na omrežje." - }, "general": { "message": "Splošno" }, @@ -925,9 +916,6 @@ "revealSeedWordsWarning": { "message": "S temi besedami lahko kdorkoli ukrade vse vaše račune." }, - "revert": { - "message": "Obnovi" - }, "remove": { "message": "izbriši" }, diff --git a/app/_locales/sr/messages.json b/app/_locales/sr/messages.json index a7afb91c1..4d72762d0 100644 --- a/app/_locales/sr/messages.json +++ b/app/_locales/sr/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Saldo je možda zastario" }, - "balanceIsInsufficientGas": { - "message": "Nedovoljan iznos za trenutni ukupni gas" - }, "basic": { "message": "Основна" }, @@ -469,9 +466,6 @@ "gasLimit": { "message": "Limit gasa" }, - "gasLimitCalculation": { - "message": "Izračunavamo predloženi limit za gas na osnovu stope uspešnosti mreže." - }, "gasLimitInfoModalContent": { "message": "Granica gasa je maksimalni iznos jedinica gasa koje ste voljni da potrošite." }, @@ -493,9 +487,6 @@ "gasPriceNoDenom": { "message": "Cena gas-a" }, - "gasPriceCalculation": { - "message": "Preračunavamo predložene cene za gas na osnovu stope uspešnosti mreže." - }, "general": { "message": "Opšte" }, @@ -934,9 +925,6 @@ "revealSeedWordsWarning": { "message": "Ove reči se mogu iskoristiti za krađu svih vaših naloga." }, - "revert": { - "message": "Vrati" - }, "remove": { "message": "Уклони" }, diff --git a/app/_locales/sv/messages.json b/app/_locales/sv/messages.json index cbe7afd89..e0ec851ee 100644 --- a/app/_locales/sv/messages.json +++ b/app/_locales/sv/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Saldot kanske inte är uppdaterat" }, - "balanceIsInsufficientGas": { - "message": "Otillräckligt saldo för aktuell totalsumma för gas" - }, "basic": { "message": "Grunder" }, @@ -462,9 +459,6 @@ "gasLimit": { "message": "Gasgräns" }, - "gasLimitCalculation": { - "message": "Vi beräknar den föreslagna gasgränsen baserat på nätverket framgångsgrad." - }, "gasLimitInfoModalContent": { "message": "Gasgräns innebär det maximala antalet gasenheter som du är villig att spendera." }, @@ -486,9 +480,6 @@ "gasPriceNoDenom": { "message": "Gaspris" }, - "gasPriceCalculation": { - "message": "Vi beräknar de föreslagna gaspriserna baserat på nätverkets resultat." - }, "general": { "message": "Allmänt" }, @@ -927,9 +918,6 @@ "revealSeedWordsWarning": { "message": "De här orden kan användas för att stjäla alla dina konton." }, - "revert": { - "message": "Återställ" - }, "remove": { "message": "Ta bort" }, diff --git a/app/_locales/sw/messages.json b/app/_locales/sw/messages.json index f5e055861..2ab4f52a5 100644 --- a/app/_locales/sw/messages.json +++ b/app/_locales/sw/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Salio linaweza kuwa limepitwa na wakati" }, - "balanceIsInsufficientGas": { - "message": "Salio halitoshi kwa jumla ya sasa ya gesi" - }, "basic": { "message": "Msingi" }, @@ -462,9 +459,6 @@ "gasLimit": { "message": "Kikomo cha Gesi" }, - "gasLimitCalculation": { - "message": "Tunakokotoa kikomo cha gesi kilichopendekezwa kulingana na viwango vya mafanikio ya mtandao." - }, "gasLimitInfoModalContent": { "message": "Ukomo wa gesi ni kiwango cha juu kabisa cha cha vizio vya gesi ambavyo upo tayari kutumia." }, @@ -486,9 +480,6 @@ "gasPriceNoDenom": { "message": "Bei ya Gesi" }, - "gasPriceCalculation": { - "message": "Tunakokotoa bei za gesi zilizopendekzwa kulingana na viwango vya kufanikiwa mtandao." - }, "general": { "message": "Jumla" }, @@ -921,9 +912,6 @@ "revealSeedWordsWarning": { "message": "Maneno haya yanaweza kutumika kuiba akanti zako zote." }, - "revert": { - "message": "Batilisha" - }, "remove": { "message": "Ondoa" }, diff --git a/app/_locales/ta/messages.json b/app/_locales/ta/messages.json index 5d70662b5..ab4a2d996 100644 --- a/app/_locales/ta/messages.json +++ b/app/_locales/ta/messages.json @@ -46,9 +46,6 @@ "balance": { "message": "இருப்பு:" }, - "balanceIsInsufficientGas": { - "message": "நடப்பு வாயு மொத்தம் போதுமான சமநிலை" - }, "blockiesIdenticon": { "message": "ப்ளாக்கிஸ் ஐடென்டிகோன் பயன்பாட்டு" }, @@ -189,18 +186,12 @@ "gasLimit": { "message": "எரிவாயு வரம்பு" }, - "gasLimitCalculation": { - "message": "நெட்வொர்க் வெற்றி விகிதங்களின் அடிப்படையில் பரிந்துரைக்கப்பட்ட எரிவாயு வரம்பை நாங்கள் கணக்கிடுகிறோம்." - }, "gasLimitTooLow": { "message": "எரிவாயு வரம்பு குறைந்தது 21000 ஆக இருக்க வேண்டும்" }, "gasPrice": { "message": "எரிவாயு விலை (GWEI)" }, - "gasPriceCalculation": { - "message": "நெட்வொர்க் வெற்றி விகிதங்களின் அடிப்படையில் பரிந்துரைக்கப்பட்ட எரிவாயு விலைகளை நாங்கள் கணக்கிடுகிறோம்." - }, "getEther": { "message": "ஈத்தர் கிடைக்கும்" }, @@ -396,9 +387,6 @@ "revealSeedWordsWarning": { "message": "உங்கள் விதை வார்த்தைகள் ஒரு பொது இடத்தில் மீட்க வேண்டாம்! உங்கள் எல்லா கணக்குகளையும் திருட இந்த வார்த்தைகள் பயன்படுத்தப்படலாம்." }, - "revert": { - "message": "மாற்றியமை" - }, "rinkeby": { "message": "ரிங்கெப்ய டெஸ்ட் நெட்வொர்க்" }, diff --git a/app/_locales/th/messages.json b/app/_locales/th/messages.json index d019685f5..01cc020f0 100644 --- a/app/_locales/th/messages.json +++ b/app/_locales/th/messages.json @@ -52,9 +52,6 @@ "balance": { "message": "ยอดคงเหลือ:" }, - "balanceIsInsufficientGas": { - "message": "ยอดคงเหลือไม่พอสำหรับจ่ายค่าแก๊สทั้งหมด" - }, "blockiesIdenticon": { "message": "ใช้งาน Blockies Identicon" }, @@ -243,18 +240,12 @@ "gasLimit": { "message": "วงเงินแก็ส" }, - "gasLimitCalculation": { - "message": "เราแนะนำวงเงินแก็สตามความสำเร็จบนเครือข่าย" - }, "gasLimitTooLow": { "message": "วงเงินแก็สต้องอย่างน้อย 21000" }, "gasPrice": { "message": "ราคาแก๊ส (GWEI)" }, - "gasPriceCalculation": { - "message": "เราแนะนำราคาแก็สตามความสำเร็จบนเครือข่าย" - }, "general": { "message": "ทั่วไป" }, @@ -465,9 +456,6 @@ "revealSeedWordsWarning": { "message": "อย่าเปิดเผยคำกลุ่มคำชีดของคุณในที่สาธารณะ! คำเหล่านี้สามารถใช้เพื่อขโมยบัญชีทั้งหมดของคุณ" }, - "revert": { - "message": "ย้อนกลับ" - }, "rinkeby": { "message": "เครือข่ายทดสอบ Rinkeby" }, diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index 46242c50f..f21f35be8 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -46,9 +46,6 @@ "balance": { "message": "Bakiye:" }, - "balanceIsInsufficientGas": { - "message": "Toplam gas için yetersiz bakiye" - }, "blockiesIdenticon": { "message": "Blockies Identicon kullan" }, @@ -195,18 +192,12 @@ "gasLimit": { "message": "Gas Limiti" }, - "gasLimitCalculation": { - "message": "Önerilen gas limitini ağ başarı oranını baz alarak hesaplıyoruz." - }, "gasLimitTooLow": { "message": "Gas limiti en az 21000 olmalıdır" }, "gasPrice": { "message": "Gas Fiyatı (GWEI)" }, - "gasPriceCalculation": { - "message": "Önerilen gas fiyatını ağ başarı oranını baz alarak hesaplıyoruz." - }, "getEther": { "message": "Ether Al" }, @@ -402,9 +393,6 @@ "revealSeedWordsWarning": { "message": "Açık bir yerde kaynak kelimeliriniz geri getirmeyin! Bu kelimeler tüm hesaplarınızı çalmak için kullanılabilir." }, - "revert": { - "message": "Geri döndür" - }, "rinkeby": { "message": "Rinkeby Test Ağı" }, diff --git a/app/_locales/uk/messages.json b/app/_locales/uk/messages.json index 60daf4bab..c735a98b0 100644 --- a/app/_locales/uk/messages.json +++ b/app/_locales/uk/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "Залишок можливо вже змінився" }, - "balanceIsInsufficientGas": { - "message": "Недостатній баланс для поточної загальної кількості газу" - }, "basic": { "message": "Основні параметри" }, @@ -472,9 +469,6 @@ "gasLimit": { "message": "Ліміт газу" }, - "gasLimitCalculation": { - "message": "Ми підраховуємо пропонований ліміт пального на основі рейтингів успішності мережі." - }, "gasLimitInfoModalContent": { "message": "Ліміт газу – максимальна кількість одиниць газу, яку ви бажаєте витратити." }, @@ -496,9 +490,6 @@ "gasPriceNoDenom": { "message": "Ціна Газу" }, - "gasPriceCalculation": { - "message": "Ми розрахуємо рекомендовані ціни газу на основі відсотка успішних транзакцій у мережі." - }, "general": { "message": "Загальні" }, @@ -943,9 +934,6 @@ "revealSeedWordsWarning": { "message": "Ці слова можуть бути використані, щоб вкрасти всі ваші облікові записи." }, - "revert": { - "message": "Повернути" - }, "remove": { "message": "Видалити" }, diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index 6136403ba..cf668f161 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -37,9 +37,6 @@ "balance": { "message": "Số dư:" }, - "balanceIsInsufficientGas": { - "message": "Số dư không đủ để thanh toán tổng tiền gas hiện tại" - }, "buyCoinSwitch": { "message": "Mua trên CoinSwitch" }, @@ -144,18 +141,12 @@ "gasLimit": { "message": "Hạn mức ga" }, - "gasLimitCalculation": { - "message": "Chúng tôi tính toán và gợi ý một hạn mức ga cụ thể dựa trên tỷ lệ thành công của hệ thống." - }, "gasLimitTooLow": { "message": "Hạn mức ga phải đạt tối thiểu 21000" }, "gasPrice": { "message": "Giá ga (GWEI)" }, - "gasPriceCalculation": { - "message": "Chúng tôi tính toán và gợi ý một giá ga cụ thể dựa trên tỷ lệ thành công của hệ thống." - }, "getEther": { "message": "Lấy Ether" }, @@ -285,9 +276,6 @@ "required": { "message": "Yêu cầu" }, - "revert": { - "message": "Chuyển lại" - }, "rinkeby": { "message": "Mạng thử nghiệm Rinkeby" }, diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index 2bc722f58..3d2ff6f69 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "余额可能已过期" }, - "balanceIsInsufficientGas": { - "message": "当前余额不足以支付 Gas" - }, "basic": { "message": "基本" }, @@ -469,9 +466,6 @@ "functionType": { "message": "功能类型" }, - "gasLimitCalculation": { - "message": "我们根据网络成功率计算建议的 Gas Limit。" - }, "gasLimitInfoModalContent": { "message": "天然气限制即您个人希望购买的最大单位数量。" }, @@ -490,9 +484,6 @@ "gasPriceNoDenom": { "message": "天然气价格" }, - "gasPriceCalculation": { - "message": "我们根据网络成功率计算建议的 Gas Price" - }, "general": { "message": "通用" }, @@ -925,9 +916,6 @@ "revealSeedWordsWarning": { "message": "助记词可以用来窃取您的所有帐户." }, - "revert": { - "message": "还原" - }, "remove": { "message": "移除" }, diff --git a/app/_locales/zh_TW/messages.json b/app/_locales/zh_TW/messages.json index a12595961..c44bfaf37 100644 --- a/app/_locales/zh_TW/messages.json +++ b/app/_locales/zh_TW/messages.json @@ -139,9 +139,6 @@ "balanceOutdated": { "message": "顯示餘額不一定是最新資訊" }, - "balanceIsInsufficientGas": { - "message": "當前餘額不足以支付 Gas" - }, "basic": { "message": "基本" }, @@ -469,9 +466,6 @@ "gasLimit": { "message": "Gas 上限" }, - "gasLimitCalculation": { - "message": "我們根據網路成功率算出建議的 Gas 上限。" - }, "gasLimitInfoModalContent": { "message": "Gas 上限代表願意為交易手續費所付出的最高總價" }, @@ -493,9 +487,6 @@ "gasPriceNoDenom": { "message": "Gas 價格" }, - "gasPriceCalculation": { - "message": "我們根據網路成功率算出建議的 Gas 價格" - }, "general": { "message": "一般" }, @@ -925,9 +916,6 @@ "revealSeedWordsWarning": { "message": "絕對不要在公共場合輸入助憶詞!這可被用來竊取您的帳戶。" }, - "revert": { - "message": "還原" - }, "remove": { "message": "移除" }, diff --git a/ui/app/components/app/customize-gas-modal/gas-modal-card.js b/ui/app/components/app/customize-gas-modal/gas-modal-card.js deleted file mode 100644 index a6dc11b72..000000000 --- a/ui/app/components/app/customize-gas-modal/gas-modal-card.js +++ /dev/null @@ -1,38 +0,0 @@ -import React, { Component } from 'react' -import { inherits } from 'util' -import InputNumber from '../input-number.js' - -export default GasModalCard - -inherits(GasModalCard, Component) -function GasModalCard () { - Component.call(this) -} - -GasModalCard.prototype.render = function GasModalCard () { - const { - onChange, - unitLabel, - value, - min, - step, - title, - copy, - } = this.props - - return ( -
-
{title}
-
{copy}
- -
- ) -} - diff --git a/ui/app/components/app/customize-gas-modal/index.js b/ui/app/components/app/customize-gas-modal/index.js deleted file mode 100644 index f95f58e53..000000000 --- a/ui/app/components/app/customize-gas-modal/index.js +++ /dev/null @@ -1,388 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { inherits } from 'util' -import { connect } from 'react-redux' -import BigNumber from 'bignumber.js' -import * as actions from '../../../store/actions' -import GasModalCard from './gas-modal-card' -import Button from '../../ui/button' - -import ethUtil from 'ethereumjs-util' - -import { - updateSendErrors, -} from '../../../ducks/send/send.duck' - -import { MIN_GAS_PRICE_DEC, MIN_GAS_LIMIT_DEC, MIN_GAS_PRICE_GWEI } from '../../../pages/send/send.constants' -import { isBalanceSufficient } from '../../../pages/send/send.utils' - -import { - conversionUtil, - multiplyCurrencies, - conversionGreaterThan, - conversionMax, - subtractCurrencies, -} from '../../../helpers/utils/conversion-util' - -import { - getGasIsLoading, - getForceGasMin, - conversionRateSelector, - getSendAmount, - getSelectedToken, - getSendFrom, - getCurrentAccountWithSendEtherInfo, - getSelectedTokenToFiatRate, - getSendMaxModeState, -} from '../../../selectors/selectors' - -import { getGasPrice, getGasLimit } from '../../../pages/send/send.selectors' - -function mapStateToProps (state) { - const selectedToken = getSelectedToken(state) - const currentAccount = getSendFrom(state) || getCurrentAccountWithSendEtherInfo(state) - const conversionRate = conversionRateSelector(state) - - return { - gasPrice: getGasPrice(state), - gasLimit: getGasLimit(state), - gasIsLoading: getGasIsLoading(state), - forceGasMin: getForceGasMin(state), - conversionRate, - amount: getSendAmount(state), - maxModeOn: getSendMaxModeState(state), - balance: currentAccount.balance, - primaryCurrency: selectedToken && selectedToken.symbol, - selectedToken, - amountConversionRate: selectedToken ? getSelectedTokenToFiatRate(state) : conversionRate, - } -} - -function mapDispatchToProps (dispatch) { - return { - hideModal: () => dispatch(actions.hideModal()), - setGasPrice: newGasPrice => dispatch(actions.setGasPrice(newGasPrice)), - setGasLimit: newGasLimit => dispatch(actions.setGasLimit(newGasLimit)), - setGasTotal: newGasTotal => dispatch(actions.setGasTotal(newGasTotal)), - updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)), - updateSendErrors: error => dispatch(updateSendErrors(error)), - } -} - -function getFreshState (props) { - const gasPrice = props.gasPrice || MIN_GAS_PRICE_DEC - const gasLimit = props.gasLimit || MIN_GAS_LIMIT_DEC - - const gasTotal = multiplyCurrencies(gasLimit, gasPrice, { - toNumericBase: 'hex', - multiplicandBase: 16, - multiplierBase: 16, - }) - - return { - gasPrice, - gasLimit, - gasTotal, - error: null, - priceSigZeros: '', - priceSigDec: '', - } -} - -inherits(CustomizeGasModal, Component) -function CustomizeGasModal (props) { - Component.call(this) - - const originalState = getFreshState(props) - this.state = { - ...originalState, - originalState, - } -} - -CustomizeGasModal.contextTypes = { - t: PropTypes.func, - metricsEvent: PropTypes.func, -} - -export default connect(mapStateToProps, mapDispatchToProps)(CustomizeGasModal) - -CustomizeGasModal.prototype.UNSAFE_componentWillReceiveProps = function (nextProps) { - const currentState = getFreshState(this.props) - const { - gasPrice: currentGasPrice, - gasLimit: currentGasLimit, - } = currentState - const newState = getFreshState(nextProps) - const { - gasPrice: newGasPrice, - gasLimit: newGasLimit, - gasTotal: newGasTotal, - } = newState - const gasPriceChanged = currentGasPrice !== newGasPrice - const gasLimitChanged = currentGasLimit !== newGasLimit - - if (gasPriceChanged) { - this.setState({ - gasPrice: newGasPrice, - gasTotal: newGasTotal, - priceSigZeros: '', - priceSigDec: '', - }) - } - if (gasLimitChanged) { - this.setState({ gasLimit: newGasLimit, gasTotal: newGasTotal }) - } - if (gasLimitChanged || gasPriceChanged) { - this.validate({ gasLimit: newGasLimit, gasTotal: newGasTotal }) - } -} - -CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) { - const { metricsEvent } = this.context - const { - setGasPrice, - setGasLimit, - hideModal, - setGasTotal, - maxModeOn, - selectedToken, - balance, - updateSendAmount, - updateSendErrors, - } = this.props - const { - originalState, - } = this.state - - if (maxModeOn && !selectedToken) { - const maxAmount = subtractCurrencies( - ethUtil.addHexPrefix(balance), - ethUtil.addHexPrefix(gasTotal), - { toNumericBase: 'hex' } - ) - updateSendAmount(maxAmount) - } - - metricsEvent({ - eventOpts: { - category: 'Activation', - action: 'userCloses', - name: 'closeCustomizeGas', - }, - pageOpts: { - section: 'customizeGasModal', - component: 'customizeGasSaveButton', - }, - customVariables: { - gasPriceChange: (new BigNumber(ethUtil.addHexPrefix(gasPrice))).minus(new BigNumber(ethUtil.addHexPrefix(originalState.gasPrice))).toString(10), - gasLimitChange: (new BigNumber(ethUtil.addHexPrefix(gasLimit))).minus(new BigNumber(ethUtil.addHexPrefix(originalState.gasLimit))).toString(10), - }, - }) - - setGasPrice(ethUtil.addHexPrefix(gasPrice)) - setGasLimit(ethUtil.addHexPrefix(gasLimit)) - setGasTotal(ethUtil.addHexPrefix(gasTotal)) - updateSendErrors({ insufficientFunds: false }) - hideModal() -} - -CustomizeGasModal.prototype.revert = function () { - this.setState(this.state.originalState) -} - -CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) { - const { - amount, - balance, - selectedToken, - amountConversionRate, - conversionRate, - maxModeOn, - } = this.props - - let error = null - - const balanceIsSufficient = isBalanceSufficient({ - amount: selectedToken || maxModeOn ? '0' : amount, - gasTotal, - balance, - selectedToken, - amountConversionRate, - conversionRate, - }) - - if (!balanceIsSufficient) { - error = this.context.t('balanceIsInsufficientGas') - } - - const gasLimitTooLow = gasLimit && conversionGreaterThan( - { - value: MIN_GAS_LIMIT_DEC, - fromNumericBase: 'dec', - conversionRate, - }, - { - value: gasLimit, - fromNumericBase: 'hex', - }, - ) - - if (gasLimitTooLow) { - error = this.context.t('gasLimitTooLow') - } - - this.setState({ error }) - return error -} - -CustomizeGasModal.prototype.convertAndSetGasLimit = function (newGasLimit) { - const { gasPrice } = this.state - - const gasLimit = conversionUtil(newGasLimit, { - fromNumericBase: 'dec', - toNumericBase: 'hex', - }) - - const gasTotal = multiplyCurrencies(gasLimit, gasPrice, { - toNumericBase: 'hex', - multiplicandBase: 16, - multiplierBase: 16, - }) - - this.validate({ gasTotal, gasLimit }) - - this.setState({ gasTotal, gasLimit }) -} - -CustomizeGasModal.prototype.convertAndSetGasPrice = function (newGasPrice) { - const { gasLimit } = this.state - const sigZeros = String(newGasPrice).match(/^\d+[.]\d*?(0+)$/) - const sigDec = String(newGasPrice).match(/^\d+([.])0*$/) - - this.setState({ - priceSigZeros: sigZeros && sigZeros[1] || '', - priceSigDec: sigDec && sigDec[1] || '', - }) - - const gasPrice = conversionUtil(newGasPrice, { - fromNumericBase: 'dec', - toNumericBase: 'hex', - fromDenomination: 'GWEI', - toDenomination: 'WEI', - }) - - const gasTotal = multiplyCurrencies(gasLimit, gasPrice, { - toNumericBase: 'hex', - multiplicandBase: 16, - multiplierBase: 16, - }) - - this.validate({ gasTotal }) - - this.setState({ gasTotal, gasPrice }) -} - -CustomizeGasModal.prototype.render = function () { - const { hideModal, forceGasMin, gasIsLoading } = this.props - const { gasPrice, gasLimit, gasTotal, error, priceSigZeros, priceSigDec } = this.state - - let convertedGasPrice = conversionUtil(gasPrice, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - fromDenomination: 'WEI', - toDenomination: 'GWEI', - }) - - convertedGasPrice += convertedGasPrice.match(/[.]/) ? priceSigZeros : `${priceSigDec}${priceSigZeros}` - - let newGasPrice = gasPrice - if (forceGasMin) { - const convertedMinPrice = conversionUtil(forceGasMin, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - }) - convertedGasPrice = conversionMax( - { value: convertedMinPrice, fromNumericBase: 'dec' }, - { value: convertedGasPrice, fromNumericBase: 'dec' } - ) - newGasPrice = conversionMax( - { value: gasPrice, fromNumericBase: 'hex' }, - { value: forceGasMin, fromNumericBase: 'hex' } - ) - } - - const convertedGasLimit = conversionUtil(gasLimit, { - fromNumericBase: 'hex', - toNumericBase: 'dec', - }) - - if (gasIsLoading) { - return null - } - - const { t } = this.context - - return ( -
-
-
-
- {this.context.t('customGas')} -
-
-
-
- this.convertAndSetGasPrice(value)} - title={t('gasPrice')} - copy={t('gasPriceCalculation')} - gasIsLoading={gasIsLoading} - /> - this.convertAndSetGasLimit(value)} - title={t('gasLimit')} - copy={t('gasLimitCalculation')} - gasIsLoading={gasIsLoading} - /> -
-
- {error && ( -
- {error} -
- )} -
this.revert()}> - {t('revert')} -
-
- - -
-
-
-
- ) -} diff --git a/ui/app/components/app/input-number.js b/ui/app/components/app/input-number.js deleted file mode 100644 index d78690c46..000000000 --- a/ui/app/components/app/input-number.js +++ /dev/null @@ -1,81 +0,0 @@ -import React, { Component } from 'react' -import { inherits } from 'util' -import { addCurrencies, conversionGTE, conversionLTE, subtractCurrencies } from '../../helpers/utils/conversion-util' - -export default InputNumber - -inherits(InputNumber, Component) -function InputNumber () { - Component.call(this) - - this.setValue = this.setValue.bind(this) -} - -function isValidInput (text) { - const re = /^([1-9]\d*|0)(\.|\.\d*)?$/ - return re.test(text) -} - -function removeLeadingZeroes (str) { - return str.replace(/^0*(?=\d)/, '') -} - -InputNumber.prototype.setValue = function (newValue) { - newValue = removeLeadingZeroes(newValue) - if (newValue && !isValidInput(newValue)) { - return - } - const { fixed, min = -1, max = Infinity, onChange } = this.props - - newValue = fixed ? newValue.toFixed(4) : newValue - const newValueGreaterThanMin = conversionGTE( - { value: newValue || '0', fromNumericBase: 'dec' }, - { value: min, fromNumericBase: 'hex' }, - ) - - const newValueLessThanMax = conversionLTE( - { value: newValue || '0', fromNumericBase: 'dec' }, - { value: max, fromNumericBase: 'hex' }, - ) - if (newValueGreaterThanMin && newValueLessThanMax) { - onChange(newValue) - } else if (!newValueGreaterThanMin) { - onChange(min) - } else if (!newValueLessThanMax) { - onChange(max) - } -} - -InputNumber.prototype.render = function InputNumber () { - const { unitLabel, step = 1, placeholder, value } = this.props - - return ( -
- { - this.setValue(e.target.value) - }} - min={0} - /> - {unitLabel} -
-
this.setValue(addCurrencies(value, step, { toNumericBase: 'dec' }))} - > - -
-
this.setValue(subtractCurrencies(value, step, { toNumericBase: 'dec' }))} - > - -
-
-
- ) -} From 89e7dc2312a0025a5430bed6f8c83debb98fd07c Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 10 Jan 2020 15:35:46 -0330 Subject: [PATCH 102/689] Convert Modal component to ES6 class (#7783) --- ui/app/components/app/modals/modal.js | 100 +++++++++++++------------- 1 file changed, 49 insertions(+), 51 deletions(-) diff --git a/ui/app/components/app/modals/modal.js b/ui/app/components/app/modals/modal.js index 90057f7e0..46ca0cce6 100644 --- a/ui/app/components/app/modals/modal.js +++ b/ui/app/components/app/modals/modal.js @@ -1,6 +1,6 @@ +import PropTypes from 'prop-types' import React, { Component } from 'react' -import { inherits } from 'util' import { connect } from 'react-redux' import * as actions from '../../../store/actions' import { resetCustomData as resetCustomGasData } from '../../../ducks/gas/gas.duck' @@ -464,61 +464,59 @@ function mapDispatchToProps (dispatch) { } } -// Global Modal Component -inherits(Modal, Component) -function Modal () { - Component.call(this) -} - -export default connect(mapStateToProps, mapDispatchToProps)(Modal) +class Modal extends Component { + static propTypes = { + active: PropTypes.bool.isRequired, + hideModal: PropTypes.func.isRequired, + hideWarning: PropTypes.func.isRequired, + modalState: PropTypes.object.isRequired, + } -Modal.prototype.render = function () { - const modal = MODALS[this.props.modalState.name || 'DEFAULT'] - const { contents: children, disableBackdropClick = false } = modal - const modalStyle = modal[isMobileView() ? 'mobileModalStyle' : 'laptopModalStyle'] - const contentStyle = modal.contentStyle || {} - - return ( - { - if (modal.onHide) { - modal.onHide(this.props) - } - this.onHide(modal.customOnHideOpts) - }} - ref={(ref) => { - this.modalRef = ref - }} - modalStyle={modalStyle} - contentStyle={contentStyle} - backdropStyle={BACKDROPSTYLE} - closeOnClick={!disableBackdropClick} - > - {children} - - ) -} + hide () { + this.modalRef.hide() + } -Modal.prototype.UNSAFE_componentWillReceiveProps = function (nextProps) { - if (nextProps.active) { - this.show() - } else if (this.props.active) { - this.hide() + show () { + this.modalRef.show() } -} -Modal.prototype.onHide = function (customOnHideOpts) { - if (this.props.onHideCallback) { - this.props.onHideCallback() + UNSAFE_componentWillReceiveProps (nextProps, _) { + if (nextProps.active) { + this.show() + } else if (this.props.active) { + this.hide() + } } - this.props.hideModal(customOnHideOpts) -} -Modal.prototype.hide = function () { - this.modalRef.hide() + render () { + const modal = MODALS[this.props.modalState.name || 'DEFAULT'] + const { contents: children, disableBackdropClick = false } = modal + const modalStyle = modal[isMobileView() ? 'mobileModalStyle' : 'laptopModalStyle'] + const contentStyle = modal.contentStyle || {} + + return ( + { + if (modal.onHide) { + modal.onHide({ + hideWarning: this.props.hideWarning, + }) + } + this.props.hideModal(modal.customOnHideOpts) + }} + ref={(ref) => { + this.modalRef = ref + }} + modalStyle={modalStyle} + contentStyle={contentStyle} + backdropStyle={BACKDROPSTYLE} + closeOnClick={!disableBackdropClick} + > + {children} + + ) + } } -Modal.prototype.show = function () { - this.modalRef.show() -} +export default connect(mapStateToProps, mapDispatchToProps)(Modal) From f6de94a6e5cb4b9b3945d3d10259486b7b242985 Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Fri, 10 Jan 2020 11:11:49 -0800 Subject: [PATCH 103/689] Remove redundant gas selector file (#7805) One of these two selectors are in use, which is is another file https://github.com/MetaMask/metamask-extension/blob/92971d3c87fb778b5900e84bf4129f7c483ba98a/ui/app/selectors/custom-gas.js#L44 --- .../app/gas-customization/gas.selectors.js | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 ui/app/components/app/gas-customization/gas.selectors.js diff --git a/ui/app/components/app/gas-customization/gas.selectors.js b/ui/app/components/app/gas-customization/gas.selectors.js deleted file mode 100644 index c3c02c38c..000000000 --- a/ui/app/components/app/gas-customization/gas.selectors.js +++ /dev/null @@ -1,14 +0,0 @@ -const selectors = { - getCurrentBlockTime, - getBasicGasEstimateLoadingStatus, -} - -export default selectors - -function getCurrentBlockTime (state) { - return state.gas.currentBlockTime -} - -function getBasicGasEstimateLoadingStatus (state) { - return state.gas.basicEstimateIsLoading -} From ff966d515d13df8b3811bbe1d06913ec02829015 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 10 Jan 2020 15:32:57 -0400 Subject: [PATCH 104/689] Re-arrange transaction navigation test actions (#7806) These tests were updated in #7473 to navigate in a different order, because the transaction order changed. Unfortunately this meant that a second contract deployment was being confirmed, where it was previously being rejected. This updates the test to ensure the same transaction is rejected and confirmed as prior to the change in #7473 --- test/e2e/metamask-ui.spec.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index 9c6cd742b..0786714a9 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -651,21 +651,21 @@ describe('MetaMask', function () { assert.equal(navigationText.includes('2'), true, 'correct (same) transaction in focus') }) - it('confirms a transaction', async () => { + it('rejects a transaction', async () => { await delay(tinyDelayMs) - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`), 10000) + const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Reject')]`), 10000) await confirmButton.click() await delay(largeDelayMs * 2) const navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation')) await delay(tinyDelayMs) const navigationText = await navigationElement.getText() - assert.equal(navigationText.includes('4'), true, 'transaction confirmed') + assert.equal(navigationText.includes('4'), true, 'transaction rejected') }) - it('rejects a transaction', async () => { + it('confirms a transaction', async () => { await delay(tinyDelayMs / 2) - const rejectButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Reject')]`), 10000) + const rejectButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`), 10000) await delay(tinyDelayMs / 2) await rejectButton.click() await delay(regularDelayMs) @@ -674,7 +674,7 @@ describe('MetaMask', function () { await delay(tinyDelayMs / 2) const navigationText = await navigationElement.getText() await delay(tinyDelayMs / 2) - assert.equal(navigationText.includes('3'), true, 'transaction rejected') + assert.equal(navigationText.includes('3'), true, 'transaction confirmed') }) it('rejects the rest of the transactions', async () => { @@ -855,9 +855,9 @@ describe('MetaMask', function () { it('renders the correct ETH balance', async () => { const balance = await findElement(driver, By.css('.transaction-view-balance__primary-balance')) await delay(regularDelayMs) - await driver.wait(until.elementTextMatches(balance, /^90.*\s*ETH.*$/), 10000) + await driver.wait(until.elementTextMatches(balance, /^87.*\s*ETH.*$/), 10000) const tokenAmount = await balance.getText() - assert.ok(/^90.*\s*ETH.*$/.test(tokenAmount)) + assert.ok(/^87.*\s*ETH.*$/.test(tokenAmount)) await delay(regularDelayMs) }) }) From 46f54abf52dd17b449fca4f78e54e07058f3318a Mon Sep 17 00:00:00 2001 From: Lenard Frommelt Date: Fri, 10 Jan 2020 20:34:46 +0000 Subject: [PATCH 105/689] fixed Tohen Typo (#7808) --- app/_locales/de/messages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index 3d7ec6194..6e0ce19e0 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -303,7 +303,7 @@ "message": "Höhere Gebühren können Bearbeitungszeiten verkürzen, wofür es allerdings keine Garantie gibt." }, "customToken": { - "message": "Custom-Tohen" + "message": "Custom-Token" }, "customRPC": { "message": "Spezieller RPC" From 82ef9674f2cd428c3d8601e4f17af12e56d953b0 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 13 Jan 2020 10:41:41 -0330 Subject: [PATCH 106/689] Move util test file alongside subject (#7807) --- test/unit/util_test.js => ui/app/helpers/utils/util.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename test/unit/util_test.js => ui/app/helpers/utils/util.test.js (99%) diff --git a/test/unit/util_test.js b/ui/app/helpers/utils/util.test.js similarity index 99% rename from test/unit/util_test.js rename to ui/app/helpers/utils/util.test.js index 4753b2bd5..6e623ae3a 100644 --- a/test/unit/util_test.js +++ b/ui/app/helpers/utils/util.test.js @@ -1,7 +1,7 @@ import assert from 'assert' import sinon from 'sinon' import ethUtil from 'ethereumjs-util' -import * as util from '../../ui/app/helpers/utils/util' +import * as util from './util' describe('util', function () { let ethInWei = '1' From d802e09a8b1190ead8f75bf7b962e151a4584679 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 13 Jan 2020 10:42:58 -0330 Subject: [PATCH 107/689] Convert Mascot component to an ES6 class (#7787) --- ui/app/components/ui/mascot.js | 106 ++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 49 deletions(-) diff --git a/ui/app/components/ui/mascot.js b/ui/app/components/ui/mascot.js index 6e09e01b2..4b6aac27d 100644 --- a/ui/app/components/ui/mascot.js +++ b/ui/app/components/ui/mascot.js @@ -1,62 +1,70 @@ +import PropTypes from 'prop-types' import React, { Component } from 'react' -import { inherits } from 'util' import metamaskLogo from 'metamask-logo' import debounce from 'debounce' -export default Mascot +export default class Mascot extends Component { + static propTypes = { + animationEventEmitter: PropTypes.object.isRequired, + width: PropTypes.string, + height: PropTypes.string, + } -inherits(Mascot, Component) -function Mascot ({ width = '200', height = '200' }) { - Component.call(this) - this.logo = metamaskLogo({ - followMouse: true, - pxNotRatio: true, - width, - height, - }) + constructor (props) { + super(props) - this.refollowMouse = debounce(this.logo.setFollowMouse.bind(this.logo, true), 1000) - this.unfollowMouse = this.logo.setFollowMouse.bind(this.logo, false) -} + const { width = '200', height = '200' } = props -Mascot.prototype.render = function Mascot () { - // this is a bit hacky - // the event emitter is on `this.props` - // and we dont get that until render - this.handleAnimationEvents() - return ( -
- ) -} + this.logo = metamaskLogo({ + followMouse: true, + pxNotRatio: true, + width, + height, + }) -Mascot.prototype.componentDidMount = function () { - const targetDivId = 'metamask-mascot-container' - const container = document.getElementById(targetDivId) - container.appendChild(this.logo.container) -} + this.refollowMouse = debounce(this.logo.setFollowMouse.bind(this.logo, true), 1000) + this.unfollowMouse = this.logo.setFollowMouse.bind(this.logo, false) + } -Mascot.prototype.componentWillUnmount = function () { - this.animations = this.props.animationEventEmitter - this.animations.removeAllListeners() - this.logo.container.remove() - this.logo.stopAnimation() -} + handleAnimationEvents () { + // only setup listeners once + if (this.animations) { + return + } + this.animations = this.props.animationEventEmitter + this.animations.on('point', this.lookAt.bind(this)) + this.animations.on('setFollowMouse', this.logo.setFollowMouse.bind(this.logo)) + } -Mascot.prototype.handleAnimationEvents = function () { - // only setup listeners once - if (this.animations) { - return + lookAt (target) { + this.unfollowMouse() + this.logo.lookAt(target) + this.refollowMouse() + } + + componentDidMount () { + const targetDivId = 'metamask-mascot-container' + const container = document.getElementById(targetDivId) + container.appendChild(this.logo.container) } - this.animations = this.props.animationEventEmitter - this.animations.on('point', this.lookAt.bind(this)) - this.animations.on('setFollowMouse', this.logo.setFollowMouse.bind(this.logo)) -} -Mascot.prototype.lookAt = function (target) { - this.unfollowMouse() - this.logo.lookAt(target) - this.refollowMouse() + componentWillUnmount () { + this.animations = this.props.animationEventEmitter + this.animations.removeAllListeners() + this.logo.container.remove() + this.logo.stopAnimation() + } + + render () { + // this is a bit hacky + // the event emitter is on `this.props` + // and we dont get that until render + this.handleAnimationEvents() + return ( +
+ ) + } } From 27cfb6aa51f139dcc3bf3334be3c35b0e123407b Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 13 Jan 2020 11:07:32 -0400 Subject: [PATCH 108/689] Move webdriver interactions into driver module (#7798) The Selenium webdriver is difficult to use, and easy to misuse. To help use the driver and make it easier to maintain our e2e tests, all driver interactions are now performed via a `driver` module. This is basically a wrapper class around the `selenium-webdriver` that exposes only the methods we want to use directly, along with all of our helper methods. --- test/{e2e => data}/fetch-mocks.json | 0 test/e2e/address-book.spec.js | 160 ++- test/e2e/ethereum-on.spec.js | 107 +- test/e2e/from-import-ui.spec.js | 235 ++-- test/e2e/helpers.js | 156 --- test/e2e/incremental-security.spec.js | 108 +- test/e2e/metamask-responsive-ui.spec.js | 140 ++- test/e2e/metamask-ui.spec.js | 1019 ++++++++--------- test/e2e/permissions.spec.js | 114 +- test/e2e/send-edit.spec.js | 141 ++- test/e2e/signature-request.spec.js | 83 +- test/e2e/threebox.spec.js | 149 ++- test/e2e/web3.spec.js | 94 +- test/e2e/webdriver/driver.js | 153 +++ test/e2e/webdriver/index.js | 44 +- test/integration/lib/confirm-sig-requests.js | 2 +- test/integration/lib/currency-localization.js | 2 +- test/integration/lib/tx-list-items.js | 2 +- 18 files changed, 1330 insertions(+), 1379 deletions(-) rename test/{e2e => data}/fetch-mocks.json (100%) create mode 100644 test/e2e/webdriver/driver.js diff --git a/test/e2e/fetch-mocks.json b/test/data/fetch-mocks.json similarity index 100% rename from test/e2e/fetch-mocks.json rename to test/data/fetch-mocks.json diff --git a/test/e2e/address-book.spec.js b/test/e2e/address-book.spec.js index 85eba82f6..fc1738ebe 100644 --- a/test/e2e/address-book.spec.js +++ b/test/e2e/address-book.spec.js @@ -1,15 +1,11 @@ const assert = require('assert') -const webdriver = require('selenium-webdriver') +const { By, until } = require('selenium-webdriver') -const { By, until } = webdriver const { - checkBrowserForConsoleErrors, - delay, - findElement, - findElements, - verboseReportOnFailure, - setupFetchMocking, prepareExtensionForTesting, + tinyDelayMs, + regularDelayMs, + largeDelayMs, } = require('./helpers') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -20,9 +16,6 @@ describe('MetaMask', function () { let driver const testSeedPhrase = 'forum vessel pink push lonely enact gentle tail admit parrot grunt dress' - const tinyDelayMs = 200 - const regularDelayMs = tinyDelayMs * 2 - const largeDelayMs = regularDelayMs * 2 this.timeout(0) this.bail(true) @@ -38,12 +31,11 @@ describe('MetaMask', function () { }) const result = await prepareExtensionForTesting() driver = result.driver - await setupFetchMocking(driver) }) afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors() if (errors.length) { const errorReports = errors.map(err => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` @@ -51,7 +43,7 @@ describe('MetaMask', function () { } } if (this.currentTest.state === 'failed') { - await verboseReportOnFailure(driver, this.currentTest) + await driver.verboseReportOnFailure(driver, this.currentTest) } }) @@ -62,63 +54,63 @@ describe('MetaMask', function () { describe('Going through the first time flow', () => { it('clicks the continue button on the welcome screen', async () => { - await findElement(driver, By.css('.welcome-page__header')) - const welcomeScreenBtn = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) + await driver.findElement(By.css('.welcome-page__header')) + const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) welcomeScreenBtn.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { - const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) + const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) customRpcButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await findElement(driver, By.css('.btn-default')) + const optOutButton = await driver.findElement(By.css('.btn-default')) optOutButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('accepts a secure password', async () => { - const passwordBox = await findElement(driver, By.css('.first-time-flow__form #create-password')) - const passwordBoxConfirm = await findElement(driver, By.css('.first-time-flow__form #confirm-password')) - const button = await findElement(driver, By.css('.first-time-flow__form button')) + const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) + const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) + const button = await driver.findElement(By.css('.first-time-flow__form button')) await passwordBox.sendKeys('correct horse battery staple') await passwordBoxConfirm.sendKeys('correct horse battery staple') - const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox')) + const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) await tosCheckBox.click() await button.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) let seedPhrase it('reveals the seed phrase', async () => { const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button') - await driver.wait(until.elementLocated(byRevealButton, 10000)) - const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000) + const revealSeedPhraseButton = await driver.findElement(byRevealButton, 10000) await revealSeedPhraseButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - seedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')).getText() + const revealedSeedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')) + seedPhrase = await revealedSeedPhrase.getText() assert.equal(seedPhrase.split(' ').length, 12) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) async function clickWordAndWait (word) { const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]` - const word0 = await findElement(driver, By.xpath(xpath), 10000) + const word0 = await driver.findElement(By.xpath(xpath)) await word0.click() - await delay(tinyDelayMs) + await driver.delay(tinyDelayMs) } it('can retype the seed phrase', async () => { @@ -128,146 +120,148 @@ describe('MetaMask', function () { await clickWordAndWait(word) } - const confirm = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirm = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirm.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('clicks through the success screen', async () => { - await findElement(driver, By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) + await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) + const doneButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await doneButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Import seed phrase', () => { it('logs out of the vault', async () => { - await driver.findElement(By.css('.account-menu__icon')).click() - await delay(regularDelayMs) + const accountMenu = await driver.findElement(By.css('.account-menu__icon')) + await accountMenu.click() + await driver.delay(regularDelayMs) - const logoutButton = await findElement(driver, By.css('.account-menu__logout-button')) + const logoutButton = await driver.findElement(By.css('.account-menu__logout-button')) assert.equal(await logoutButton.getText(), 'Log out') await logoutButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('imports seed phrase', async () => { - const restoreSeedLink = await findElement(driver, By.css('.unlock-page__link--import')) + const restoreSeedLink = await driver.findElement(By.css('.unlock-page__link--import')) assert.equal(await restoreSeedLink.getText(), 'Import using account seed phrase') await restoreSeedLink.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const seedTextArea = await findElement(driver, By.css('textarea')) + const seedTextArea = await driver.findElement(By.css('textarea')) await seedTextArea.sendKeys(testSeedPhrase) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) const passwordInputs = await driver.findElements(By.css('input')) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) await passwordInputs[0].sendKeys('correct horse battery staple') await passwordInputs[1].sendKeys('correct horse battery staple') - await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.restore.message}')]`)).click() - await delay(regularDelayMs) + const restoreButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.restore.message}')]`)) + restoreButton.click() + await driver.delay(regularDelayMs) }) it('balance renders', async () => { - const balance = await findElement(driver, By.css('.balance-display .token-amount')) + const balance = await driver.findElement(By.css('.balance-display .token-amount')) await driver.wait(until.elementTextMatches(balance, /25\s*ETH/)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Adds an entry to the address book and sends eth to that address', () => { it('starts a send transaction', async function () { - const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`)) + const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) await sendButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const inputAddress = await findElement(driver, By.css('input[placeholder="Search, public address (0x), or ENS"]')) + const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const addToAddressBookButton = await findElement(driver, By.css('.dialog.send__dialog.dialog--message')) + const addToAddressBookButton = await driver.findElement(By.css('.dialog.send__dialog.dialog--message')) await addToAddressBookButton.click() const addressBookAddModal = await driver.findElement(By.css('span .modal')) - await findElement(driver, By.css('.add-to-address-book-modal')) - const addressBookInput = await findElement(driver, By.css('.add-to-address-book-modal__input')) + await driver.findElement(By.css('.add-to-address-book-modal')) + const addressBookInput = await driver.findElement(By.css('.add-to-address-book-modal__input')) await addressBookInput.sendKeys('Test Name 1') - await delay(tinyDelayMs) - const addressBookSaveButton = await findElement(driver, By.css('.add-to-address-book-modal__footer .btn-primary')) + await driver.delay(tinyDelayMs) + const addressBookSaveButton = await driver.findElement(By.css('.add-to-address-book-modal__footer .btn-primary')) await addressBookSaveButton.click() await driver.wait(until.stalenessOf(addressBookAddModal)) - const inputAmount = await findElement(driver, By.css('.unit-input__input')) + const inputAmount = await driver.findElement(By.css('.unit-input__input')) await inputAmount.sendKeys('1') const inputValue = await inputAmount.getAttribute('value') assert.equal(inputValue, '1') - await delay(regularDelayMs) + await driver.delay(regularDelayMs) // Continue to next screen - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('confirms the transaction', async function () { - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(largeDelayMs * 2) + await driver.delay(largeDelayMs * 2) }) it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 1 }, 10000) - const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary')) + const txValues = await driver.findElement(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000) }) }) describe('Sends to an address book entry', () => { it('starts a send transaction by clicking address book entry', async function () { - const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`)) + const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) await sendButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const recipientRow = await findElement(driver, By.css('.send__select-recipient-wrapper__group-item')) - const recipientRowTitle = await findElement(driver, By.css('.send__select-recipient-wrapper__group-item__title')) + const recipientRow = await driver.findElement(By.css('.send__select-recipient-wrapper__group-item')) + const recipientRowTitle = await driver.findElement(By.css('.send__select-recipient-wrapper__group-item__title')) const recipientRowTitleString = await recipientRowTitle.getText() assert.equal(recipientRowTitleString, 'Test Name 1') await recipientRow.click() - await delay(regularDelayMs) - const inputAmount = await findElement(driver, By.css('.unit-input__input')) + await driver.delay(regularDelayMs) + const inputAmount = await driver.findElement(By.css('.unit-input__input')) await inputAmount.sendKeys('2') - await delay(regularDelayMs) + await driver.delay(regularDelayMs) // Continue to next screen - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('confirms the transaction', async function () { - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(largeDelayMs * 2) + await driver.delay(largeDelayMs * 2) }) it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 2 }, 10000) - const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary')) + const txValues = await driver.findElement(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txValues, /-2\s*ETH/), 10000) }) }) diff --git a/test/e2e/ethereum-on.spec.js b/test/e2e/ethereum-on.spec.js index 1dc2b2fc9..3955d5993 100644 --- a/test/e2e/ethereum-on.spec.js +++ b/test/e2e/ethereum-on.spec.js @@ -3,15 +3,9 @@ const webdriver = require('selenium-webdriver') const { By, until } = webdriver const { - checkBrowserForConsoleErrors, - delay, - findElement, - openNewPage, - verboseReportOnFailure, - waitUntilXWindowHandles, - switchToWindowWithTitle, - setupFetchMocking, prepareExtensionForTesting, + regularDelayMs, + largeDelayMs, } = require('./helpers') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -22,10 +16,6 @@ describe('MetaMask', function () { let driver let publicAddress - const tinyDelayMs = 200 - const regularDelayMs = tinyDelayMs * 2 - const largeDelayMs = regularDelayMs * 2 - this.timeout(0) this.bail(true) @@ -40,12 +30,11 @@ describe('MetaMask', function () { }) const result = await prepareExtensionForTesting() driver = result.driver - await setupFetchMocking(driver) }) afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { const errorReports = errors.map(err => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` @@ -53,7 +42,7 @@ describe('MetaMask', function () { } } if (this.currentTest.state === 'failed') { - await verboseReportOnFailure(driver, this.currentTest) + await driver.verboseReportOnFailure(driver, this.currentTest) } }) @@ -64,51 +53,51 @@ describe('MetaMask', function () { describe('Going through the first time flow, but skipping the seed phrase challenge', () => { it('clicks the continue button on the welcome screen', async () => { - await findElement(driver, By.css('.welcome-page__header')) - const welcomeScreenBtn = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) + await driver.findElement(By.css('.welcome-page__header')) + const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) welcomeScreenBtn.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { - const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) + const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) customRpcButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await findElement(driver, By.css('.btn-default')) + const optOutButton = await driver.findElement(By.css('.btn-default')) optOutButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('accepts a secure password', async () => { - const passwordBox = await findElement(driver, By.css('.first-time-flow__form #create-password')) - const passwordBoxConfirm = await findElement(driver, By.css('.first-time-flow__form #confirm-password')) - const button = await findElement(driver, By.css('.first-time-flow__form button')) + const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) + const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) + const button = await driver.findElement(By.css('.first-time-flow__form button')) await passwordBox.sendKeys('correct horse battery staple') await passwordBoxConfirm.sendKeys('correct horse battery staple') - const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox')) + const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) await tosCheckBox.click() await button.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('skips the seed phrase challenge', async () => { - const button = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) + const button = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) await button.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const detailsButton = await findElement(driver, By.css('.account-details__details-button')) + const detailsButton = await driver.findElement(By.css('.account-details__details-button')) await detailsButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('gets the current accounts address', async () => { - const addressInput = await findElement(driver, By.css('.qr-ellip-address')) + const addressInput = await driver.findElement(By.css('.qr-ellip-address')) publicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) @@ -116,7 +105,7 @@ describe('MetaMask', function () { await accountModalClose.click() await driver.wait(until.stalenessOf(accountModal)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) @@ -127,69 +116,69 @@ describe('MetaMask', function () { let dapp it('connects to the dapp', async () => { - await openNewPage(driver, 'http://127.0.0.1:8080/') - await delay(regularDelayMs) + await driver.openNewPage('http://127.0.0.1:8080/') + await driver.delay(regularDelayMs) - const connectButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Connect')]`)) + const connectButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Connect')]`)) await connectButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - await waitUntilXWindowHandles(driver, 3) + await driver.waitUntilXWindowHandles(3) const windowHandles = await driver.getAllWindowHandles() extension = windowHandles[0] - dapp = await switchToWindowWithTitle(driver, 'E2E Test Dapp', windowHandles) + dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) popup = windowHandles.find(handle => handle !== extension && handle !== dapp) - await driver.switchTo().window(popup) + await driver.switchToWindow(popup) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const accountButton = await findElement(driver, By.css('.permissions-connect-choose-account__account')) + const accountButton = await driver.findElement(By.css('.permissions-connect-choose-account__account')) await accountButton.click() - const submitButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Submit')]`)) + const submitButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Submit')]`)) await submitButton.click() - await waitUntilXWindowHandles(driver, 2) - await driver.switchTo().window(dapp) - await delay(regularDelayMs) + await driver.waitUntilXWindowHandles(2) + await driver.switchToWindow(dapp) + await driver.delay(regularDelayMs) }) it('has the ganache network id within the dapp', async () => { - const networkDiv = await findElement(driver, By.css('#network')) - await delay(regularDelayMs) + const networkDiv = await driver.findElement(By.css('#network')) + await driver.delay(regularDelayMs) assert.equal(await networkDiv.getText(), '5777') }) it('changes the network', async () => { - await driver.switchTo().window(extension) + await driver.switchToWindow(extension) - const networkDropdown = await findElement(driver, By.css('.network-name')) + const networkDropdown = await driver.findElement(By.css('.network-name')) await networkDropdown.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const ropstenButton = await findElement(driver, By.xpath(`//span[contains(text(), 'Ropsten')]`)) + const ropstenButton = await driver.findElement(By.xpath(`//span[contains(text(), 'Ropsten')]`)) await ropstenButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('sets the network div within the dapp', async () => { - await driver.switchTo().window(dapp) - const networkDiv = await findElement(driver, By.css('#network')) + await driver.switchToWindow(dapp) + const networkDiv = await driver.findElement(By.css('#network')) assert.equal(await networkDiv.getText(), '3') }) it('sets the chainId div within the dapp', async () => { - await driver.switchTo().window(dapp) - const chainIdDiv = await findElement(driver, By.css('#chainId')) + await driver.switchToWindow(dapp) + const chainIdDiv = await driver.findElement(By.css('#chainId')) assert.equal(await chainIdDiv.getText(), '0x3') }) it('sets the account div within the dapp', async () => { - await driver.switchTo().window(dapp) - const accountsDiv = await findElement(driver, By.css('#accounts')) + await driver.switchToWindow(dapp) + const accountsDiv = await driver.findElement(By.css('#accounts')) assert.equal(await accountsDiv.getText(), publicAddress.toLowerCase()) }) }) diff --git a/test/e2e/from-import-ui.spec.js b/test/e2e/from-import-ui.spec.js index a10d6ac33..3d742785f 100644 --- a/test/e2e/from-import-ui.spec.js +++ b/test/e2e/from-import-ui.spec.js @@ -3,13 +3,10 @@ const webdriver = require('selenium-webdriver') const { By, Key, until } = webdriver const { - checkBrowserForConsoleErrors, - delay, - verboseReportOnFailure, - findElement, - findElements, - setupFetchMocking, prepareExtensionForTesting, + tinyDelayMs, + regularDelayMs, + largeDelayMs, } = require('./helpers') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -23,9 +20,6 @@ describe('Using MetaMask with an existing account', function () { const testAddress = '0x0Cc5261AB8cE458dc977078A3623E2BaDD27afD3' const testPrivateKey2 = '14abe6f4aab7f9f626fe981c864d0adeb5685f289ac9270c27b8fd790b4235d6' const testPrivateKey3 = 'F4EC2590A0C10DE95FBF4547845178910E40F5035320C516A18C117DE02B5669' - const tinyDelayMs = 200 - const regularDelayMs = 1000 - const largeDelayMs = regularDelayMs * 2 this.timeout(0) this.bail(true) @@ -41,12 +35,11 @@ describe('Using MetaMask with an existing account', function () { }) const result = await prepareExtensionForTesting() driver = result.driver - await setupFetchMocking(driver) }) afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { const errorReports = errors.map(err => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` @@ -54,7 +47,7 @@ describe('Using MetaMask with an existing account', function () { } } if (this.currentTest.state === 'failed') { - await verboseReportOnFailure(driver, this.currentTest) + await driver.verboseReportOnFailure(driver, this.currentTest) } }) @@ -65,186 +58,191 @@ describe('Using MetaMask with an existing account', function () { describe('First time flow starting from an existing seed phrase', () => { it('clicks the continue button on the welcome screen', async () => { - await findElement(driver, By.css('.welcome-page__header')) - const welcomeScreenBtn = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) + await driver.findElement(By.css('.welcome-page__header')) + const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) welcomeScreenBtn.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "Import Wallet" option', async () => { - const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Import Wallet')]`)) + const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) customRpcButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await findElement(driver, By.css('.btn-default')) + const optOutButton = await driver.findElement(By.css('.btn-default')) optOutButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('imports a seed phrase', async () => { - const [seedTextArea] = await findElements(driver, By.css('textarea.first-time-flow__textarea')) + const [seedTextArea] = await driver.findElements(By.css('textarea.first-time-flow__textarea')) await seedTextArea.sendKeys(testSeedPhrase) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const [password] = await findElements(driver, By.id('password')) + const [password] = await driver.findElements(By.id('password')) await password.sendKeys('correct horse battery staple') - const [confirmPassword] = await findElements(driver, By.id('confirm-password')) + const [confirmPassword] = await driver.findElements(By.id('confirm-password')) confirmPassword.sendKeys('correct horse battery staple') - const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox')) + const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) await tosCheckBox.click() - const [importButton] = await findElements(driver, By.xpath(`//button[contains(text(), 'Import')]`)) + const [importButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Import')]`)) await importButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('clicks through the success screen', async () => { - await findElement(driver, By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) + await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) + const doneButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await doneButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Show account information', () => { it('shows the correct account address', async () => { - await driver.findElement(By.css('.account-details__details-button')).click() - await driver.findElement(By.css('.qr-wrapper')).isDisplayed() - await delay(regularDelayMs) + const accountDetailsButton = await driver.findElement(By.css('.account-details__details-button')) + await accountDetailsButton.click() + await driver.findVisibleElement(By.css('.qr-wrapper')) + await driver.delay(regularDelayMs) - const [address] = await findElements(driver, By.css('input.qr-ellip-address')) + const [address] = await driver.findElements(By.css('input.qr-ellip-address')) assert.equal(await address.getAttribute('value'), testAddress) const accountModalClose = await driver.findElement(By.css('.account-modal-close')) await accountModalClose.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('shows a QR code for the account', async () => { - await driver.findElement(By.css('.account-details__details-button')).click() - await driver.findElement(By.css('.qr-wrapper')).isDisplayed() + const accountDetailsButton = await driver.findElement(By.css('.account-details__details-button')) + await accountDetailsButton.click() + await driver.findVisibleElement(By.css('.qr-wrapper')) const detailModal = await driver.findElement(By.css('span .modal')) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) const accountModalClose = await driver.findElement(By.css('.account-modal-close')) await accountModalClose.click() await driver.wait(until.stalenessOf(detailModal)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Log out and log back in', () => { it('logs out of the account', async () => { - const accountIdenticon = driver.findElement(By.css('.account-menu__icon .identicon')) - accountIdenticon.click() - await delay(regularDelayMs) + const accountIdenticon = await driver.findElement(By.css('.account-menu__icon .identicon')) + await accountIdenticon.click() + await driver.delay(regularDelayMs) - const [logoutButton] = await findElements(driver, By.css('.account-menu__logout-button')) + const [logoutButton] = await driver.findElements(By.css('.account-menu__logout-button')) assert.equal(await logoutButton.getText(), 'Log out') await logoutButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('accepts the account password after lock', async () => { - await driver.findElement(By.id('password')).sendKeys('correct horse battery staple') - await driver.findElement(By.id('password')).sendKeys(Key.ENTER) - await delay(largeDelayMs) + const passwordField = await driver.findElement(By.id('password')) + await passwordField.sendKeys('correct horse battery staple') + await passwordField.sendKeys(Key.ENTER) + await driver.delay(largeDelayMs) }) }) describe('Add an account', () => { it('switches to localhost', async () => { - const networkDropdown = await findElement(driver, By.css('.network-name')) + const networkDropdown = await driver.findElement(By.css('.network-name')) await networkDropdown.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const [localhost] = await findElements(driver, By.xpath(`//span[contains(text(), 'Localhost')]`)) + const [localhost] = await driver.findElements(By.xpath(`//span[contains(text(), 'Localhost')]`)) await localhost.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('choose Create Account from the account menu', async () => { - await driver.findElement(By.css('.account-menu__icon')).click() - await delay(regularDelayMs) + const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) + await accountMenuButton.click() + await driver.delay(regularDelayMs) - const [createAccount] = await findElements(driver, By.xpath(`//div[contains(text(), 'Create Account')]`)) + const [createAccount] = await driver.findElements(By.xpath(`//div[contains(text(), 'Create Account')]`)) await createAccount.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('set account name', async () => { - const [accountName] = await findElements(driver, By.css('.new-account-create-form input')) + const [accountName] = await driver.findElements(By.css('.new-account-create-form input')) await accountName.sendKeys('2nd account') - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const [createButton] = await findElements(driver, By.xpath(`//button[contains(text(), 'Create')]`)) + const [createButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Create')]`)) await createButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('should show the correct account name', async () => { - const [accountName] = await findElements(driver, By.css('.account-details__account-name')) + const [accountName] = await driver.findElements(By.css('.account-details__account-name')) assert.equal(await accountName.getText(), '2nd account') - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Switch back to original account', () => { it('chooses the original account from the account menu', async () => { - await driver.findElement(By.css('.account-menu__icon')).click() - await delay(regularDelayMs) + const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) + await accountMenuButton.click() + await driver.delay(regularDelayMs) - const [originalAccountMenuItem] = await findElements(driver, By.css('.account-menu__name')) + const [originalAccountMenuItem] = await driver.findElements(By.css('.account-menu__name')) await originalAccountMenuItem.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Send ETH from inside MetaMask', () => { it('starts a send transaction', async function () { - const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`)) + const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) await sendButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const inputAddress = await findElement(driver, By.css('input[placeholder="Search, public address (0x), or ENS"]')) + const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') - const inputAmount = await findElement(driver, By.css('.unit-input__input')) + const inputAmount = await driver.findElement(By.css('.unit-input__input')) await inputAmount.sendKeys('1') // Set the gas limit - const configureGas = await findElement(driver, By.css('.advanced-gas-options-btn')) + const configureGas = await driver.findElement(By.css('.advanced-gas-options-btn')) await configureGas.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) const gasModal = await driver.findElement(By.css('span .modal')) - const save = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`)) + const save = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) await save.click() await driver.wait(until.stalenessOf(gasModal)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) // Continue to next screen - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('confirms the transaction', async function () { - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 1 }, 10000) - const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + const txValues = await driver.findElements(By.css('.transaction-list-item__amount--primary')) assert.equal(txValues.length, 1) assert.ok(/-1\s*ETH/.test(await txValues[0].getText())) }) @@ -252,102 +250,105 @@ describe('Using MetaMask with an existing account', function () { describe('Imports an account with private key', () => { it('choose Create Account from the account menu', async () => { - await driver.findElement(By.css('.account-menu__icon')).click() - await delay(regularDelayMs) + const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) + await accountMenuButton.click() + await driver.delay(regularDelayMs) - const [importAccount] = await findElements(driver, By.xpath(`//div[contains(text(), 'Import Account')]`)) + const [importAccount] = await driver.findElements(By.xpath(`//div[contains(text(), 'Import Account')]`)) await importAccount.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('enter private key', async () => { - const privateKeyInput = await findElement(driver, By.css('#private-key-box')) + const privateKeyInput = await driver.findElement(By.css('#private-key-box')) await privateKeyInput.sendKeys(testPrivateKey2) - await delay(regularDelayMs) - const importButtons = await findElements(driver, By.xpath(`//button[contains(text(), 'Import')]`)) + await driver.delay(regularDelayMs) + const importButtons = await driver.findElements(By.xpath(`//button[contains(text(), 'Import')]`)) await importButtons[0].click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('should show the correct account name', async () => { - const [accountName] = await findElements(driver, By.css('.account-details__account-name')) + const [accountName] = await driver.findElements(By.css('.account-details__account-name')) assert.equal(await accountName.getText(), 'Account 4') - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('should show the imported label', async () => { - const [importedLabel] = await findElements(driver, By.css('.account-details__keyring-label')) + const [importedLabel] = await driver.findElements(By.css('.account-details__keyring-label')) assert.equal(await importedLabel.getText(), 'IMPORTED') - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Imports and removes an account', () => { it('choose Create Account from the account menu', async () => { - await driver.findElement(By.css('.account-menu__icon')).click() - await delay(regularDelayMs) + const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) + await accountMenuButton.click() + await driver.delay(regularDelayMs) - const [importAccount] = await findElements(driver, By.xpath(`//div[contains(text(), 'Import Account')]`)) + const [importAccount] = await driver.findElements(By.xpath(`//div[contains(text(), 'Import Account')]`)) await importAccount.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('enter private key', async () => { - const privateKeyInput = await findElement(driver, By.css('#private-key-box')) + const privateKeyInput = await driver.findElement(By.css('#private-key-box')) await privateKeyInput.sendKeys(testPrivateKey3) - await delay(regularDelayMs) - const importButtons = await findElements(driver, By.xpath(`//button[contains(text(), 'Import')]`)) + await driver.delay(regularDelayMs) + const importButtons = await driver.findElements(By.xpath(`//button[contains(text(), 'Import')]`)) await importButtons[0].click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('should open the remove account modal', async () => { - const [accountName] = await findElements(driver, By.css('.account-details__account-name')) + const [accountName] = await driver.findElements(By.css('.account-details__account-name')) assert.equal(await accountName.getText(), 'Account 5') - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - await driver.findElement(By.css('.account-menu__icon')).click() - await delay(regularDelayMs) + const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) + await accountMenuButton.click() + await driver.delay(regularDelayMs) - const accountListItems = await findElements(driver, By.css('.account-menu__account')) + const accountListItems = await driver.findElements(By.css('.account-menu__account')) assert.equal(accountListItems.length, 5) - const removeAccountIcons = await findElements(driver, By.css('.remove-account-icon')) + const removeAccountIcons = await driver.findElements(By.css('.remove-account-icon')) await removeAccountIcons[1].click() - await delay(tinyDelayMs) + await driver.delay(tinyDelayMs) - await findElement(driver, By.css('.confirm-remove-account__account')) + await driver.findElement(By.css('.confirm-remove-account__account')) }) it('should remove the account', async () => { - const removeButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Remove')]`)) + const removeButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Remove')]`)) await removeButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const [accountName] = await findElements(driver, By.css('.account-details__account-name')) + const [accountName] = await driver.findElements(By.css('.account-details__account-name')) assert.equal(await accountName.getText(), 'Account 1') - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const accountListItems = await findElements(driver, By.css('.account-menu__account')) + const accountListItems = await driver.findElements(By.css('.account-menu__account')) assert.equal(accountListItems.length, 4) }) }) describe('Connects to a Hardware wallet', () => { it('choose Connect Hardware Wallet from the account menu', async () => { - const [connectAccount] = await findElements(driver, By.xpath(`//div[contains(text(), 'Connect Hardware Wallet')]`)) + const [connectAccount] = await driver.findElements(By.xpath(`//div[contains(text(), 'Connect Hardware Wallet')]`)) await connectAccount.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('should open the TREZOR Connect popup', async () => { - const trezorButton = await findElements(driver, By.css('.hw-connect__btn')) + const trezorButton = await driver.findElements(By.css('.hw-connect__btn')) await trezorButton[1].click() - await delay(regularDelayMs) - const connectButtons = await findElements(driver, By.xpath(`//button[contains(text(), 'Connect')]`)) + await driver.delay(regularDelayMs) + const connectButtons = await driver.findElements(By.xpath(`//button[contains(text(), 'Connect')]`)) await connectButtons[0].click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) const allWindows = await driver.getAllWindowHandles() assert.equal(allWindows.length, 2) }) diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 999478833..6ab427e6d 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -1,28 +1,10 @@ -const fs = require('fs') -const mkdirp = require('mkdirp') -const pify = require('pify') -const assert = require('assert') -const { until } = require('selenium-webdriver') - const { buildWebDriver } = require('./webdriver') -const fetchMockResponses = require('./fetch-mocks.json') const tinyDelayMs = 200 const regularDelayMs = tinyDelayMs * 2 const largeDelayMs = regularDelayMs * 2 module.exports = { - assertElementNotPresent, - checkBrowserForConsoleErrors, - closeAllWindowHandlesExcept, - delay, - findElement, - findElements, - openNewPage, - switchToWindowWithTitle, - verboseReportOnFailure, - waitUntilXWindowHandles, - setupFetchMocking, prepareExtensionForTesting, tinyDelayMs, regularDelayMs, @@ -34,143 +16,5 @@ async function prepareExtensionForTesting ({ responsive, port } = {}) { const extensionPath = `dist/${browser}` const { driver, extensionId, extensionUrl } = await buildWebDriver({ browser, extensionPath, responsive, port }) - await driver.get(extensionUrl) - return { driver, extensionId, extensionUrl } } - -async function setupFetchMocking (driver) { - // define fetchMocking script, to be evaluated in the browser - function fetchMocking (fetchMockResponses) { - window.origFetch = window.fetch.bind(window) - window.fetch = async (...args) => { - const url = args[0] - if (url === 'https://ethgasstation.info/json/ethgasAPI.json') { - return { json: async () => clone(fetchMockResponses.ethGasBasic) } - } else if (url === 'https://ethgasstation.info/json/predictTable.json') { - return { json: async () => clone(fetchMockResponses.ethGasPredictTable) } - } else if (url.match(/chromeextensionmm/)) { - return { json: async () => clone(fetchMockResponses.metametrics) } - } - return window.origFetch(...args) - } - if (window.chrome && window.chrome.webRequest) { - window.chrome.webRequest.onBeforeRequest.addListener(cancelInfuraRequest, { urls: ['https://*.infura.io/*'] }, ['blocking']) - } - function cancelInfuraRequest (requestDetails) { - console.log(`fetchMocking - Canceling request: "${requestDetails.url}"`) - return { cancel: true } - } - function clone (obj) { - return JSON.parse(JSON.stringify(obj)) - } - } - // fetchMockResponses are parsed last minute to ensure that objects are uniquely instantiated - const fetchMockResponsesJson = JSON.stringify(fetchMockResponses) - // eval the fetchMocking script in the browser - await driver.executeScript(`(${fetchMocking})(${fetchMockResponsesJson})`) -} - -async function checkBrowserForConsoleErrors (driver) { - const ignoredLogTypes = ['WARNING'] - const ignoredErrorMessages = [ - // Third-party Favicon 404s show up as errors - 'favicon.ico - Failed to load resource: the server responded with a status of 404 (Not Found)', - ] - 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()) - return errorObjects.filter(entry => !ignoredErrorMessages.some(message => entry.message.includes(message))) -} - -async function verboseReportOnFailure (driver, 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) - const screenshot = await driver.takeScreenshot() - await pify(fs.writeFile)(`${filepathBase}-screenshot.png`, screenshot, { encoding: 'base64' }) - const htmlSource = await driver.getPageSource() - await pify(fs.writeFile)(`${filepathBase}-dom.html`, htmlSource) -} - -function delay (time) { - return new Promise(resolve => setTimeout(resolve, time)) -} - -async function findElement (driver, by, timeout = 10000) { - return driver.wait(until.elementLocated(by), timeout) -} - -async function findElements (driver, by, timeout = 10000) { - return driver.wait(until.elementsLocated(by), timeout) -} - -async function openNewPage (driver, url) { - const newHandle = await driver.switchTo().newWindow() - await driver.get(url) - return newHandle -} - -async function waitUntilXWindowHandles (driver, x, delayStep = 1000, timeout = 5000) { - let timeElapsed = 0 - while (timeElapsed <= timeout) { - const windowHandles = await driver.getAllWindowHandles() - if (windowHandles.length === x) { - return - } - await delay(delayStep) - timeElapsed += delayStep - } - throw new Error('waitUntilXWindowHandles timed out polling window handles') -} - -async function switchToWindowWithTitle (driver, title, windowHandles) { - if (!windowHandles) { - windowHandles = await driver.getAllWindowHandles() - } - - for (const handle of windowHandles) { - await driver.switchTo().window(handle) - const handleTitle = await driver.getTitle() - if (handleTitle === title) { - return handle - } - } - - throw new Error('No window with title: ' + title) -} - -/** - * Closes all windows except those in the given list of exceptions - * @param {object} driver the WebDriver instance - * @param {Array} exceptions the list of window handle exceptions - * @param {Array?} windowHandles the full list of window handles - * @returns {Promise} - */ -async function closeAllWindowHandlesExcept (driver, exceptions, windowHandles) { - windowHandles = windowHandles || await driver.getAllWindowHandles() - - for (const handle of windowHandles) { - if (!exceptions.includes(handle)) { - await driver.switchTo().window(handle) - await delay(1000) - await driver.close() - await delay(1000) - } - } -} - -async function assertElementNotPresent (webdriver, driver, by) { - let dataTab - try { - dataTab = await findElement(driver, by, 4000) - } catch (err) { - assert(err instanceof webdriver.error.NoSuchElementError || err instanceof webdriver.error.TimeoutError) - } - assert.ok(!dataTab, 'Found element that should not be present') -} diff --git a/test/e2e/incremental-security.spec.js b/test/e2e/incremental-security.spec.js index 9aa69e578..811040452 100644 --- a/test/e2e/incremental-security.spec.js +++ b/test/e2e/incremental-security.spec.js @@ -3,15 +3,10 @@ const webdriver = require('selenium-webdriver') const { By, until } = webdriver const { - assertElementNotPresent, - checkBrowserForConsoleErrors, - delay, - findElement, - findElements, - openNewPage, - verboseReportOnFailure, - setupFetchMocking, prepareExtensionForTesting, + tinyDelayMs, + regularDelayMs, + largeDelayMs, } = require('./helpers') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -22,10 +17,6 @@ describe('MetaMask', function () { let driver let publicAddress - const tinyDelayMs = 200 - const regularDelayMs = tinyDelayMs * 2 - const largeDelayMs = regularDelayMs * 2 - this.timeout(0) this.bail(true) @@ -44,12 +35,11 @@ describe('MetaMask', function () { }) const result = await prepareExtensionForTesting() driver = result.driver - await setupFetchMocking(driver) }) afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { const errorReports = errors.map(err => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` @@ -57,7 +47,7 @@ describe('MetaMask', function () { } } if (this.currentTest.state === 'failed') { - await verboseReportOnFailure(driver, this.currentTest) + await driver.verboseReportOnFailure(driver, this.currentTest) } }) @@ -68,51 +58,51 @@ describe('MetaMask', function () { describe('Going through the first time flow, but skipping the seed phrase challenge', () => { it('clicks the continue button on the welcome screen', async () => { - await findElement(driver, By.css('.welcome-page__header')) - const welcomeScreenBtn = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) + await driver.findElement(By.css('.welcome-page__header')) + const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) welcomeScreenBtn.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { - const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) + const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) customRpcButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await findElement(driver, By.css('.btn-default')) + const optOutButton = await driver.findElement(By.css('.btn-default')) optOutButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('accepts a secure password', async () => { - const passwordBox = await findElement(driver, By.css('.first-time-flow__form #create-password')) - const passwordBoxConfirm = await findElement(driver, By.css('.first-time-flow__form #confirm-password')) - const button = await findElement(driver, By.css('.first-time-flow__form button')) + const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) + const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) + const button = await driver.findElement(By.css('.first-time-flow__form button')) await passwordBox.sendKeys('correct horse battery staple') await passwordBoxConfirm.sendKeys('correct horse battery staple') - const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox')) + const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) await tosCheckBox.click() await button.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('skips the seed phrase challenge', async () => { - const button = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) + const button = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) await button.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const detailsButton = await findElement(driver, By.css('.account-details__details-button')) + const detailsButton = await driver.findElement(By.css('.account-details__details-button')) await detailsButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('gets the current accounts address', async () => { - const addressInput = await findElement(driver, By.css('.qr-ellip-address')) + const addressInput = await driver.findElement(By.css('.qr-ellip-address')) publicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) @@ -121,7 +111,7 @@ describe('MetaMask', function () { await accountModalClose.click() await driver.wait(until.stalenessOf(accountModal)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) @@ -133,28 +123,28 @@ describe('MetaMask', function () { const windowHandles = await driver.getAllWindowHandles() extension = windowHandles[0] - await openNewPage(driver, 'http://127.0.0.1:8080/') - await delay(regularDelayMs) + await driver.openNewPage('http://127.0.0.1:8080/') + await driver.delay(regularDelayMs) }) it('sends eth to the current account', async () => { - const addressInput = await findElement(driver, By.css('#address')) + const addressInput = await driver.findElement(By.css('#address')) await addressInput.sendKeys(publicAddress) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const sendButton = await findElement(driver, By.css('#send')) + const sendButton = await driver.findElement(By.css('#send')) await sendButton.click() - const txStatus = await findElement(driver, By.css('#success')) + const txStatus = await driver.findElement(By.css('#success')) await driver.wait(until.elementTextMatches(txStatus, /Success/), 15000) }) it('switches back to MetaMask', async () => { - await driver.switchTo().window(extension) + await driver.switchToWindow(extension) }) it('should have the correct amount of eth', async () => { - const balances = await findElements(driver, By.css('.currency-display-component__text')) + const balances = await driver.findElements(By.css('.currency-display-component__text')) await driver.wait(until.elementTextMatches(balances[0], /1/), 15000) const balance = await balances[0].getText() @@ -164,40 +154,40 @@ describe('MetaMask', function () { describe('backs up the seed phrase', () => { it('should show a backup reminder', async () => { - const backupReminder = await findElements(driver, By.xpath("//div[contains(@class, 'home-notification__text') and contains(text(), 'Backup your Secret Recovery code to keep your wallet and funds secure')]")) + const backupReminder = await driver.findElements(By.xpath("//div[contains(@class, 'home-notification__text') and contains(text(), 'Backup your Secret Recovery code to keep your wallet and funds secure')]")) assert.equal(backupReminder.length, 1) }) it('should take the user to the seedphrase backup screen', async () => { - const backupButton = await findElement(driver, By.css('.home-notification__accept-button')) + const backupButton = await driver.findElement(By.css('.home-notification__accept-button')) await backupButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) let seedPhrase it('reveals the seed phrase', async () => { const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button') - await driver.wait(until.elementLocated(byRevealButton, 10000)) - const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000) + const revealSeedPhraseButton = await driver.findElement(byRevealButton) await revealSeedPhraseButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - seedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')).getText() + const revealedSeedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')) + seedPhrase = await revealedSeedPhrase.getText() assert.equal(seedPhrase.split(' ').length, 12) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) async function clickWordAndWait (word) { const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]` - const word0 = await findElement(driver, By.xpath(xpath), 10000) + const word0 = await driver.findElement(By.xpath(xpath)) await word0.click() - await delay(tinyDelayMs) + await driver.delay(tinyDelayMs) } it('can retype the seed phrase', async () => { @@ -207,19 +197,19 @@ describe('MetaMask', function () { await clickWordAndWait(word) } - const confirm = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirm = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirm.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('can click through the success screen', async () => { - const confirm = await findElement(driver, By.xpath(`//button[contains(text(), 'All Done')]`)) + const confirm = await driver.findElement(By.xpath(`//button[contains(text(), 'All Done')]`)) await confirm.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('should have the correct amount of eth', async () => { - const balances = await findElements(driver, By.css('.currency-display-component__text')) + const balances = await driver.findElements(By.css('.currency-display-component__text')) await driver.wait(until.elementTextMatches(balances[0], /1/), 15000) const balance = await balances[0].getText() @@ -227,7 +217,7 @@ describe('MetaMask', function () { }) it('should not show a backup reminder', async () => { - await assertElementNotPresent(webdriver, driver, By.css('.backup-notification')) + await driver.assertElementNotPresent(By.css('.backup-notification')) }) }) }) diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index 161ed0adf..2e8d74f36 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -3,13 +3,10 @@ const webdriver = require('selenium-webdriver') const { By, until } = webdriver const { - checkBrowserForConsoleErrors, - delay, - findElement, - findElements, - verboseReportOnFailure, - setupFetchMocking, prepareExtensionForTesting, + tinyDelayMs, + regularDelayMs, + largeDelayMs, } = require('./helpers') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -20,9 +17,6 @@ describe('MetaMask', function () { let driver const testSeedPhrase = 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent' - const tinyDelayMs = 200 - const regularDelayMs = tinyDelayMs * 2 - const largeDelayMs = regularDelayMs * 2 this.timeout(0) this.bail(true) @@ -31,12 +25,11 @@ describe('MetaMask', function () { await ganacheServer.start() const result = await prepareExtensionForTesting({ responsive: true }) driver = result.driver - await setupFetchMocking(driver) }) afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { const errorReports = errors.map(err => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` @@ -44,7 +37,7 @@ describe('MetaMask', function () { } } if (this.currentTest.state === 'failed') { - await verboseReportOnFailure(driver, this.currentTest) + await driver.verboseReportOnFailure(driver, this.currentTest) } }) @@ -55,63 +48,63 @@ describe('MetaMask', function () { describe('Going through the first time flow', () => { it('clicks the continue button on the welcome screen', async () => { - await findElement(driver, By.css('.welcome-page__header')) - const welcomeScreenBtn = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) + await driver.findElement(By.css('.welcome-page__header')) + const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) welcomeScreenBtn.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { - const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) + const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) customRpcButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "I agree" option on the metametrics opt-in screen', async () => { - const optOutButton = await findElement(driver, By.css('.btn-primary')) + const optOutButton = await driver.findElement(By.css('.btn-primary')) optOutButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('accepts a secure password', async () => { - const passwordBox = await findElement(driver, By.css('.first-time-flow__form #create-password')) - const passwordBoxConfirm = await findElement(driver, By.css('.first-time-flow__form #confirm-password')) - const button = await findElement(driver, By.css('.first-time-flow__form button')) + const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) + const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) + const button = await driver.findElement(By.css('.first-time-flow__form button')) await passwordBox.sendKeys('correct horse battery staple') await passwordBoxConfirm.sendKeys('correct horse battery staple') - const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox')) + const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) await tosCheckBox.click() await button.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) let seedPhrase it('reveals the seed phrase', async () => { const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button') - await driver.wait(until.elementLocated(byRevealButton, 10000)) - const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000) + const revealSeedPhraseButton = await driver.findElement(byRevealButton) await revealSeedPhraseButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - seedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')).getText() + const revealedSeedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')) + seedPhrase = await revealedSeedPhrase.getText() assert.equal(seedPhrase.split(' ').length, 12) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) async function clickWordAndWait (word) { const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]` - const word0 = await findElement(driver, By.xpath(xpath), 10000) + const word0 = await driver.findElement(By.xpath(xpath)) await word0.click() - await delay(tinyDelayMs) + await driver.delay(tinyDelayMs) } it('can retype the seed phrase', async () => { @@ -121,126 +114,129 @@ describe('MetaMask', function () { await clickWordAndWait(word) } - const confirm = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirm = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirm.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('clicks through the success screen', async () => { - await findElement(driver, By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) + await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) + const doneButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await doneButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Show account information', () => { it('show account details dropdown menu', async () => { - await driver.findElement(By.css('div.menu-bar__open-in-browser')).click() + const openInBrowser = await driver.findElement(By.css('div.menu-bar__open-in-browser')) + await openInBrowser.click() const options = await driver.findElements(By.css('div.menu.account-details-dropdown div.menu__item')) assert.equal(options.length, 4) // HD Wallet type does not have to show the Remove Account option - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Import seed phrase', () => { it('logs out of the vault', async () => { - await driver.findElement(By.css('.account-menu__icon')).click() - await delay(regularDelayMs) + const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) + await accountMenuButton.click() + await driver.delay(regularDelayMs) - const logoutButton = await findElement(driver, By.css('.account-menu__logout-button')) + const logoutButton = await driver.findElement(By.css('.account-menu__logout-button')) assert.equal(await logoutButton.getText(), 'Log out') await logoutButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('imports seed phrase', async () => { - const restoreSeedLink = await findElement(driver, By.css('.unlock-page__link--import')) + const restoreSeedLink = await driver.findElement(By.css('.unlock-page__link--import')) assert.equal(await restoreSeedLink.getText(), 'Import using account seed phrase') await restoreSeedLink.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const seedTextArea = await findElement(driver, By.css('textarea')) + const seedTextArea = await driver.findElement(By.css('textarea')) await seedTextArea.sendKeys(testSeedPhrase) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) const passwordInputs = await driver.findElements(By.css('input')) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) await passwordInputs[0].sendKeys('correct horse battery staple') await passwordInputs[1].sendKeys('correct horse battery staple') - await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.restore.message}')]`)).click() - await delay(regularDelayMs) + const restoreButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.restore.message}')]`)) + await restoreButton.click() + await driver.delay(regularDelayMs) }) it('switches to localhost', async () => { - const networkDropdown = await findElement(driver, By.css('.network-name')) + const networkDropdown = await driver.findElement(By.css('.network-name')) await networkDropdown.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const [localhost] = await findElements(driver, By.xpath(`//span[contains(text(), 'Localhost')]`)) + const [localhost] = await driver.findElements(By.xpath(`//span[contains(text(), 'Localhost')]`)) await localhost.click() - await delay(largeDelayMs * 2) + await driver.delay(largeDelayMs * 2) }) it('balance renders', async () => { - const balance = await findElement(driver, By.css('.transaction-view-balance__primary-balance')) + const balance = await driver.findElement(By.css('.transaction-view-balance__primary-balance')) await driver.wait(until.elementTextMatches(balance, /100\s*ETH/)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Send ETH from inside MetaMask', () => { it('starts to send a transaction', async function () { - const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`)) + const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) await sendButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const inputAddress = await findElement(driver, By.css('input[placeholder="Search, public address (0x), or ENS"]')) + const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') - const inputAmount = await findElement(driver, By.css('.unit-input__input')) + const inputAmount = await driver.findElement(By.css('.unit-input__input')) await inputAmount.sendKeys('1') const inputValue = await inputAmount.getAttribute('value') assert.equal(inputValue, '1') - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('opens and closes the gas modal', async function () { // Set the gas limit - const configureGas = await findElement(driver, By.css('.advanced-gas-options-btn')) + const configureGas = await driver.findElement(By.css('.advanced-gas-options-btn')) await configureGas.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) const gasModal = await driver.findElement(By.css('span .modal')) - const save = await findElement(driver, By.css('.page-container__header-close-text')) + const save = await driver.findElement(By.css('.page-container__header-close-text')) await save.click() await driver.wait(until.stalenessOf(gasModal), 10000) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('clicks through to the confirm screen', async function () { // Continue to next screen - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('confirms the transaction', async function () { - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 1 }, 10000) - const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary')) + const txValues = await driver.findElement(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000) }) }) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index 0786714a9..02184d0fd 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -3,18 +3,10 @@ const webdriver = require('selenium-webdriver') const { By, Key, until } = webdriver const { - assertElementNotPresent, - checkBrowserForConsoleErrors, - closeAllWindowHandlesExcept, - delay, - findElement, - findElements, - openNewPage, - switchToWindowWithTitle, - verboseReportOnFailure, - waitUntilXWindowHandles, - setupFetchMocking, prepareExtensionForTesting, + tinyDelayMs, + regularDelayMs, + largeDelayMs, } = require('./helpers') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -26,9 +18,6 @@ describe('MetaMask', function () { let tokenAddress const testSeedPhrase = 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent' - const tinyDelayMs = 200 - const regularDelayMs = tinyDelayMs * 2 - const largeDelayMs = regularDelayMs * 2 this.timeout(0) this.bail(true) @@ -37,12 +26,11 @@ describe('MetaMask', function () { await ganacheServer.start() const result = await prepareExtensionForTesting() driver = result.driver - await setupFetchMocking(driver) }) afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { const errorReports = errors.map(err => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` @@ -50,7 +38,7 @@ describe('MetaMask', function () { } } if (this.currentTest.state === 'failed') { - await verboseReportOnFailure(driver, this.currentTest) + await driver.verboseReportOnFailure(driver, this.currentTest) } }) @@ -61,63 +49,64 @@ describe('MetaMask', function () { describe('Going through the first time flow', () => { it('clicks the continue button on the welcome screen', async () => { - await findElement(driver, By.css('.welcome-page__header')) - const welcomeScreenBtn = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) + await driver.findElement(By.css('.welcome-page__header')) + const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) welcomeScreenBtn.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { - const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) + const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) customRpcButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await findElement(driver, By.css('.btn-default')) + const optOutButton = await driver.findElement(By.css('.btn-default')) optOutButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('accepts a secure password', async () => { - const passwordBox = await findElement(driver, By.css('.first-time-flow__form #create-password')) - const passwordBoxConfirm = await findElement(driver, By.css('.first-time-flow__form #confirm-password')) - const button = await findElement(driver, By.css('.first-time-flow__form button')) + const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) + const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) + const button = await driver.findElement(By.css('.first-time-flow__form button')) await passwordBox.sendKeys('correct horse battery staple') await passwordBoxConfirm.sendKeys('correct horse battery staple') - const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox')) + const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) await tosCheckBox.click() await button.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) let seedPhrase it('reveals the seed phrase', async () => { const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button') - await driver.wait(until.elementLocated(byRevealButton, 10000)) - const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000) + await driver.findElement(byRevealButton) + const revealSeedPhraseButton = await driver.findElement(byRevealButton) await revealSeedPhraseButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - seedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')).getText() + const revealedSeedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')) + seedPhrase = await revealedSeedPhrase.getText() assert.equal(seedPhrase.split(' ').length, 12) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) async function clickWordAndWait (word) { const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]` - const word0 = await findElement(driver, By.xpath(xpath), 10000) + const word0 = await driver.findElement(By.xpath(xpath)) await word0.click() - await delay(tinyDelayMs) + await driver.delay(tinyDelayMs) } it('can retype the seed phrase', async () => { @@ -127,142 +116,147 @@ describe('MetaMask', function () { await clickWordAndWait(word) } - const confirm = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirm = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirm.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('clicks through the success screen', async () => { - await findElement(driver, By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) + await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) + const doneButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await doneButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Show account information', () => { it('shows the QR code for the account', async () => { - await driver.findElement(By.css('.account-details__details-button')).click() - await driver.findElement(By.css('.qr-wrapper')).isDisplayed() - await delay(regularDelayMs) + const accountDetailsButton = await driver.findElement(By.css('.account-details__details-button')) + await accountDetailsButton.click() + await driver.findVisibleElement(By.css('.qr-wrapper')) + await driver.delay(regularDelayMs) const accountModal = await driver.findElement(By.css('span .modal')) - const accountModalClose = await driver.findElement(By.css('.account-modal-close')) await accountModalClose.click() await driver.wait(until.stalenessOf(accountModal)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Log out an log back in', () => { it('logs out of the account', async () => { - await driver.findElement(By.css('.account-menu__icon')).click() - await delay(regularDelayMs) + const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) + await accountMenuButton.click() + await driver.delay(regularDelayMs) - const logoutButton = await findElement(driver, By.css('.account-menu__logout-button')) + const logoutButton = await driver.findElement(By.css('.account-menu__logout-button')) assert.equal(await logoutButton.getText(), 'Log out') await logoutButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('accepts the account password after lock', async () => { - await driver.findElement(By.id('password')).sendKeys('correct horse battery staple') - await driver.findElement(By.id('password')).sendKeys(Key.ENTER) - await delay(largeDelayMs * 4) + const passwordField = await driver.findElement(By.id('password')) + await passwordField.sendKeys('correct horse battery staple') + await passwordField.sendKeys(Key.ENTER) + await driver.delay(largeDelayMs * 4) }) }) describe('Add account', () => { it('choose Create Account from the account menu', async () => { - await driver.findElement(By.css('.account-menu__icon')).click() - await delay(regularDelayMs) + const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) + await accountMenuButton.click() + await driver.delay(regularDelayMs) - const createAccount = await findElement(driver, By.xpath(`//div[contains(text(), 'Create Account')]`)) + const createAccount = await driver.findElement(By.xpath(`//div[contains(text(), 'Create Account')]`)) await createAccount.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('set account name', async () => { - const accountName = await findElement(driver, By.css('.new-account-create-form input')) + const accountName = await driver.findElement(By.css('.new-account-create-form input')) await accountName.sendKeys('2nd account') - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const create = await findElement(driver, By.xpath(`//button[contains(text(), 'Create')]`)) + const create = await driver.findElement(By.xpath(`//button[contains(text(), 'Create')]`)) await create.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('should display correct account name', async () => { - const accountName = await findElement(driver, By.css('.account-details__account-name')) + const accountName = await driver.findElement(By.css('.account-details__account-name')) assert.equal(await accountName.getText(), '2nd account') - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Import seed phrase', () => { it('logs out of the vault', async () => { - await driver.findElement(By.css('.account-menu__icon')).click() - await delay(regularDelayMs) + const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) + accountMenuButton.click() + await driver.delay(regularDelayMs) - const logoutButton = await findElement(driver, By.css('.account-menu__logout-button')) + const logoutButton = await driver.findElement(By.css('.account-menu__logout-button')) assert.equal(await logoutButton.getText(), 'Log out') await logoutButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('imports seed phrase', async () => { - const restoreSeedLink = await findElement(driver, By.css('.unlock-page__link--import')) + const restoreSeedLink = await driver.findElement(By.css('.unlock-page__link--import')) assert.equal(await restoreSeedLink.getText(), 'Import using account seed phrase') await restoreSeedLink.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const seedTextArea = await findElement(driver, By.css('textarea')) + const seedTextArea = await driver.findElement(By.css('textarea')) await seedTextArea.sendKeys(testSeedPhrase) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) const passwordInputs = await driver.findElements(By.css('input')) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) await passwordInputs[0].sendKeys('correct horse battery staple') await passwordInputs[1].sendKeys('correct horse battery staple') - await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.restore.message}')]`)).click() - await delay(regularDelayMs) + const restoreButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.restore.message}')]`)) + await restoreButton.click() + await driver.delay(regularDelayMs) }) it('balance renders', async () => { - const balance = await findElement(driver, By.css('.balance-display .token-amount')) + const balance = await driver.findElement(By.css('.balance-display .token-amount')) await driver.wait(until.elementTextMatches(balance, /100\s*ETH/)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Send ETH from inside MetaMask using default gas', () => { it('starts a send transaction', async function () { - const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`)) + const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) await sendButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const inputAddress = await findElement(driver, By.css('input[placeholder="Search, public address (0x), or ENS"]')) + const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') - const inputAmount = await findElement(driver, By.css('.unit-input__input')) + const inputAmount = await driver.findElement(By.css('.unit-input__input')) await inputAmount.sendKeys('1000') - const errorAmount = await findElement(driver, By.css('.send-v2__error-amount')) + const errorAmount = await driver.findElement(By.css('.send-v2__error-amount')) assert.equal(await errorAmount.getText(), 'Insufficient funds.', 'send screen should render an insufficient fund error message') await inputAmount.sendKeys(Key.BACK_SPACE) - await delay(50) + await driver.delay(50) await inputAmount.sendKeys(Key.BACK_SPACE) - await delay(50) + await driver.delay(50) await inputAmount.sendKeys(Key.BACK_SPACE) - await delay(tinyDelayMs) + await driver.delay(tinyDelayMs) - await assertElementNotPresent(webdriver, driver, By.css('.send-v2__error-amount')) + await driver.assertElementNotPresent(By.css('.send-v2__error-amount')) - const amountMax = await findElement(driver, By.css('.send-v2__amount-max')) + const amountMax = await driver.findElement(By.css('.send-v2__amount-max')) await amountMax.click() assert.equal(await inputAmount.isEnabled(), false) @@ -279,123 +273,123 @@ describe('MetaMask', function () { inputValue = await inputAmount.getAttribute('value') assert.equal(inputValue, '1') - await delay(regularDelayMs) + await driver.delay(regularDelayMs) // Continue to next screen - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('confirms the transaction', async function () { - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(largeDelayMs * 2) + await driver.delay(largeDelayMs * 2) }) it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 1 }, 10000) - const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary')) + const txValues = await driver.findElement(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000) }) }) describe('Send ETH from inside MetaMask using fast gas option', () => { it('starts a send transaction', async function () { - const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`)) + const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) await sendButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const inputAddress = await findElement(driver, By.css('input[placeholder="Search, public address (0x), or ENS"]')) + const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') - const inputAmount = await findElement(driver, By.css('.unit-input__input')) + const inputAmount = await driver.findElement(By.css('.unit-input__input')) await inputAmount.sendKeys('1') const inputValue = await inputAmount.getAttribute('value') assert.equal(inputValue, '1') // Set the gas price - const fastGas = await findElement(driver, By.xpath(`//button/div/div[contains(text(), "Fast")]`)) + const fastGas = await driver.findElement(By.xpath(`//button/div/div[contains(text(), "Fast")]`)) await fastGas.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) // Continue to next screen - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('confirms the transaction', async function () { - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 2 }, 10000) - const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary')) + const txValues = await driver.findElement(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000) }) }) describe('Send ETH from inside MetaMask using advanced gas modal', () => { it('starts a send transaction', async function () { - const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`)) + const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) await sendButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const inputAddress = await findElement(driver, By.css('input[placeholder="Search, public address (0x), or ENS"]')) + const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') - const inputAmount = await findElement(driver, By.css('.unit-input__input')) + const inputAmount = await driver.findElement(By.css('.unit-input__input')) await inputAmount.sendKeys('1') const inputValue = await inputAmount.getAttribute('value') assert.equal(inputValue, '1') // Set the gas limit - const configureGas = await findElement(driver, By.css('.advanced-gas-options-btn')) + const configureGas = await driver.findElement(By.css('.advanced-gas-options-btn')) await configureGas.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) const gasModal = await driver.findElement(By.css('span .modal')) - const save = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`)) + const save = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) await save.click() await driver.wait(until.stalenessOf(gasModal)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) // Continue to next screen - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('confirms the transaction', async function () { - const transactionAmounts = await findElements(driver, By.css('.currency-display-component__text')) + const transactionAmounts = await driver.findElements(By.css('.currency-display-component__text')) const transactionAmount = transactionAmounts[0] assert.equal(await transactionAmount.getText(), '1') - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 3 }, 10000) - const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary')) + const txValues = await driver.findElement(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000) }) }) @@ -407,132 +401,133 @@ describe('MetaMask', function () { let dapp it('goes to the settings screen', async () => { - await driver.findElement(By.css('.account-menu__icon')).click() - await delay(regularDelayMs) + const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) + await accountMenuButton.click() + await driver.delay(regularDelayMs) - const settingsButton = await findElement(driver, By.xpath(`//div[contains(text(), 'Settings')]`)) + const settingsButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Settings')]`)) settingsButton.click() - // await findElement(driver, By.css('.tab-bar')) + // await driver.findElement(By.css('.tab-bar')) - const advancedTab = await findElement(driver, By.xpath(`//div[contains(text(), 'Advanced')]`)) + const advancedTab = await driver.findElement(By.xpath(`//div[contains(text(), 'Advanced')]`)) await advancedTab.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const showConversionToggle = await findElement(driver, By.css('.settings-page__content-row:nth-of-type(6) .settings-page__content-item-col > div > div')) + const showConversionToggle = await driver.findElement(By.css('.settings-page__content-row:nth-of-type(6) .settings-page__content-item-col > div > div')) await showConversionToggle.click() - const advancedGasTitle = await findElement(driver, By.xpath(`//span[contains(text(), 'Advanced gas controls')]`)) - await driver.executeScript('arguments[0].scrollIntoView(true)', advancedGasTitle) + const advancedGasTitle = await driver.findElement(By.xpath(`//span[contains(text(), 'Advanced gas controls')]`)) + await driver.scrollToElement(advancedGasTitle) - const advancedGasToggle = await findElement(driver, By.css('.settings-page__content-row:nth-of-type(4) .settings-page__content-item-col > div > div')) + const advancedGasToggle = await driver.findElement(By.css('.settings-page__content-row:nth-of-type(4) .settings-page__content-item-col > div > div')) await advancedGasToggle.click() windowHandles = await driver.getAllWindowHandles() extension = windowHandles[0] - await closeAllWindowHandlesExcept(driver, [extension]) + await driver.closeAllWindowHandlesExcept([extension]) - const metamaskHomeButton = await findElement(driver, By.css('.app-header__logo-container')) + const metamaskHomeButton = await driver.findElement(By.css('.app-header__logo-container')) await metamaskHomeButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('connects the dapp', async () => { - await openNewPage(driver, 'http://127.0.0.1:8080/') - await delay(regularDelayMs) + await driver.openNewPage('http://127.0.0.1:8080/') + await driver.delay(regularDelayMs) - const connectButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Connect')]`)) + const connectButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Connect')]`)) await connectButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - await waitUntilXWindowHandles(driver, 3) + await driver.waitUntilXWindowHandles(3) windowHandles = await driver.getAllWindowHandles() extension = windowHandles[0] - dapp = await switchToWindowWithTitle(driver, 'E2E Test Dapp', windowHandles) + dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) popup = windowHandles.find(handle => handle !== extension && handle !== dapp) - await driver.switchTo().window(popup) + await driver.switchToWindow(popup) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const accountButton = await findElement(driver, By.css('.permissions-connect-choose-account__account')) + const accountButton = await driver.findElement(By.css('.permissions-connect-choose-account__account')) await accountButton.click() - const submitButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Submit')]`)) + const submitButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Submit')]`)) await submitButton.click() - await waitUntilXWindowHandles(driver, 2) - await driver.switchTo().window(dapp) - await delay(regularDelayMs) + await driver.waitUntilXWindowHandles(2) + await driver.switchToWindow(dapp) + await driver.delay(regularDelayMs) }) it('initiates a send from the dapp', async () => { - const send3eth = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`), 10000) + const send3eth = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`), 10000) await send3eth.click() - await delay(2000) + await driver.delay(2000) windowHandles = await driver.getAllWindowHandles() - await switchToWindowWithTitle(driver, 'MetaMask Notification', windowHandles) - await delay(regularDelayMs) + await driver.switchToWindowWithTitle('MetaMask Notification', windowHandles) + await driver.delay(regularDelayMs) - await assertElementNotPresent(webdriver, driver, By.xpath(`//li[contains(text(), 'Data')]`)) + await driver.assertElementNotPresent(By.xpath(`//li[contains(text(), 'Data')]`)) - const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.advanced-gas-inputs__gas-edit-row__input')) + const [gasPriceInput, gasLimitInput] = await driver.findElements(By.css('.advanced-gas-inputs__gas-edit-row__input')) await gasPriceInput.sendKeys(Key.chord(Key.CONTROL, 'a')) - await delay(50) + await driver.delay(50) await gasPriceInput.sendKeys(Key.BACK_SPACE) - await delay(50) + await driver.delay(50) await gasPriceInput.sendKeys('10') - await delay(50) - await delay(tinyDelayMs) - await delay(50) + await driver.delay(50) + await driver.delay(tinyDelayMs) + await driver.delay(50) await gasLimitInput.sendKeys(Key.chord(Key.CONTROL, 'a')) - await delay(50) + await driver.delay(50) await gasLimitInput.sendKeys('25000') - await delay(1000) + await driver.delay(1000) - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`), 10000) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`), 10000) await confirmButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - await waitUntilXWindowHandles(driver, 2) - await driver.switchTo().window(extension) - await delay(regularDelayMs) + await driver.waitUntilXWindowHandles(2) + await driver.switchToWindow(extension) + await driver.delay(regularDelayMs) }) let txValues it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 4 }, 10000) - txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + txValues = await driver.findElements(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txValues[0], /-3\s*ETH/), 10000) }) it('the transaction has the expected gas price', async function () { - await delay(largeDelayMs) + await driver.delay(largeDelayMs) let txGasPriceLabels let txGasPrices try { await txValues[0].click() - txGasPrices = await findElements(driver, By.css('.transaction-breakdown__value')) - txGasPriceLabels = await findElements(driver, By.css('.transaction-breakdown-row__title')) - txGasPrices = await findElements(driver, By.css('.transaction-breakdown__value')) + txGasPrices = await driver.findElements(By.css('.transaction-breakdown__value')) + txGasPriceLabels = await driver.findElements(By.css('.transaction-breakdown-row__title')) + txGasPrices = await driver.findElements(By.css('.transaction-breakdown__value')) await driver.wait(until.elementTextMatches(txGasPrices[3], /^10$/), 10000) } catch (e) { console.log(e.message) - txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + txValues = await driver.findElements(By.css('.transaction-list-item__amount--primary')) await txValues[0].click() - txGasPriceLabels = await findElements(driver, By.css('.transaction-breakdown-row__title')) - txGasPrices = await findElements(driver, By.css('.transaction-breakdown__value')) + txGasPriceLabels = await driver.findElements(By.css('.transaction-breakdown-row__title')) + txGasPrices = await driver.findElements(By.css('.transaction-breakdown__value')) await driver.wait(until.elementTextMatches(txGasPrices[3], /^10$/), 10000) } assert(txGasPriceLabels[2]) @@ -543,92 +538,92 @@ describe('MetaMask', function () { describe('Navigate transactions', () => { it('adds multiple transactions', async () => { - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - await waitUntilXWindowHandles(driver, 2) + await driver.waitUntilXWindowHandles(2) const windowHandles = await driver.getAllWindowHandles() const extension = windowHandles[0] const dapp = windowHandles[1] - await driver.switchTo().window(dapp) - await delay(largeDelayMs) + await driver.switchToWindow(dapp) + await driver.delay(largeDelayMs) - const send3eth = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`), 10000) + const send3eth = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) await send3eth.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) - const contractDeployment = await findElement(driver, By.xpath(`//button[contains(text(), 'Deploy Contract')]`), 10000) + const contractDeployment = await driver.findElement(By.xpath(`//button[contains(text(), 'Deploy Contract')]`)) await contractDeployment.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) await send3eth.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) await contractDeployment.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) - await driver.switchTo().window(extension) - await delay(regularDelayMs) + await driver.switchToWindow(extension) + await driver.delay(regularDelayMs) - let transactions = await findElements(driver, By.css('.transaction-list-item')) + let transactions = await driver.findElements(By.css('.transaction-list-item')) await transactions[0].click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) try { - transactions = await findElements(driver, By.css('.transaction-list-item'), 1000) + transactions = await driver.findElements(By.css('.transaction-list-item')) await transactions[0].click() } catch (e) { console.log(e) } - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('navigates the transactions', async () => { - let navigateTxButtons = await findElements(driver, By.css('.confirm-page-container-navigation__arrow'), 20000) + let navigateTxButtons = await driver.findElements(By.css('.confirm-page-container-navigation__arrow')) assert.equal(navigateTxButtons.length, 4, 'navigation button present') await navigateTxButtons[2].click() - let navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation')) + let navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) let navigationText = await navigationElement.getText() assert.equal(navigationText.includes('2'), true, 'changed transaction right') - navigateTxButtons = await findElements(driver, By.css('.confirm-page-container-navigation__arrow')) + navigateTxButtons = await driver.findElements(By.css('.confirm-page-container-navigation__arrow')) await navigateTxButtons[2].click() - navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation')) + navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) navigationText = await navigationElement.getText() assert.equal(navigationText.includes('3'), true, 'changed transaction right') - navigateTxButtons = await findElements(driver, By.css('.confirm-page-container-navigation__arrow')) + navigateTxButtons = await driver.findElements(By.css('.confirm-page-container-navigation__arrow')) await navigateTxButtons[2].click() - navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation')) + navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) navigationText = await navigationElement.getText() assert.equal(navigationText.includes('4'), true, 'changed transaction right') - navigateTxButtons = await findElements(driver, By.css('.confirm-page-container-navigation__arrow')) + navigateTxButtons = await driver.findElements(By.css('.confirm-page-container-navigation__arrow')) await navigateTxButtons[0].click() - navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation')) + navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) navigationText = await navigationElement.getText() assert.equal(navigationText.includes('1'), true, 'navigate to first transaction') - navigateTxButtons = await findElements(driver, By.css('.confirm-page-container-navigation__arrow')) + navigateTxButtons = await driver.findElements(By.css('.confirm-page-container-navigation__arrow')) await navigateTxButtons[3].click() - navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation')) + navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) navigationText = await navigationElement.getText() assert.equal(navigationText.split('4').length, 3, 'navigate to last transaction') - navigateTxButtons = await findElements(driver, By.css('.confirm-page-container-navigation__arrow')) + navigateTxButtons = await driver.findElements(By.css('.confirm-page-container-navigation__arrow')) await navigateTxButtons[1].click() - navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation')) + navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) navigationText = await navigationElement.getText() assert.equal(navigationText.includes('3'), true, 'changed transaction left') - navigateTxButtons = await findElements(driver, By.css('.confirm-page-container-navigation__arrow')) + navigateTxButtons = await driver.findElements(By.css('.confirm-page-container-navigation__arrow')) await navigateTxButtons[1].click() - navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation')) + navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) navigationText = await navigationElement.getText() assert.equal(navigationText.includes('2'), true, 'changed transaction left') }) it('adds a transaction while confirm screen is in focus', async () => { - let navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation')) + let navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) let navigationText = await navigationElement.getText() assert.equal(navigationText.includes('2'), true, 'second transaction in focus') @@ -636,57 +631,57 @@ describe('MetaMask', function () { const extension = windowHandles[0] const dapp = windowHandles[1] - await driver.switchTo().window(dapp) - await delay(regularDelayMs) + await driver.switchToWindow(dapp) + await driver.delay(regularDelayMs) - const send3eth = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`), 10000) + const send3eth = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) await send3eth.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - await driver.switchTo().window(extension) - await delay(regularDelayMs) + await driver.switchToWindow(extension) + await driver.delay(regularDelayMs) - navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation')) + navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) navigationText = await navigationElement.getText() assert.equal(navigationText.includes('2'), true, 'correct (same) transaction in focus') }) it('rejects a transaction', async () => { - await delay(tinyDelayMs) - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Reject')]`), 10000) + await driver.delay(tinyDelayMs) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Reject')]`)) await confirmButton.click() - await delay(largeDelayMs * 2) + await driver.delay(largeDelayMs * 2) - const navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation')) - await delay(tinyDelayMs) + const navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) + await driver.delay(tinyDelayMs) const navigationText = await navigationElement.getText() assert.equal(navigationText.includes('4'), true, 'transaction rejected') }) it('confirms a transaction', async () => { - await delay(tinyDelayMs / 2) - const rejectButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`), 10000) - await delay(tinyDelayMs / 2) + await driver.delay(tinyDelayMs / 2) + const rejectButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) + await driver.delay(tinyDelayMs / 2) await rejectButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation')) - await delay(tinyDelayMs / 2) + const navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) + await driver.delay(tinyDelayMs / 2) const navigationText = await navigationElement.getText() - await delay(tinyDelayMs / 2) + await driver.delay(tinyDelayMs / 2) assert.equal(navigationText.includes('3'), true, 'transaction confirmed') }) it('rejects the rest of the transactions', async () => { - const rejectAllButton = await findElement(driver, By.xpath(`//a[contains(text(), 'Reject 3')]`), 10000) + const rejectAllButton = await driver.findElement(By.xpath(`//a[contains(text(), 'Reject 3')]`)) await rejectAllButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const rejectButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Reject All')]`), 10000) + const rejectButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Reject All')]`)) await rejectButton.click() - await delay(largeDelayMs * 2) + await driver.delay(largeDelayMs * 2) - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) assert.equal(confirmedTxes.length, 5, '5 transactions present') }) }) @@ -698,167 +693,163 @@ describe('MetaMask', function () { const windowHandles = await driver.getAllWindowHandles() extension = windowHandles[0] dapp = windowHandles[1] - await delay(tinyDelayMs) + await driver.delay(tinyDelayMs) - await driver.switchTo().window(dapp) - await delay(regularDelayMs) + await driver.switchToWindow(dapp) + await driver.delay(regularDelayMs) - const deployContractButton = await findElement(driver, By.css('#deployButton')) + const deployContractButton = await driver.findElement(By.css('#deployButton')) await deployContractButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - await driver.switchTo().window(extension) - await delay(regularDelayMs) + await driver.switchToWindow(extension) + await driver.delay(regularDelayMs) - const txListItem = await findElement(driver, By.xpath(`//div[contains(text(), 'Contract Deployment')]`)) + const txListItem = await driver.findElement(By.xpath(`//div[contains(text(), 'Contract Deployment')]`)) await txListItem.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('displays the contract creation data', async () => { - const dataTab = await findElement(driver, By.xpath(`//li[contains(text(), 'Data')]`)) + const dataTab = await driver.findElement(By.xpath(`//li[contains(text(), 'Data')]`)) await dataTab.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - await findElement(driver, By.xpath(`//div[contains(text(), '127.0.0.1')]`)) + await driver.findElement(By.xpath(`//div[contains(text(), '127.0.0.1')]`)) - const confirmDataDiv = await findElement(driver, By.css('.confirm-page-container-content__data-box')) + const confirmDataDiv = await driver.findElement(By.css('.confirm-page-container-content__data-box')) const confirmDataText = await confirmDataDiv.getText() assert.equal(confirmDataText.match(/0x608060405234801561001057600080fd5b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff/)) - const detailsTab = await findElement(driver, By.xpath(`//li[contains(text(), 'Details')]`)) + const detailsTab = await driver.findElement(By.xpath(`//li[contains(text(), 'Details')]`)) await detailsTab.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('confirms a deploy contract transaction', async () => { - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 6 }, 10000) - const txAction = await findElements(driver, By.css('.transaction-list-item__action')) + const txAction = await driver.findElements(By.css('.transaction-list-item__action')) await driver.wait(until.elementTextMatches(txAction[0], /Contract\sDeployment/), 10000) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('calls and confirms a contract method where ETH is sent', async () => { - await driver.switchTo().window(dapp) - await delay(regularDelayMs) + await driver.switchToWindow(dapp) + await driver.delay(regularDelayMs) - let contractStatus = await findElement(driver, By.css('#contractStatus')) + let contractStatus = await driver.findElement(By.css('#contractStatus')) await driver.wait(until.elementTextMatches(contractStatus, /Deployed/), 15000) - const depositButton = await findElement(driver, By.css('#depositButton')) + const depositButton = await driver.findElement(By.css('#depositButton')) await depositButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) - contractStatus = await findElement(driver, By.css('#contractStatus')) + contractStatus = await driver.findElement(By.css('#contractStatus')) await driver.wait(until.elementTextMatches(contractStatus, /Deposit\sinitiated/), 10000) - await driver.switchTo().window(extension) - await delay(largeDelayMs * 2) + await driver.switchToWindow(extension) + await driver.delay(largeDelayMs * 2) - await findElements(driver, By.css('.transaction-list-item')) - const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + await driver.findElements(By.css('.transaction-list-item')) + const [txListValue] = await driver.findElements(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txListValue, /-4\s*ETH/), 10000) await txListValue.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) // Set the gas limit - const configureGas = await findElement(driver, By.css('.confirm-detail-row__header-text--edit')) + const configureGas = await driver.findElement(By.css('.confirm-detail-row__header-text--edit')) await configureGas.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const gasModal = await findElement(driver, By.css('span .modal')) - await delay(regularDelayMs) - const modalTabs = await findElements(driver, By.css('.page-container__tab')) + const gasModal = await driver.findElement(By.css('span .modal')) + await driver.delay(regularDelayMs) + const modalTabs = await driver.findElements(By.css('.page-container__tab')) await modalTabs[1].click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.advanced-gas-inputs__gas-edit-row__input')) + const [gasPriceInput, gasLimitInput] = await driver.findElements(By.css('.advanced-gas-inputs__gas-edit-row__input')) const gasLimitValue = await gasLimitInput.getAttribute('value') assert(Number(gasLimitValue) < 100000, 'Gas Limit too high') await gasPriceInput.sendKeys(Key.chord(Key.CONTROL, 'a')) - await delay(50) + await driver.delay(50) await gasPriceInput.sendKeys(Key.BACK_SPACE) - await delay(50) + await driver.delay(50) await gasPriceInput.sendKeys('10') - await delay(50) + await driver.delay(50) await gasLimitInput.sendKeys(Key.chord(Key.CONTROL, 'a')) - await delay(50) + await driver.delay(50) await gasLimitInput.sendKeys(Key.BACK_SPACE) - await delay(50) + await driver.delay(50) await gasLimitInput.sendKeys('60001') - await delay(1000) + await driver.delay(1000) - const save = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`)) + const save = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) await save.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) await driver.wait(until.stalenessOf(gasModal)) - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 7 }, 10000) - const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + const txValues = await driver.findElements(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txValues[0], /-4\s*ETH/), 10000) - - // const txAccounts = await findElements(driver, By.css('.tx-list-account')) - // const firstTxAddress = await txAccounts[0].getText() - // assert(firstTxAddress.match(/^0x\w{8}\.{3}\w{4}$/)) }) it('calls and confirms a contract method where ETH is received', async () => { - await driver.switchTo().window(dapp) - await delay(regularDelayMs) + await driver.switchToWindow(dapp) + await driver.delay(regularDelayMs) - const withdrawButton = await findElement(driver, By.css('#withdrawButton')) + const withdrawButton = await driver.findElement(By.css('#withdrawButton')) await withdrawButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - await driver.switchTo().window(extension) - await delay(largeDelayMs * 2) + await driver.switchToWindow(extension) + await driver.delay(largeDelayMs * 2) - const txListItem = await findElement(driver, By.css('.transaction-list-item')) + const txListItem = await driver.findElement(By.css('.transaction-list-item')) await txListItem.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 8 }, 10000) - const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary')) + const txValues = await driver.findElement(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txValues, /-0\s*ETH/), 10000) - await closeAllWindowHandlesExcept(driver, [extension, dapp]) - await driver.switchTo().window(extension) + await driver.closeAllWindowHandlesExcept([extension, dapp]) + await driver.switchToWindow(extension) }) it('renders the correct ETH balance', async () => { - const balance = await findElement(driver, By.css('.transaction-view-balance__primary-balance')) - await delay(regularDelayMs) + const balance = await driver.findElement(By.css('.transaction-view-balance__primary-balance')) + await driver.delay(regularDelayMs) await driver.wait(until.elementTextMatches(balance, /^87.*\s*ETH.*$/), 10000) const tokenAmount = await balance.getText() assert.ok(/^87.*\s*ETH.*$/.test(tokenAmount)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) @@ -867,167 +858,167 @@ describe('MetaMask', function () { let windowHandles = await driver.getAllWindowHandles() const extension = windowHandles[0] const dapp = windowHandles[1] - await delay(regularDelayMs * 2) + await driver.delay(regularDelayMs * 2) - await driver.switchTo().window(dapp) - await delay(regularDelayMs * 2) + await driver.switchToWindow(dapp) + await driver.delay(regularDelayMs * 2) - const createToken = await findElement(driver, By.xpath(`//button[contains(text(), 'Create Token')]`)) + const createToken = await driver.findElement(By.xpath(`//button[contains(text(), 'Create Token')]`)) await createToken.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) windowHandles = await driver.getAllWindowHandles() const popup = windowHandles[2] - await driver.switchTo().window(popup) - await delay(regularDelayMs) + await driver.switchToWindow(popup) + await driver.delay(regularDelayMs) - const configureGas = await driver.wait(until.elementLocated(By.css('.confirm-detail-row__header-text--edit')), 10000) + const configureGas = await driver.findElement(By.css('.confirm-detail-row__header-text--edit')) await configureGas.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const advancedTabButton = await driver.wait(until.elementLocated(By.xpath(`//li[contains(text(), 'Advanced')]`)), 10000) + const advancedTabButton = await driver.findElement(By.xpath(`//li[contains(text(), 'Advanced')]`)) await advancedTabButton.click() - await delay(tinyDelayMs) + await driver.delay(tinyDelayMs) - const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.advanced-gas-inputs__gas-edit-row__input')) + const [gasPriceInput, gasLimitInput] = await driver.findElements(By.css('.advanced-gas-inputs__gas-edit-row__input')) assert(gasPriceInput.getAttribute('value'), 20) assert(gasLimitInput.getAttribute('value'), 4700000) - const saveButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`)) + const saveButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) await saveButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - await driver.switchTo().window(dapp) - await delay(tinyDelayMs) + await driver.switchToWindow(dapp) + await driver.delay(tinyDelayMs) const tokenContractAddress = await driver.findElement(By.css('#tokenAddress')) await driver.wait(until.elementTextMatches(tokenContractAddress, /0x/)) tokenAddress = await tokenContractAddress.getText() - await delay(regularDelayMs) - await closeAllWindowHandlesExcept(driver, [extension, dapp]) - await delay(regularDelayMs) - await driver.switchTo().window(extension) - await delay(largeDelayMs) + await driver.delay(regularDelayMs) + await driver.closeAllWindowHandlesExcept([extension, dapp]) + await driver.delay(regularDelayMs) + await driver.switchToWindow(extension) + await driver.delay(largeDelayMs) }) it('clicks on the Add Token button', async () => { const addToken = await driver.findElement(By.xpath(`//div[contains(text(), 'Add Token')]`)) await addToken.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('picks the newly created Test token', async () => { - const addCustomToken = await findElement(driver, By.xpath("//li[contains(text(), 'Custom Token')]")) + const addCustomToken = await driver.findElement(By.xpath("//li[contains(text(), 'Custom Token')]")) await addCustomToken.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const newTokenAddress = await findElement(driver, By.css('#custom-address')) + const newTokenAddress = await driver.findElement(By.css('#custom-address')) await newTokenAddress.sendKeys(tokenAddress) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const addTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Tokens')]`)) + const addTokens = await driver.findElement(By.xpath(`//button[contains(text(), 'Add Tokens')]`)) await addTokens.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('renders the balance for the new token', async () => { - const balance = await findElement(driver, By.css('.transaction-view-balance .transaction-view-balance__primary-balance')) + const balance = await driver.findElement(By.css('.transaction-view-balance .transaction-view-balance__primary-balance')) await driver.wait(until.elementTextMatches(balance, /^10.000\s*TST\s*$/)) const tokenAmount = await balance.getText() assert.ok(/^10.000\s*TST\s*$/.test(tokenAmount)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Send token from inside MetaMask', () => { let gasModal it('starts to send a transaction', async function () { - const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`)) + const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) await sendButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const inputAddress = await findElement(driver, By.css('input[placeholder="Search, public address (0x), or ENS"]')) + const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') - const inputAmount = await findElement(driver, By.css('.unit-input__input')) + const inputAmount = await driver.findElement(By.css('.unit-input__input')) await inputAmount.sendKeys('1') // Set the gas limit - const configureGas = await findElement(driver, By.css('.advanced-gas-options-btn')) + const configureGas = await driver.findElement(By.css('.advanced-gas-options-btn')) await configureGas.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) gasModal = await driver.findElement(By.css('span .modal')) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('opens customize gas modal', async () => { - await driver.wait(until.elementLocated(By.css('.page-container__title'))) - const save = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`)) + await driver.findElement(By.css('.page-container__title')) + const save = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) await save.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('transitions to the confirm screen', async () => { await driver.wait(until.stalenessOf(gasModal)) // Continue to next screen - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) await driver.wait(until.elementIsEnabled(nextScreen)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('displays the token transfer data', async () => { - const dataTab = await findElement(driver, By.xpath(`//li[contains(text(), 'Data')]`)) - dataTab.click() - await delay(regularDelayMs) + const dataTab = await driver.findElement(By.xpath(`//li[contains(text(), 'Data')]`)) + await dataTab.click() + await driver.delay(regularDelayMs) - const functionType = await findElement(driver, By.css('.confirm-page-container-content__function-type')) + const functionType = await driver.findElement(By.css('.confirm-page-container-content__function-type')) const functionTypeText = await functionType.getText() assert.equal(functionTypeText, 'Transfer') - const tokenAmount = await findElement(driver, By.css('.confirm-page-container-summary__title-text')) + const tokenAmount = await driver.findElement(By.css('.confirm-page-container-summary__title-text')) const tokenAmountText = await tokenAmount.getText() assert.equal(tokenAmountText, '1 TST') - const confirmDataDiv = await findElement(driver, By.css('.confirm-page-container-content__data-box')) + const confirmDataDiv = await driver.findElement(By.css('.confirm-page-container-content__data-box')) const confirmDataText = await confirmDataDiv.getText() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) assert(confirmDataText.match(/0xa9059cbb0000000000000000000000002f318c334780961fb129d2a6c30d0763d9a5c97/)) - const detailsTab = await findElement(driver, By.xpath(`//li[contains(text(), 'Details')]`)) + const detailsTab = await driver.findElement(By.xpath(`//li[contains(text(), 'Details')]`)) detailsTab.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('submits the transaction', async function () { - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 1 }, 10000) - const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + const txValues = await driver.findElements(By.css('.transaction-list-item__amount--primary')) assert.equal(txValues.length, 1) await driver.wait(until.elementTextMatches(txValues[0], /-1\s*TST/), 10000) - const txStatuses = await findElements(driver, By.css('.transaction-list-item__action')) + const txStatuses = await driver.findElements(By.css('.transaction-list-item__action')) await driver.wait(until.elementTextMatches(txStatuses[0], /Sent\sToken/i), 10000) }) }) @@ -1037,95 +1028,95 @@ describe('MetaMask', function () { it('sends an already created token', async () => { const windowHandles = await driver.getAllWindowHandles() const extension = windowHandles[0] - const dapp = await switchToWindowWithTitle(driver, 'E2E Test Dapp', windowHandles) - await delay(regularDelayMs) + const dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) + await driver.delay(regularDelayMs) - await driver.switchTo().window(dapp) - await delay(tinyDelayMs) + await driver.switchToWindow(dapp) + await driver.delay(tinyDelayMs) - const transferTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Transfer Tokens')]`)) + const transferTokens = await driver.findElement(By.xpath(`//button[contains(text(), 'Transfer Tokens')]`)) await transferTokens.click() - await driver.switchTo().window(extension) - await delay(largeDelayMs) + await driver.switchToWindow(extension) + await driver.delay(largeDelayMs) - await findElements(driver, By.css('.transaction-list__pending-transactions')) - const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + await driver.findElements(By.css('.transaction-list__pending-transactions')) + const [txListValue] = await driver.findElements(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/), 10000) await txListValue.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const transactionAmounts = await findElements(driver, By.css('.currency-display-component__text')) + const transactionAmounts = await driver.findElements(By.css('.currency-display-component__text')) const transactionAmount = transactionAmounts[0] assert(await transactionAmount.getText(), '1.5 TST') // Set the gas limit - const configureGas = await driver.wait(until.elementLocated(By.css('.confirm-detail-row__header-text--edit')), 10000) + const configureGas = await driver.findElement(By.css('.confirm-detail-row__header-text--edit')) await configureGas.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) gasModal = await driver.findElement(By.css('span .modal')) }) it('customizes gas', async () => { - const modalTabs = await findElements(driver, By.css('.page-container__tab')) + const modalTabs = await driver.findElements(By.css('.page-container__tab')) await modalTabs[1].click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.advanced-gas-inputs__gas-edit-row__input')) + const [gasPriceInput, gasLimitInput] = await driver.findElements(By.css('.advanced-gas-inputs__gas-edit-row__input')) await gasPriceInput.sendKeys(Key.chord(Key.CONTROL, 'a')) - await delay(50) + await driver.delay(50) await gasPriceInput.sendKeys(Key.BACK_SPACE) - await delay(50) + await driver.delay(50) await gasPriceInput.sendKeys('10') - await delay(50) + await driver.delay(50) await gasLimitInput.sendKeys(Key.chord(Key.CONTROL, 'a')) - await delay(50) + await driver.delay(50) await gasLimitInput.sendKeys(Key.BACK_SPACE) - await delay(50) + await driver.delay(50) await gasLimitInput.sendKeys('60000') - await delay(1000) + await driver.delay(1000) - const save = await findElement(driver, By.css('.page-container__footer-button')) + const save = await driver.findElement(By.css('.page-container__footer-button')) await save.click() await driver.wait(until.stalenessOf(gasModal)) - const gasFeeInputs = await findElements(driver, By.css('.confirm-detail-row__primary')) + const gasFeeInputs = await driver.findElements(By.css('.confirm-detail-row__primary')) const renderedGasFee = await gasFeeInputs[0].getText() assert.equal(renderedGasFee, '0.0006') }) it('submits the transaction', async function () { - const tokenAmount = await findElement(driver, By.css('.confirm-page-container-summary__title-text')) + const tokenAmount = await driver.findElement(By.css('.confirm-page-container-summary__title-text')) const tokenAmountText = await tokenAmount.getText() assert.equal(tokenAmountText, '1.5 TST') - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 2 }, 10000) - const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + const txValues = await driver.findElements(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/)) - const txStatuses = await findElements(driver, By.css('.transaction-list-item__action')) + const txStatuses = await driver.findElements(By.css('.transaction-list-item__action')) await driver.wait(until.elementTextMatches(txStatuses[0], /Sent\sToken/), 10000) - const walletBalance = await findElement(driver, By.css('.wallet-balance')) + const walletBalance = await driver.findElement(By.css('.wallet-balance')) await walletBalance.click() - const tokenListItems = await findElements(driver, By.css('.token-list-item')) + const tokenListItems = await driver.findElements(By.css('.token-list-item')) await tokenListItems[0].click() - await delay(1000) + await driver.delay(1000) - const tokenBalanceAmount = await findElements(driver, By.css('.transaction-view-balance__primary-balance')) + const tokenBalanceAmount = await driver.findElements(By.css('.transaction-view-balance__primary-balance')) await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /7.500\s*TST/), 10000) }) }) @@ -1135,123 +1126,123 @@ describe('MetaMask', function () { it('approves an already created token', async () => { const windowHandles = await driver.getAllWindowHandles() const extension = windowHandles[0] - const dapp = await switchToWindowWithTitle(driver, 'E2E Test Dapp', windowHandles) - await closeAllWindowHandlesExcept(driver, [extension, dapp]) - await delay(regularDelayMs) + const dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) + await driver.closeAllWindowHandlesExcept([extension, dapp]) + await driver.delay(regularDelayMs) - await driver.switchTo().window(dapp) - await delay(tinyDelayMs) + await driver.switchToWindow(dapp) + await driver.delay(tinyDelayMs) - const approveTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Approve Tokens')]`)) + const approveTokens = await driver.findElement(By.xpath(`//button[contains(text(), 'Approve Tokens')]`)) await approveTokens.click() - await driver.switchTo().window(extension) - await delay(regularDelayMs) + await driver.switchToWindow(extension) + await driver.delay(regularDelayMs) await driver.wait(async () => { - const pendingTxes = await findElements(driver, By.css('.transaction-list__pending-transactions .transaction-list-item')) + const pendingTxes = await driver.findElements(By.css('.transaction-list__pending-transactions .transaction-list-item')) return pendingTxes.length === 1 }, 10000) - const [txListItem] = await findElements(driver, By.css('.transaction-list-item')) - const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + const [txListItem] = await driver.findElements(By.css('.transaction-list-item')) + const [txListValue] = await driver.findElements(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txListValue, /-7\s*TST/)) await txListItem.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('displays the token approval data', async () => { - const fullTxDataButton = await findElement(driver, By.css('.confirm-approve-content__view-full-tx-button')) + const fullTxDataButton = await driver.findElement(By.css('.confirm-approve-content__view-full-tx-button')) await fullTxDataButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const functionType = await findElement(driver, By.css('.confirm-approve-content__data .confirm-approve-content__small-text')) + const functionType = await driver.findElement(By.css('.confirm-approve-content__data .confirm-approve-content__small-text')) const functionTypeText = await functionType.getText() assert.equal(functionTypeText, 'Function: Approve') - const confirmDataDiv = await findElement(driver, By.css('.confirm-approve-content__data__data-block')) + const confirmDataDiv = await driver.findElement(By.css('.confirm-approve-content__data__data-block')) const confirmDataText = await confirmDataDiv.getText() assert(confirmDataText.match(/0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef4/)) }) it('opens the gas edit modal', async () => { - const editButtons = await findElements(driver, By.css('.confirm-approve-content__small-blue-text.cursor-pointer')) + const editButtons = await driver.findElements(By.css('.confirm-approve-content__small-blue-text.cursor-pointer')) await editButtons[0].click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) gasModal = await driver.findElement(By.css('span .modal')) }) it('customizes gas', async () => { - const modalTabs = await findElements(driver, By.css('.page-container__tab')) + const modalTabs = await driver.findElements(By.css('.page-container__tab')) await modalTabs[1].click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.advanced-gas-inputs__gas-edit-row__input')) + const [gasPriceInput, gasLimitInput] = await driver.findElements(By.css('.advanced-gas-inputs__gas-edit-row__input')) await gasPriceInput.sendKeys(Key.chord(Key.CONTROL, 'a')) - await delay(50) + await driver.delay(50) await gasPriceInput.sendKeys(Key.BACK_SPACE) - await delay(50) + await driver.delay(50) await gasPriceInput.sendKeys('10') - await delay(50) + await driver.delay(50) await gasLimitInput.sendKeys(Key.chord(Key.CONTROL, 'a')) - await delay(50) + await driver.delay(50) await gasLimitInput.sendKeys(Key.BACK_SPACE) - await delay(50) + await driver.delay(50) await gasLimitInput.sendKeys('60001') - await delay(1000) + await driver.delay(1000) - const save = await findElement(driver, By.css('.page-container__footer-button')) + const save = await driver.findElement(By.css('.page-container__footer-button')) await save.click() await driver.wait(until.stalenessOf(gasModal)) - const gasFeeInEth = await findElement(driver, By.css('.confirm-approve-content__transaction-details-content__secondary-fee')) + const gasFeeInEth = await driver.findElement(By.css('.confirm-approve-content__transaction-details-content__secondary-fee')) assert.equal(await gasFeeInEth.getText(), '0.0006 ETH') }) it('edits the permission', async () => { - const editButtons = await findElements(driver, By.css('.confirm-approve-content__small-blue-text.cursor-pointer')) + const editButtons = await driver.findElements(By.css('.confirm-approve-content__small-blue-text.cursor-pointer')) await editButtons[1].click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) const permissionModal = await driver.findElement(By.css('span .modal')) - const radioButtons = await findElements(driver, By.css('.edit-approval-permission__edit-section__radio-button')) + const radioButtons = await driver.findElements(By.css('.edit-approval-permission__edit-section__radio-button')) await radioButtons[1].click() - const customInput = await findElement(driver, By.css('input')) - await delay(50) + const customInput = await driver.findElement(By.css('input')) + await driver.delay(50) await customInput.sendKeys('5') - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const saveButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`)) + const saveButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) await saveButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) await driver.wait(until.stalenessOf(permissionModal)) - const permissionInfo = await findElements(driver, By.css('.confirm-approve-content__medium-text')) + const permissionInfo = await driver.findElements(By.css('.confirm-approve-content__medium-text')) const amountDiv = permissionInfo[0] assert.equal(await amountDiv.getText(), '5 TST') }) it('submits the transaction', async function () { - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 3 }, 10000) - const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + const txValues = await driver.findElements(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txValues[0], /-5\s*TST/)) - const txStatuses = await findElements(driver, By.css('.transaction-list-item__action')) + const txStatuses = await driver.findElements(By.css('.transaction-list-item__action')) await driver.wait(until.elementTextMatches(txStatuses[0], /Approve/)) }) }) @@ -1260,46 +1251,46 @@ describe('MetaMask', function () { it('transfers an already created token, without specifying gas', async () => { const windowHandles = await driver.getAllWindowHandles() const extension = windowHandles[0] - const dapp = await switchToWindowWithTitle(driver, 'E2E Test Dapp', windowHandles) - await closeAllWindowHandlesExcept(driver, [extension, dapp]) - await delay(regularDelayMs) + const dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) + await driver.closeAllWindowHandlesExcept([extension, dapp]) + await driver.delay(regularDelayMs) - await driver.switchTo().window(dapp) + await driver.switchToWindow(dapp) - const transferTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Transfer Tokens Without Gas')]`)) + const transferTokens = await driver.findElement(By.xpath(`//button[contains(text(), 'Transfer Tokens Without Gas')]`)) await transferTokens.click() - await driver.switchTo().window(extension) - await delay(regularDelayMs) + await driver.switchToWindow(extension) + await driver.delay(regularDelayMs) await driver.wait(async () => { - const pendingTxes = await findElements(driver, By.css('.transaction-list__pending-transactions .transaction-list-item')) + const pendingTxes = await driver.findElements(By.css('.transaction-list__pending-transactions .transaction-list-item')) return pendingTxes.length === 1 }, 10000) - const [txListItem] = await findElements(driver, By.css('.transaction-list-item')) - const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + const [txListItem] = await driver.findElements(By.css('.transaction-list-item')) + const [txListValue] = await driver.findElements(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/)) await txListItem.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('submits the transaction', async function () { - await delay(largeDelayMs * 2) - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + await driver.delay(largeDelayMs * 2) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(largeDelayMs * 2) + await driver.delay(largeDelayMs * 2) }) it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 4 }, 10000) - const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + const txValues = await driver.findElements(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/)) - const txStatuses = await findElements(driver, By.css('.transaction-list-item__action')) + const txStatuses = await driver.findElements(By.css('.transaction-list-item__action')) await driver.wait(until.elementTextMatches(txStatuses[0], /Sent Tokens/)) }) }) @@ -1308,75 +1299,75 @@ describe('MetaMask', function () { it('approves an already created token', async () => { const windowHandles = await driver.getAllWindowHandles() const extension = windowHandles[0] - const dapp = await switchToWindowWithTitle(driver, 'E2E Test Dapp', windowHandles) - await closeAllWindowHandlesExcept(driver, [extension, dapp]) - await delay(regularDelayMs) + const dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) + await driver.closeAllWindowHandlesExcept([extension, dapp]) + await driver.delay(regularDelayMs) - await driver.switchTo().window(dapp) - await delay(tinyDelayMs) + await driver.switchToWindow(dapp) + await driver.delay(tinyDelayMs) - const transferTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Approve Tokens Without Gas')]`)) + const transferTokens = await driver.findElement(By.xpath(`//button[contains(text(), 'Approve Tokens Without Gas')]`)) await transferTokens.click() - await driver.switchTo().window(extension) - await delay(regularDelayMs) + await driver.switchToWindow(extension) + await driver.delay(regularDelayMs) await driver.wait(async () => { - const pendingTxes = await findElements(driver, By.css('.transaction-list__pending-transactions .transaction-list-item')) + const pendingTxes = await driver.findElements(By.css('.transaction-list__pending-transactions .transaction-list-item')) return pendingTxes.length === 1 }, 10000) - const [txListItem] = await findElements(driver, By.css('.transaction-list-item')) - const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + const [txListItem] = await driver.findElements(By.css('.transaction-list-item')) + const [txListValue] = await driver.findElements(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txListValue, /-7\s*TST/)) await txListItem.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('shows the correct recipient', async function () { - const fullTxDataButton = await findElement(driver, By.css('.confirm-approve-content__view-full-tx-button')) + const fullTxDataButton = await driver.findElement(By.css('.confirm-approve-content__view-full-tx-button')) await fullTxDataButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const permissionInfo = await findElements(driver, By.css('.confirm-approve-content__medium-text')) + const permissionInfo = await driver.findElements(By.css('.confirm-approve-content__medium-text')) const recipientDiv = permissionInfo[1] assert.equal(await recipientDiv.getText(), '0x2f318C33...C970') }) it('submits the transaction', async function () { - await delay(1000) - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + await driver.delay(1000) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 5 }, 10000) - const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + const txValues = await driver.findElements(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txValues[0], /-7\s*TST/)) - const txStatuses = await findElements(driver, By.css('.transaction-list-item__action')) + const txStatuses = await driver.findElements(By.css('.transaction-list-item__action')) await driver.wait(until.elementTextMatches(txStatuses[0], /Approve/)) }) }) describe('Hide token', () => { it('hides the token when clicked', async () => { - const [hideTokenEllipsis] = await findElements(driver, By.css('.token-list-item__ellipsis')) + const [hideTokenEllipsis] = await driver.findElements(By.css('.token-list-item__ellipsis')) await hideTokenEllipsis.click() const byTokenMenuDropdownOption = By.css('.menu__item--clickable') - const tokenMenuDropdownOption = await driver.wait(until.elementLocated(byTokenMenuDropdownOption)) + const tokenMenuDropdownOption = await driver.findElement(byTokenMenuDropdownOption) await tokenMenuDropdownOption.click() - const confirmHideModal = await findElement(driver, By.css('span .modal')) + const confirmHideModal = await driver.findElement(By.css('span .modal')) const byHideTokenConfirmationButton = By.css('.hide-token-confirmation__button') - const hideTokenConfirmationButton = await driver.wait(until.elementLocated(byHideTokenConfirmationButton)) + const hideTokenConfirmationButton = await driver.findElement(byHideTokenConfirmationButton) await hideTokenConfirmationButton.click() await driver.wait(until.stalenessOf(confirmHideModal)) @@ -1385,33 +1376,33 @@ describe('MetaMask', function () { describe('Add existing token using search', () => { it('clicks on the Add Token button', async () => { - const addToken = await findElement(driver, By.xpath(`//div[contains(text(), 'Add Token')]`)) + const addToken = await driver.findElement(By.xpath(`//div[contains(text(), 'Add Token')]`)) await addToken.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('can pick a token from the existing options', async () => { - const tokenSearch = await findElement(driver, By.css('#search-tokens')) + const tokenSearch = await driver.findElement(By.css('#search-tokens')) await tokenSearch.sendKeys('BAT') - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const token = await findElement(driver, By.xpath("//span[contains(text(), 'BAT')]")) + const token = await driver.findElement(By.xpath("//span[contains(text(), 'BAT')]")) await token.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const addTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Tokens')]`)) + const addTokens = await driver.findElement(By.xpath(`//button[contains(text(), 'Add Tokens')]`)) await addTokens.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('renders the balance for the chosen token', async () => { - const balance = await findElement(driver, By.css('.transaction-view-balance__primary-balance')) + const balance = await driver.findElement(By.css('.transaction-view-balance__primary-balance')) await driver.wait(until.elementTextMatches(balance, /0\s*BAT/)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) @@ -1425,67 +1416,67 @@ describe('MetaMask', function () { customRpcUrls.forEach(customRpcUrl => { it(`creates custom RPC: ${customRpcUrl}`, async () => { - const networkDropdown = await findElement(driver, By.css('.network-name')) + const networkDropdown = await driver.findElement(By.css('.network-name')) await networkDropdown.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const customRpcButton = await findElement(driver, By.xpath(`//span[contains(text(), 'Custom RPC')]`)) + const customRpcButton = await driver.findElement(By.xpath(`//span[contains(text(), 'Custom RPC')]`)) await customRpcButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - await findElement(driver, By.css('.settings-page__sub-header-text')) + await driver.findElement(By.css('.settings-page__sub-header-text')) - const customRpcInputs = await findElements(driver, By.css('input[type="text"]')) + const customRpcInputs = await driver.findElements(By.css('input[type="text"]')) const customRpcInput = customRpcInputs[1] await customRpcInput.clear() await customRpcInput.sendKeys(customRpcUrl) - const customRpcSave = await findElement(driver, By.css('.network-form__footer .btn-secondary')) + const customRpcSave = await driver.findElement(By.css('.network-form__footer .btn-secondary')) await customRpcSave.click() - await delay(largeDelayMs * 2) + await driver.delay(largeDelayMs * 2) }) }) it('selects another provider', async () => { - const networkDropdown = await findElement(driver, By.css('.network-name')) + const networkDropdown = await driver.findElement(By.css('.network-name')) await networkDropdown.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const customRpcButton = await findElement(driver, By.xpath(`//span[contains(text(), 'Main Ethereum Network')]`)) + const customRpcButton = await driver.findElement(By.xpath(`//span[contains(text(), 'Main Ethereum Network')]`)) await customRpcButton.click() - await delay(largeDelayMs * 2) + await driver.delay(largeDelayMs * 2) }) it('finds all recent RPCs in history', async () => { - const networkDropdown = await findElement(driver, By.css('.network-name')) + const networkDropdown = await driver.findElement(By.css('.network-name')) await networkDropdown.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) // only recent 3 are found and in correct order (most recent at the top) - const customRpcs = await findElements(driver, By.xpath(`//span[contains(text(), 'http://127.0.0.1:8545/')]`)) + const customRpcs = await driver.findElements(By.xpath(`//span[contains(text(), 'http://127.0.0.1:8545/')]`)) assert.equal(customRpcs.length, customRpcUrls.length) }) it('deletes a custom RPC', async () => { - const networkListItems = await findElements(driver, By.css('.networks-tab__networks-list-name')) + const networkListItems = await driver.findElements(By.css('.networks-tab__networks-list-name')) const lastNetworkListItem = networkListItems[networkListItems.length - 1] await lastNetworkListItem.click() - await delay(100) + await driver.delay(100) - const deleteButton = await findElement(driver, By.css('.btn-danger')) + const deleteButton = await driver.findElement(By.css('.btn-danger')) await deleteButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const confirmDeleteNetworkModal = await findElement(driver, By.css('span .modal')) + const confirmDeleteNetworkModal = await driver.findElement(By.css('span .modal')) const byConfirmDeleteNetworkButton = By.css('.button.btn-danger.modal-container__footer-button') - const confirmDeleteNetworkButton = await driver.wait(until.elementLocated(byConfirmDeleteNetworkButton)) + const confirmDeleteNetworkButton = await driver.findElement(byConfirmDeleteNetworkButton) await confirmDeleteNetworkButton.click() await driver.wait(until.stalenessOf(confirmDeleteNetworkModal)) - const newNetworkListItems = await findElements(driver, By.css('.networks-tab__networks-list-name')) + const newNetworkListItems = await driver.findElements(By.css('.networks-tab__networks-list-name')) assert.equal(networkListItems.length - 1, newNetworkListItems.length) }) diff --git a/test/e2e/permissions.spec.js b/test/e2e/permissions.spec.js index 0d8ec3781..95b19709d 100644 --- a/test/e2e/permissions.spec.js +++ b/test/e2e/permissions.spec.js @@ -3,16 +3,9 @@ const webdriver = require('selenium-webdriver') const { By, until } = webdriver const { - checkBrowserForConsoleErrors, - delay, - findElement, - findElements, - openNewPage, - verboseReportOnFailure, - waitUntilXWindowHandles, - switchToWindowWithTitle, - setupFetchMocking, prepareExtensionForTesting, + regularDelayMs, + largeDelayMs, } = require('./helpers') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -23,10 +16,6 @@ describe('MetaMask', function () { let driver let publicAddress - const tinyDelayMs = 200 - const regularDelayMs = tinyDelayMs * 2 - const largeDelayMs = regularDelayMs * 2 - this.timeout(0) this.bail(true) @@ -41,12 +30,11 @@ describe('MetaMask', function () { }) const result = await prepareExtensionForTesting() driver = result.driver - await setupFetchMocking(driver) }) afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { const errorReports = errors.map(err => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` @@ -54,7 +42,7 @@ describe('MetaMask', function () { } } if (this.currentTest.state === 'failed') { - await verboseReportOnFailure(driver, this.currentTest) + await driver.verboseReportOnFailure(driver, this.currentTest) } }) @@ -65,51 +53,51 @@ describe('MetaMask', function () { describe('Going through the first time flow, but skipping the seed phrase challenge', () => { it('clicks the continue button on the welcome screen', async () => { - await findElement(driver, By.css('.welcome-page__header')) - const welcomeScreenBtn = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) + await driver.findElement(By.css('.welcome-page__header')) + const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) welcomeScreenBtn.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { - const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) + const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) customRpcButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await findElement(driver, By.css('.btn-default')) + const optOutButton = await driver.findElement(By.css('.btn-default')) optOutButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('accepts a secure password', async () => { - const passwordBox = await findElement(driver, By.css('.first-time-flow__form #create-password')) - const passwordBoxConfirm = await findElement(driver, By.css('.first-time-flow__form #confirm-password')) - const button = await findElement(driver, By.css('.first-time-flow__form button')) + const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) + const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) + const button = await driver.findElement(By.css('.first-time-flow__form button')) await passwordBox.sendKeys('correct horse battery staple') await passwordBoxConfirm.sendKeys('correct horse battery staple') - const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox')) + const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) await tosCheckBox.click() await button.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('skips the seed phrase challenge', async () => { - const button = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) + const button = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) await button.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const detailsButton = await findElement(driver, By.css('.account-details__details-button')) + const detailsButton = await driver.findElement(By.css('.account-details__details-button')) await detailsButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('gets the current accounts address', async () => { - const addressInput = await findElement(driver, By.css('.qr-ellip-address')) + const addressInput = await driver.findElement(By.css('.qr-ellip-address')) publicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) @@ -117,7 +105,7 @@ describe('MetaMask', function () { await accountModalClose.click() await driver.wait(until.stalenessOf(accountModal)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) @@ -127,86 +115,86 @@ describe('MetaMask', function () { let dapp it('connects to the dapp', async () => { - await openNewPage(driver, 'http://127.0.0.1:8080/') - await delay(regularDelayMs) + await driver.openNewPage('http://127.0.0.1:8080/') + await driver.delay(regularDelayMs) - const connectButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Connect')]`)) + const connectButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Connect')]`)) await connectButton.click() - await waitUntilXWindowHandles(driver, 3) + await driver.waitUntilXWindowHandles(3) const windowHandles = await driver.getAllWindowHandles() extension = windowHandles[0] - dapp = await switchToWindowWithTitle(driver, 'E2E Test Dapp', windowHandles) + dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) popup = windowHandles.find(handle => handle !== extension && handle !== dapp) - await driver.switchTo().window(popup) + await driver.switchToWindow(popup) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const accountButton = await findElement(driver, By.css('.permissions-connect-choose-account__account')) + const accountButton = await driver.findElement(By.css('.permissions-connect-choose-account__account')) await accountButton.click() - const submitButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Submit')]`)) + const submitButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Submit')]`)) await submitButton.click() - await waitUntilXWindowHandles(driver, 2) - await driver.switchTo().window(extension) - await delay(regularDelayMs) + await driver.waitUntilXWindowHandles(2) + await driver.switchToWindow(extension) + await driver.delay(regularDelayMs) }) it('shows connected sites', async () => { - const connectedSites = await findElement(driver, By.xpath(`//button[contains(text(), 'Connected Sites')]`)) + const connectedSites = await driver.findElement(By.xpath(`//button[contains(text(), 'Connected Sites')]`)) await connectedSites.click() - await findElement(driver, By.css('.connected-sites__title')) + await driver.findElement(By.css('.connected-sites__title')) - const domains = await findElements(driver, By.css('.connected-sites-list__domain')) + const domains = await driver.findElements(By.css('.connected-sites-list__domain')) assert.equal(domains.length, 1) - const domainName = await findElement(driver, By.css('.connected-sites-list__domain-name')) + const domainName = await driver.findElement(By.css('.connected-sites-list__domain-name')) assert.equal(await domainName.getText(), 'E2E Test Dapp') await domains[0].click() - const permissionDescription = await findElement(driver, By.css('.connected-sites-list__permission-description')) + const permissionDescription = await driver.findElement(By.css('.connected-sites-list__permission-description')) assert.equal(await permissionDescription.getText(), 'View the address of the selected account') }) it('can get accounts within the dapp', async () => { - await driver.switchTo().window(dapp) - await delay(regularDelayMs) + await driver.switchToWindow(dapp) + await driver.delay(regularDelayMs) - const getAccountsButton = await findElement(driver, By.xpath(`//button[contains(text(), 'eth_accounts')]`)) + const getAccountsButton = await driver.findElement(By.xpath(`//button[contains(text(), 'eth_accounts')]`)) await getAccountsButton.click() - const getAccountsResult = await findElement(driver, By.css('#getAccountsResult')) + const getAccountsResult = await driver.findElement(By.css('#getAccountsResult')) assert.equal((await getAccountsResult.getText()).toLowerCase(), publicAddress.toLowerCase()) }) it('can disconnect all accounts', async () => { - await driver.switchTo().window(extension) + await driver.switchToWindow(extension) - const disconnectAllButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Disconnect All')]`)) + const disconnectAllButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Disconnect All')]`)) await disconnectAllButton.click() const disconnectModal = await driver.findElement(By.css('span .modal')) - const disconnectAllModalButton = await findElement(driver, By.css('.disconnect-all-modal .btn-danger')) + const disconnectAllModalButton = await driver.findElement(By.css('.disconnect-all-modal .btn-danger')) await disconnectAllModalButton.click() await driver.wait(until.stalenessOf(disconnectModal)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('can no longer get accounts within the dapp', async () => { - await driver.switchTo().window(dapp) - await delay(regularDelayMs) + await driver.switchToWindow(dapp) + await driver.delay(regularDelayMs) - const getAccountsButton = await findElement(driver, By.xpath(`//button[contains(text(), 'eth_accounts')]`)) + const getAccountsButton = await driver.findElement(By.xpath(`//button[contains(text(), 'eth_accounts')]`)) await getAccountsButton.click() - const getAccountsResult = await findElement(driver, By.css('#getAccountsResult')) + const getAccountsResult = await driver.findElement(By.css('#getAccountsResult')) assert.equal(await getAccountsResult.getText(), 'Not able to get accounts') }) }) diff --git a/test/e2e/send-edit.spec.js b/test/e2e/send-edit.spec.js index 21cfbd0b2..df0d03acf 100644 --- a/test/e2e/send-edit.spec.js +++ b/test/e2e/send-edit.spec.js @@ -3,13 +3,10 @@ const webdriver = require('selenium-webdriver') const { By, Key, until } = webdriver const { - checkBrowserForConsoleErrors, - delay, - verboseReportOnFailure, - findElement, - findElements, - setupFetchMocking, prepareExtensionForTesting, + tinyDelayMs, + regularDelayMs, + largeDelayMs, } = require('./helpers') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -20,9 +17,6 @@ describe('Using MetaMask with an existing account', function () { let driver const testSeedPhrase = 'forum vessel pink push lonely enact gentle tail admit parrot grunt dress' - const tinyDelayMs = 200 - const regularDelayMs = 1000 - const largeDelayMs = regularDelayMs * 2 this.timeout(0) this.bail(true) @@ -38,12 +32,11 @@ describe('Using MetaMask with an existing account', function () { }) const result = await prepareExtensionForTesting() driver = result.driver - await setupFetchMocking(driver) }) afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { const errorReports = errors.map(err => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` @@ -51,7 +44,7 @@ describe('Using MetaMask with an existing account', function () { } } if (this.currentTest.state === 'failed') { - await verboseReportOnFailure(driver, this.currentTest) + await driver.verboseReportOnFailure(driver, this.currentTest) } }) @@ -62,102 +55,102 @@ describe('Using MetaMask with an existing account', function () { describe('First time flow starting from an existing seed phrase', () => { it('clicks the continue button on the welcome screen', async () => { - await findElement(driver, By.css('.welcome-page__header')) - const welcomeScreenBtn = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) + await driver.findElement(By.css('.welcome-page__header')) + const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) welcomeScreenBtn.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "Import Wallet" option', async () => { - const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Import Wallet')]`)) + const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) customRpcButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await findElement(driver, By.css('.btn-default')) + const optOutButton = await driver.findElement(By.css('.btn-default')) optOutButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('imports a seed phrase', async () => { - const [seedTextArea] = await findElements(driver, By.css('textarea.first-time-flow__textarea')) + const [seedTextArea] = await driver.findElements(By.css('textarea.first-time-flow__textarea')) await seedTextArea.sendKeys(testSeedPhrase) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const [password] = await findElements(driver, By.id('password')) + const [password] = await driver.findElements(By.id('password')) await password.sendKeys('correct horse battery staple') - const [confirmPassword] = await findElements(driver, By.id('confirm-password')) + const [confirmPassword] = await driver.findElements(By.id('confirm-password')) confirmPassword.sendKeys('correct horse battery staple') - const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox')) + const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) await tosCheckBox.click() - const [importButton] = await findElements(driver, By.xpath(`//button[contains(text(), 'Import')]`)) + const [importButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Import')]`)) await importButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('clicks through the success screen', async () => { - await findElement(driver, By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) + await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) + const doneButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await doneButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('Send ETH from inside MetaMask', () => { it('starts a send transaction', async function () { - const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`)) + const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) await sendButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const inputAddress = await findElement(driver, By.css('input[placeholder="Search, public address (0x), or ENS"]')) + const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') - const inputAmount = await findElement(driver, By.css('.unit-input__input')) + const inputAmount = await driver.findElement(By.css('.unit-input__input')) await inputAmount.sendKeys('1') // Set the gas limit - const configureGas = await findElement(driver, By.css('.advanced-gas-options-btn')) + const configureGas = await driver.findElement(By.css('.advanced-gas-options-btn')) await configureGas.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) const gasModal = await driver.findElement(By.css('span .modal')) - const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.advanced-gas-inputs__gas-edit-row__input')) + const [gasPriceInput, gasLimitInput] = await driver.findElements(By.css('.advanced-gas-inputs__gas-edit-row__input')) await gasPriceInput.sendKeys(Key.chord(Key.CONTROL, 'a')) - await delay(50) + await driver.delay(50) await gasPriceInput.sendKeys(Key.BACK_SPACE) - await delay(50) + await driver.delay(50) await gasPriceInput.sendKeys(Key.BACK_SPACE) - await delay(50) + await driver.delay(50) await gasPriceInput.sendKeys('10') - await delay(50) - await delay(tinyDelayMs) - await delay(50) + await driver.delay(50) + await driver.delay(tinyDelayMs) + await driver.delay(50) await gasLimitInput.sendKeys(Key.chord(Key.CONTROL, 'a')) - await delay(50) + await driver.delay(50) await gasLimitInput.sendKeys('25000') - await delay(1000) + await driver.delay(1000) - const save = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`)) + const save = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) await save.click() await driver.wait(until.stalenessOf(gasModal)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) // Continue to next screen - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('has correct value and fee on the confirm screen the transaction', async function () { - const transactionAmounts = await findElements(driver, By.css('.currency-display-component__text')) + const transactionAmounts = await driver.findElements(By.css('.currency-display-component__text')) const transactionAmount = transactionAmounts[0] assert.equal(await transactionAmount.getText(), '1') @@ -166,55 +159,55 @@ describe('Using MetaMask with an existing account', function () { }) it('edits the transaction', async function () { - const editButton = await findElement(driver, By.css('.confirm-page-container-header__back-button')) + const editButton = await driver.findElement(By.css('.confirm-page-container-header__back-button')) await editButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const inputAmount = await findElement(driver, By.css('.unit-input__input')) + const inputAmount = await driver.findElement(By.css('.unit-input__input')) await inputAmount.sendKeys(Key.chord(Key.CONTROL, 'a')) - await delay(50) + await driver.delay(50) await inputAmount.sendKeys(Key.BACK_SPACE) - await delay(50) + await driver.delay(50) await inputAmount.sendKeys('2.2') - const configureGas = await findElement(driver, By.css('.advanced-gas-options-btn')) + const configureGas = await driver.findElement(By.css('.advanced-gas-options-btn')) await configureGas.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) const gasModal = await driver.findElement(By.css('span .modal')) - const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.advanced-gas-inputs__gas-edit-row__input')) + const [gasPriceInput, gasLimitInput] = await driver.findElements(By.css('.advanced-gas-inputs__gas-edit-row__input')) await gasPriceInput.sendKeys(Key.chord(Key.CONTROL, 'a')) - await delay(50) + await driver.delay(50) await gasPriceInput.sendKeys(Key.BACK_SPACE) - await delay(50) + await driver.delay(50) await gasPriceInput.sendKeys(Key.BACK_SPACE) - await delay(50) + await driver.delay(50) await gasPriceInput.sendKeys('8') - await delay(50) - await delay(tinyDelayMs) - await delay(50) + await driver.delay(50) + await driver.delay(tinyDelayMs) + await driver.delay(50) await gasLimitInput.sendKeys(Key.chord(Key.CONTROL, 'a')) - await delay(50) + await driver.delay(50) await gasLimitInput.sendKeys('100000') - await delay(1000) + await driver.delay(1000) - const save = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`)) + const save = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) await save.click() await driver.wait(until.stalenessOf(gasModal)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('has correct updated value on the confirm screen the transaction', async function () { - const transactionAmounts = await findElements(driver, By.css('.currency-display-component__text')) + const transactionAmounts = await driver.findElements(By.css('.currency-display-component__text')) const transactionAmount = transactionAmounts[0] assert.equal(await transactionAmount.getText(), '2.2') @@ -223,18 +216,18 @@ describe('Using MetaMask with an existing account', function () { }) it('confirms the transaction', async function () { - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { - const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 1 }, 10000) - const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + const txValues = await driver.findElements(By.css('.transaction-list-item__amount--primary')) assert.equal(txValues.length, 1) assert.ok(/-2.2\s*ETH/.test(await txValues[0].getText())) }) diff --git a/test/e2e/signature-request.spec.js b/test/e2e/signature-request.spec.js index a71f1c003..7a05f6bec 100644 --- a/test/e2e/signature-request.spec.js +++ b/test/e2e/signature-request.spec.js @@ -4,16 +4,9 @@ const webdriver = require('selenium-webdriver') const { By, Key, until } = webdriver const { - checkBrowserForConsoleErrors, - delay, - findElement, - findElements, - openNewPage, - verboseReportOnFailure, - waitUntilXWindowHandles, - switchToWindowWithTitle, - setupFetchMocking, prepareExtensionForTesting, + regularDelayMs, + largeDelayMs, } = require('./helpers') const Ganache = require('./ganache') const FixtureServer = require('./fixture-server') @@ -26,10 +19,6 @@ describe('MetaMask', function () { let driver let publicAddress - const tinyDelayMs = 200 - const regularDelayMs = tinyDelayMs * 2 - const largeDelayMs = regularDelayMs * 2 - this.timeout(0) this.bail(true) @@ -40,12 +29,11 @@ describe('MetaMask', function () { publicAddress = '0x5cfe73b6021e818b776b421b1c4db2474086a7e1' const result = await prepareExtensionForTesting() driver = result.driver - await setupFetchMocking(driver) }) afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { const errorReports = errors.map(err => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` @@ -53,7 +41,7 @@ describe('MetaMask', function () { } } if (this.currentTest.state === 'failed') { - await verboseReportOnFailure(driver, this.currentTest) + await driver.verboseReportOnFailure(driver, this.currentTest) } }) @@ -70,55 +58,56 @@ describe('MetaMask', function () { let windowHandles it('accepts the account password after lock', async () => { - await delay(1000) - await driver.findElement(By.id('password')).sendKeys('correct horse battery staple') - await driver.findElement(By.id('password')).sendKeys(Key.ENTER) - await delay(largeDelayMs * 4) + await driver.delay(1000) + const passwordField = await driver.findElement(By.id('password')) + await passwordField.sendKeys('correct horse battery staple') + await passwordField.sendKeys(Key.ENTER) + await driver.delay(largeDelayMs * 4) }) it('connects to the dapp', async () => { - await openNewPage(driver, 'http://127.0.0.1:8080/') - await delay(regularDelayMs) + await driver.openNewPage('http://127.0.0.1:8080/') + await driver.delay(regularDelayMs) - const connectButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Connect')]`)) + const connectButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Connect')]`)) await connectButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - await waitUntilXWindowHandles(driver, 3) + await driver.waitUntilXWindowHandles(3) const windowHandles = await driver.getAllWindowHandles() extension = windowHandles[0] - dapp = await switchToWindowWithTitle(driver, 'E2E Test Dapp', windowHandles) + dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) popup = windowHandles.find(handle => handle !== extension && handle !== dapp) - await driver.switchTo().window(popup) + await driver.switchToWindow(popup) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const accountButton = await findElement(driver, By.css('.permissions-connect-choose-account__account')) + const accountButton = await driver.findElement(By.css('.permissions-connect-choose-account__account')) await accountButton.click() - const submitButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Submit')]`)) + const submitButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Submit')]`)) await submitButton.click() - await waitUntilXWindowHandles(driver, 2) - await driver.switchTo().window(dapp) + await driver.waitUntilXWindowHandles(2) + await driver.switchToWindow(dapp) }) it('creates a sign typed data signature request', async () => { - const signTypedMessage = await findElement(driver, By.xpath(`//button[contains(text(), 'Sign')]`), 10000) + const signTypedMessage = await driver.findElement(By.xpath(`//button[contains(text(), 'Sign')]`), 10000) await signTypedMessage.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) windowHandles = await driver.getAllWindowHandles() - await switchToWindowWithTitle(driver, 'MetaMask Notification', windowHandles) - await delay(regularDelayMs) + await driver.switchToWindowWithTitle('MetaMask Notification', windowHandles) + await driver.delay(regularDelayMs) - const title = await findElement(driver, By.css('.signature-request-content__title')) - const name = await findElement(driver, By.css('.signature-request-content__info--bolded')) - const content = await findElements(driver, By.css('.signature-request-content__info')) + const title = await driver.findElement(By.css('.signature-request-content__title')) + const name = await driver.findElement(By.css('.signature-request-content__info--bolded')) + const content = await driver.findElements(By.css('.signature-request-content__info')) const origin = content[0] const address = content[1] assert.equal(await title.getText(), 'Signature Request') @@ -128,20 +117,20 @@ describe('MetaMask', function () { }) it('signs the transaction', async () => { - const signButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Sign')]`), 10000) + const signButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Sign')]`), 10000) await signButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) extension = windowHandles[0] - await driver.switchTo().window(extension) + await driver.switchToWindow(extension) }) it('gets the current accounts address', async () => { - const detailsButton = await findElement(driver, By.css('.account-details__details-button')) + const detailsButton = await driver.findElement(By.css('.account-details__details-button')) await detailsButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const addressInput = await findElement(driver, By.css('.qr-ellip-address')) + const addressInput = await driver.findElement(By.css('.qr-ellip-address')) const newPublicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) @@ -149,7 +138,7 @@ describe('MetaMask', function () { await accountModalClose.click() await driver.wait(until.stalenessOf(accountModal)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) assert.equal(newPublicAddress.toLowerCase(), publicAddress) }) }) diff --git a/test/e2e/threebox.spec.js b/test/e2e/threebox.spec.js index bbe36b983..a6194e013 100644 --- a/test/e2e/threebox.spec.js +++ b/test/e2e/threebox.spec.js @@ -4,13 +4,10 @@ const getPort = require('get-port') const { By, until } = webdriver const { - checkBrowserForConsoleErrors, - delay, - findElement, - findElements, - verboseReportOnFailure, - setupFetchMocking, prepareExtensionForTesting, + tinyDelayMs, + regularDelayMs, + largeDelayMs, } = require('./helpers') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -21,9 +18,6 @@ describe('MetaMask', function () { let driver const testSeedPhrase = 'forum vessel pink push lonely enact gentle tail admit parrot grunt dress' - const tinyDelayMs = 200 - const regularDelayMs = tinyDelayMs * 2 - const largeDelayMs = regularDelayMs * 2 this.timeout(0) this.bail(true) @@ -39,12 +33,11 @@ describe('MetaMask', function () { }) const result = await prepareExtensionForTesting({ port: await getPort() }) driver = result.driver - await setupFetchMocking(driver) }) afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { const errorReports = errors.map(err => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` @@ -52,7 +45,7 @@ describe('MetaMask', function () { } } if (this.currentTest.state === 'failed') { - await verboseReportOnFailure(driver, this.currentTest) + await driver.verboseReportOnFailure(driver, this.currentTest) } }) @@ -65,70 +58,71 @@ describe('MetaMask', function () { describe('First time flow starting from an existing seed phrase', () => { it('clicks the continue button on the welcome screen', async () => { - await findElement(driver, By.css('.welcome-page__header')) - const welcomeScreenBtn = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) + await driver.findElement(By.css('.welcome-page__header')) + const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) welcomeScreenBtn.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "Import Wallet" option', async () => { - const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Import Wallet')]`)) + const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) customRpcButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await findElement(driver, By.css('.btn-default')) + const optOutButton = await driver.findElement(By.css('.btn-default')) optOutButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('imports a seed phrase', async () => { - const [seedTextArea] = await findElements(driver, By.css('textarea.first-time-flow__textarea')) + const [seedTextArea] = await driver.findElements(By.css('textarea.first-time-flow__textarea')) await seedTextArea.sendKeys(testSeedPhrase) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const [password] = await findElements(driver, By.id('password')) + const [password] = await driver.findElements(By.id('password')) await password.sendKeys('correct horse battery staple') - const [confirmPassword] = await findElements(driver, By.id('confirm-password')) + const [confirmPassword] = await driver.findElements(By.id('confirm-password')) confirmPassword.sendKeys('correct horse battery staple') - const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox')) + const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) await tosCheckBox.click() - const [importButton] = await findElements(driver, By.xpath(`//button[contains(text(), 'Import')]`)) + const [importButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Import')]`)) await importButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('clicks through the success screen', async () => { - await findElement(driver, By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) + await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) + const doneButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await doneButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('balance renders', async () => { - const balance = await findElement(driver, By.css('.balance-display .token-amount')) + const balance = await driver.findElement(By.css('.balance-display .token-amount')) await driver.wait(until.elementTextMatches(balance, /25\s*ETH/)) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) describe('turns on threebox syncing', () => { it('goes to the settings screen', async () => { - await driver.findElement(By.css('.account-menu__icon')).click() - await delay(regularDelayMs) + const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) + await accountMenuButton.click() + await driver.delay(regularDelayMs) - const settingsButton = await findElement(driver, By.xpath(`//div[contains(text(), 'Settings')]`)) + const settingsButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Settings')]`)) settingsButton.click() }) it('turns on threebox syncing', async () => { - const advancedButton = await findElement(driver, By.xpath(`//div[contains(text(), 'Advanced')]`)) + const advancedButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Advanced')]`)) await advancedButton.click() - const threeBoxToggle = await findElements(driver, By.css('.toggle-button')) + const threeBoxToggle = await driver.findElements(By.css('.toggle-button')) const threeBoxToggleButton = await threeBoxToggle[4].findElement(By.css('div')) await threeBoxToggleButton.click() }) @@ -137,37 +131,37 @@ describe('MetaMask', function () { describe('updates settings and address book', () => { it('adds an address to the contact list', async () => { - const generalButton = await findElement(driver, By.xpath(`//div[contains(text(), 'General')]`)) + const generalButton = await driver.findElement(By.xpath(`//div[contains(text(), 'General')]`)) await generalButton.click() }) it('turns on use of blockies', async () => { - const toggleButton = await findElement(driver, By.css('.toggle-button > div')) + const toggleButton = await driver.findElement(By.css('.toggle-button > div')) await toggleButton.click() }) it('adds an address to the contact list', async () => { - const contactsButton = await findElement(driver, By.xpath(`//div[contains(text(), 'Contacts')]`)) + const contactsButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Contacts')]`)) await contactsButton.click() - const addressBookAddButton = await findElement(driver, By.css('.address-book-add-button__button')) + const addressBookAddButton = await driver.findElement(By.css('.address-book-add-button__button')) await addressBookAddButton.click() - await delay(tinyDelayMs) + await driver.delay(tinyDelayMs) - const addAddressInputs = await findElements(driver, By.css('input')) + const addAddressInputs = await driver.findElements(By.css('input')) await addAddressInputs[0].sendKeys('Test User Name 11') - await delay(tinyDelayMs) + await driver.delay(tinyDelayMs) await addAddressInputs[1].sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') - await delay(largeDelayMs * 2) + await driver.delay(largeDelayMs * 2) - const saveButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`)) + const saveButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) await saveButton.click() - await findElement(driver, By.xpath(`//div[contains(text(), 'Test User Name 11')]`)) - await delay(regularDelayMs) + await driver.findElement(By.xpath(`//div[contains(text(), 'Test User Name 11')]`)) + await driver.delay(regularDelayMs) }) }) @@ -179,7 +173,6 @@ describe('MetaMask', function () { before(async function () { const result = await prepareExtensionForTesting({ port: await getPort() }) driver2 = result.driver - await setupFetchMocking(driver2) }) after(async function () { @@ -188,84 +181,86 @@ describe('MetaMask', function () { describe('First time flow starting from an existing seed phrase', () => { it('clicks the continue button on the welcome screen', async () => { - await findElement(driver2, By.css('.welcome-page__header')) - const welcomeScreenBtn = await findElement(driver2, By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) + await driver2.findElement(By.css('.welcome-page__header')) + const welcomeScreenBtn = await driver2.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) welcomeScreenBtn.click() - await delay(largeDelayMs) + await driver2.delay(largeDelayMs) }) it('clicks the "Import Wallet" option', async () => { - const customRpcButton = await findElement(driver2, By.xpath(`//button[contains(text(), 'Import Wallet')]`)) + const customRpcButton = await driver2.findElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) customRpcButton.click() - await delay(largeDelayMs) + await driver2.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await findElement(driver2, By.css('.btn-default')) + const optOutButton = await driver2.findElement(By.css('.btn-default')) optOutButton.click() - await delay(largeDelayMs) + await driver2.delay(largeDelayMs) }) it('imports a seed phrase', async () => { - const [seedTextArea] = await findElements(driver2, By.css('textarea.first-time-flow__textarea')) + const [seedTextArea] = await driver2.findElements(By.css('textarea.first-time-flow__textarea')) await seedTextArea.sendKeys(testSeedPhrase) - await delay(regularDelayMs) + await driver2.delay(regularDelayMs) - const [password] = await findElements(driver2, By.id('password')) + const [password] = await driver2.findElements(By.id('password')) await password.sendKeys('correct horse battery staple') - const [confirmPassword] = await findElements(driver2, By.id('confirm-password')) + const [confirmPassword] = await driver2.findElements(By.id('confirm-password')) confirmPassword.sendKeys('correct horse battery staple') - const tosCheckBox = await findElement(driver2, By.css('.first-time-flow__checkbox')) + const tosCheckBox = await driver2.findElement(By.css('.first-time-flow__checkbox')) await tosCheckBox.click() - const [importButton] = await findElements(driver2, By.xpath(`//button[contains(text(), 'Import')]`)) + const [importButton] = await driver2.findElements(By.xpath(`//button[contains(text(), 'Import')]`)) await importButton.click() - await delay(regularDelayMs) + await driver2.delay(regularDelayMs) }) it('clicks through the success screen', async () => { - await findElement(driver2, By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await findElement(driver2, By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) + await driver2.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) + const doneButton = await driver2.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await doneButton.click() - await delay(regularDelayMs) + await driver2.delay(regularDelayMs) }) it('balance renders', async () => { - const balance = await findElement(driver2, By.css('.balance-display .token-amount')) + const balance = await driver2.findElement(By.css('.balance-display .token-amount')) await driver2.wait(until.elementTextMatches(balance, /25\s*ETH/)) - await delay(regularDelayMs) + await driver2.delay(regularDelayMs) }) }) describe('restores 3box data', () => { it('confirms the 3box restore notification', async () => { - const restoreButton = await findElement(driver2, By.css('.home-notification__accept-button')) + const restoreButton = await driver2.findElement(By.css('.home-notification__accept-button')) await restoreButton.click() }) + // TODO: Fix tests from here forward; they're using the wrong driver it('goes to the settings screen', async () => { - await driver.findElement(By.css('.account-menu__icon')).click() - await delay(regularDelayMs) + const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) + await accountMenuButton.click() + await driver.delay(regularDelayMs) - const settingsButton = await findElement(driver, By.xpath(`//div[contains(text(), 'Settings')]`)) + const settingsButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Settings')]`)) settingsButton.click() }) it('finds the blockies toggle turned on', async () => { - await delay(regularDelayMs) - const toggleLabel = await findElement(driver, By.css('.toggle-button__status-label')) + await driver.delay(regularDelayMs) + const toggleLabel = await driver.findElement(By.css('.toggle-button__status-label')) const toggleLabelText = await toggleLabel.getText() assert.equal(toggleLabelText, 'ON') }) it('finds the restored address in the contact list', async () => { - const contactsButton = await findElement(driver, By.xpath(`//div[contains(text(), 'Contacts')]`)) + const contactsButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Contacts')]`)) await contactsButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - await findElement(driver, By.xpath(`//div[contains(text(), 'Test User Name 11')]`)) - await delay(regularDelayMs) + await driver.findElement(By.xpath(`//div[contains(text(), 'Test User Name 11')]`)) + await driver.delay(regularDelayMs) }) }) }) diff --git a/test/e2e/web3.spec.js b/test/e2e/web3.spec.js index c0f56d412..6fb6027d4 100644 --- a/test/e2e/web3.spec.js +++ b/test/e2e/web3.spec.js @@ -3,16 +3,9 @@ const webdriver = require('selenium-webdriver') const { By } = webdriver const { - checkBrowserForConsoleErrors, - delay, - findElement, - findElements, - openNewPage, - switchToWindowWithTitle, - verboseReportOnFailure, - waitUntilXWindowHandles, - setupFetchMocking, prepareExtensionForTesting, + regularDelayMs, + largeDelayMs, } = require('./helpers') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -20,14 +13,12 @@ describe('Using MetaMask with an existing account', function () { let driver const testSeedPhrase = 'forum vessel pink push lonely enact gentle tail admit parrot grunt dress' - const regularDelayMs = 1000 - const largeDelayMs = regularDelayMs * 2 const button = async (x) => { const buttoncheck = x await buttoncheck.click() - await delay(largeDelayMs) - const [results] = await findElements(driver, By.css('#results')) + await driver.delay(largeDelayMs) + const [results] = await driver.findElements(By.css('#results')) const resulttext = await results.getText() const parsedData = JSON.parse(resulttext) @@ -41,12 +32,11 @@ describe('Using MetaMask with an existing account', function () { before(async function () { const result = await prepareExtensionForTesting() driver = result.driver - await setupFetchMocking(driver) }) afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { const errorReports = errors.map(err => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` @@ -54,7 +44,7 @@ describe('Using MetaMask with an existing account', function () { } } if (this.currentTest.state === 'failed') { - await verboseReportOnFailure(driver, this.currentTest) + await driver.verboseReportOnFailure(driver, this.currentTest) } }) @@ -64,47 +54,47 @@ describe('Using MetaMask with an existing account', function () { describe('First time flow starting from an existing seed phrase', () => { it('clicks the continue button on the welcome screen', async () => { - await findElement(driver, By.css('.welcome-page__header')) - const welcomeScreenBtn = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) + await driver.findElement(By.css('.welcome-page__header')) + const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) welcomeScreenBtn.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "Import Wallet" option', async () => { - const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Import Wallet')]`)) + const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) customRpcButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await findElement(driver, By.css('.btn-default')) + const optOutButton = await driver.findElement(By.css('.btn-default')) optOutButton.click() - await delay(largeDelayMs) + await driver.delay(largeDelayMs) }) it('imports a seed phrase', async () => { - const [seedTextArea] = await findElements(driver, By.css('textarea.first-time-flow__textarea')) + const [seedTextArea] = await driver.findElements(By.css('textarea.first-time-flow__textarea')) await seedTextArea.sendKeys(testSeedPhrase) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const [password] = await findElements(driver, By.id('password')) + const [password] = await driver.findElements(By.id('password')) await password.sendKeys('correct horse battery staple') - const [confirmPassword] = await findElements(driver, By.id('confirm-password')) + const [confirmPassword] = await driver.findElements(By.id('confirm-password')) confirmPassword.sendKeys('correct horse battery staple') - const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox')) + const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) await tosCheckBox.click() - const [importButton] = await findElements(driver, By.xpath(`//button[contains(text(), 'Import')]`)) + const [importButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Import')]`)) await importButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) it('clicks through the success screen', async () => { - await findElement(driver, By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await findElement(driver, By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) + await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) + const doneButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await doneButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) }) }) @@ -112,37 +102,37 @@ describe('Using MetaMask with an existing account', function () { describe('opens dapp', () => { it('switches to mainnet', async () => { - const networkDropdown = await findElement(driver, By.css('.network-name')) + const networkDropdown = await driver.findElement(By.css('.network-name')) await networkDropdown.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - const [mainnet] = await findElements(driver, By.xpath(`//span[contains(text(), 'Main Ethereum Network')]`)) + const [mainnet] = await driver.findElements(By.xpath(`//span[contains(text(), 'Main Ethereum Network')]`)) await mainnet.click() - await delay(largeDelayMs * 2) + await driver.delay(largeDelayMs * 2) }) it('connects to dapp', async () => { - await openNewPage(driver, 'http://127.0.0.1:8080/') - await delay(regularDelayMs) + await driver.openNewPage('http://127.0.0.1:8080/') + await driver.delay(regularDelayMs) - const connectButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Connect')]`)) + const connectButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Connect')]`)) await connectButton.click() - await delay(regularDelayMs) + await driver.delay(regularDelayMs) - await waitUntilXWindowHandles(driver, 3) + await driver.waitUntilXWindowHandles(3) const windowHandles = await driver.getAllWindowHandles() const extension = windowHandles[0] - const popup = await switchToWindowWithTitle(driver, 'MetaMask Notification', windowHandles) + const popup = await driver.switchToWindowWithTitle('MetaMask Notification', windowHandles) const dapp = windowHandles.find(handle => handle !== extension && handle !== popup) - await delay(regularDelayMs) - const approveButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Connect')]`)) + await driver.delay(regularDelayMs) + const approveButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Connect')]`)) await approveButton.click() - await driver.switchTo().window(dapp) - await delay(regularDelayMs) + await driver.switchToWindow(dapp) + await driver.delay(regularDelayMs) }) }) @@ -162,7 +152,7 @@ describe('Using MetaMask with an existing account', function () { const result = parseInt(parsedData.result, 16) assert.equal((typeof result === 'number'), true) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) } catch (err) { console.log(err) assert(false) @@ -183,7 +173,7 @@ describe('Using MetaMask with an existing account', function () { const result = parsedData.result assert.equal(result, false) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) } catch (err) { console.log(err) assert(false) @@ -251,7 +241,7 @@ describe('Using MetaMask with an existing account', function () { const result = parseInt(parsedData.result.parentHash, 16) assert.equal((typeof result === 'number'), true) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) } catch (err) { console.log(err) @@ -279,7 +269,7 @@ describe('Using MetaMask with an existing account', function () { result = parseInt(parsedData.result.blockHash, 16) assert.equal((typeof result === 'number' || (result === 0)), true) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) } else { parsedData = await button(List[i]) console.log(parsedData.result) @@ -287,7 +277,7 @@ describe('Using MetaMask with an existing account', function () { result = parseInt(parsedData.result, 16) assert.equal((typeof result === 'number' || (result === 0)), true) - await delay(regularDelayMs) + await driver.delay(regularDelayMs) } diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js new file mode 100644 index 000000000..d03bccc03 --- /dev/null +++ b/test/e2e/webdriver/driver.js @@ -0,0 +1,153 @@ +const { promises: fs } = require('fs') +const { until, error: webdriverError } = require('selenium-webdriver') +const { strict: assert } = require('assert') + +class Driver { + /** + * @param {!ThenableWebDriver} driver - A {@code WebDriver} instance + * @param {string} browser - The type of browser this driver is controlling + * @param {number} timeout + */ + constructor (driver, browser, timeout = 10000) { + this.driver = driver + this.browser = browser + this.timeout = timeout + } + + async delay (time) { + await new Promise(resolve => setTimeout(resolve, time)) + } + + async wait (condition, timeout = this.timeout) { + await this.driver.wait(condition, timeout) + } + + async quit () { + await this.driver.quit() + } + + // Element interactions + + async findElement (locator) { + return await this.driver.wait(until.elementLocated(locator), this.timeout) + } + + async findVisibleElement (locator) { + const element = await this.findElement(locator) + await this.driver.wait(until.elementIsVisible(element), this.timeout) + return element + } + + findElements (locator) { + return this.driver.wait(until.elementsLocated(locator), this.timeout) + } + + async clickElement (locator) { + const element = await this.findElement(locator) + await element.click() + } + + async scrollToElement (element) { + await this.driver.executeScript('arguments[0].scrollIntoView(true)', element) + } + + async assertElementNotPresent (locator) { + let dataTab + try { + dataTab = await this.findElement(locator) + } catch (err) { + assert(err instanceof webdriverError.NoSuchElementError || err instanceof webdriverError.TimeoutError) + } + assert.ok(!dataTab, 'Found element that should not be present') + } + + // Window management + + async openNewPage (url) { + const newHandle = await this.driver.switchTo().newWindow() + await this.driver.get(url) + return newHandle + } + + async switchToWindow (handle) { + await this.driver.switchTo().window(handle) + } + + async getAllWindowHandles () { + return await this.driver.getAllWindowHandles() + } + + async waitUntilXWindowHandles (x, delayStep = 1000, timeout = 5000) { + let timeElapsed = 0 + while (timeElapsed <= timeout) { + const windowHandles = await this.driver.getAllWindowHandles() + if (windowHandles.length === x) { + return + } + await this.delay(delayStep) + timeElapsed += delayStep + } + throw new Error('waitUntilXWindowHandles timed out polling window handles') + } + + async switchToWindowWithTitle (title, windowHandles) { + if (!windowHandles) { + windowHandles = await this.driver.getAllWindowHandles() + } + + for (const handle of windowHandles) { + await this.driver.switchTo().window(handle) + const handleTitle = await this.driver.getTitle() + if (handleTitle === title) { + return handle + } + } + + throw new Error('No window with title: ' + title) + } + + /** + * Closes all windows except those in the given list of exceptions + * @param {Array} exceptions the list of window handle exceptions + * @param {Array?} windowHandles the full list of window handles + * @returns {Promise} + */ + async closeAllWindowHandlesExcept (exceptions, windowHandles) { + windowHandles = windowHandles || await this.driver.getAllWindowHandles() + + for (const handle of windowHandles) { + if (!exceptions.includes(handle)) { + await this.driver.switchTo().window(handle) + await this.delay(1000) + await this.driver.close() + await this.delay(1000) + } + } + } + + // Error handling + + async verboseReportOnFailure (test) { + const artifactDir = `./test-artifacts/${this.browser}/${test.title}` + const filepathBase = `${artifactDir}/test-failure` + await fs.mkdir(artifactDir, { recursive: true }) + const screenshot = await this.driver.takeScreenshot() + await fs.writeFile(`${filepathBase}-screenshot.png`, screenshot, { encoding: 'base64' }) + const htmlSource = await this.driver.getPageSource() + await fs.writeFile(`${filepathBase}-dom.html`, htmlSource) + } + + async checkBrowserForConsoleErrors () { + const ignoredLogTypes = ['WARNING'] + const ignoredErrorMessages = [ + // Third-party Favicon 404s show up as errors + 'favicon.ico - Failed to load resource: the server responded with a status of 404 (Not Found)', + ] + const browserLogs = await this.driver.manage().logs().get('browser') + const errorEntries = browserLogs.filter(entry => !ignoredLogTypes.includes(entry.level.toString())) + const errorObjects = errorEntries.map(entry => entry.toJSON()) + return errorObjects.filter(entry => !ignoredErrorMessages.some(message => entry.message.includes(message))) + } +} + +module.exports = Driver diff --git a/test/e2e/webdriver/index.js b/test/e2e/webdriver/index.js index 7abf96ed9..66e0403cf 100644 --- a/test/e2e/webdriver/index.js +++ b/test/e2e/webdriver/index.js @@ -1,23 +1,29 @@ const { Browser } = require('selenium-webdriver') +const Driver = require('./driver') const ChromeDriver = require('./chrome') const FirefoxDriver = require('./firefox') +const fetchMockResponses = require('../../data/fetch-mocks.json') -const buildWebDriver = async function buildWebDriver ({ browser, extensionPath, responsive, port }) { +async function buildWebDriver ({ browser, extensionPath, responsive, port }) { switch (browser) { case Browser.CHROME: { const { driver, extensionId, extensionUrl } = await ChromeDriver.build({ extensionPath, responsive, port }) + setupFetchMocking(driver) + await driver.get(extensionUrl) return { - driver, + driver: new Driver(driver, browser), extensionId, extensionUrl, } } case Browser.FIREFOX: { const { driver, extensionId, extensionUrl } = await FirefoxDriver.build({ extensionPath, responsive, port }) + setupFetchMocking(driver) + await driver.get(extensionUrl) return { - driver, + driver: new Driver(driver, browser), extensionId, extensionUrl, } @@ -28,6 +34,38 @@ const buildWebDriver = async function buildWebDriver ({ browser, extensionPath, } } +async function setupFetchMocking (driver) { + // define fetchMocking script, to be evaluated in the browser + function fetchMocking (fetchMockResponses) { + window.origFetch = window.fetch.bind(window) + window.fetch = async (...args) => { + const url = args[0] + if (url === 'https://ethgasstation.info/json/ethgasAPI.json') { + return { json: async () => clone(fetchMockResponses.ethGasBasic) } + } else if (url === 'https://ethgasstation.info/json/predictTable.json') { + return { json: async () => clone(fetchMockResponses.ethGasPredictTable) } + } else if (url.match(/chromeextensionmm/)) { + return { json: async () => clone(fetchMockResponses.metametrics) } + } + return window.origFetch(...args) + } + if (window.chrome && window.chrome.webRequest) { + window.chrome.webRequest.onBeforeRequest.addListener(cancelInfuraRequest, { urls: ['https://*.infura.io/*'] }, ['blocking']) + } + function cancelInfuraRequest (requestDetails) { + console.log(`fetchMocking - Canceling request: "${requestDetails.url}"`) + return { cancel: true } + } + function clone (obj) { + return JSON.parse(JSON.stringify(obj)) + } + } + // fetchMockResponses are parsed last minute to ensure that objects are uniquely instantiated + const fetchMockResponsesJson = JSON.stringify(fetchMockResponses) + // eval the fetchMocking script in the browser + await driver.executeScript(`(${fetchMocking})(${fetchMockResponsesJson})`) +} + module.exports = { buildWebDriver, } diff --git a/test/integration/lib/confirm-sig-requests.js b/test/integration/lib/confirm-sig-requests.js index fa6c3d090..21a2fc05f 100644 --- a/test/integration/lib/confirm-sig-requests.js +++ b/test/integration/lib/confirm-sig-requests.js @@ -3,7 +3,7 @@ const { timeout, queryAsync, } = require('../../lib/util') -const fetchMockResponses = require('../../e2e/fetch-mocks.json') +const fetchMockResponses = require('../../data/fetch-mocks.json') QUnit.module('confirm sig requests') diff --git a/test/integration/lib/currency-localization.js b/test/integration/lib/currency-localization.js index dcd192341..915fcffab 100644 --- a/test/integration/lib/currency-localization.js +++ b/test/integration/lib/currency-localization.js @@ -4,7 +4,7 @@ const { queryAsync, findAsync, } = require('../../lib/util') -const fetchMockResponses = require('../../e2e/fetch-mocks.json') +const fetchMockResponses = require('../../data/fetch-mocks.json') QUnit.module('currency localization') diff --git a/test/integration/lib/tx-list-items.js b/test/integration/lib/tx-list-items.js index 9f614a7a5..4eb210d53 100644 --- a/test/integration/lib/tx-list-items.js +++ b/test/integration/lib/tx-list-items.js @@ -3,7 +3,7 @@ const { queryAsync, findAsync, } = require('../../lib/util') -const fetchMockResponses = require('../../e2e/fetch-mocks.json') +const fetchMockResponses = require('../../data/fetch-mocks.json') QUnit.module('tx list items') From 428fdee7e3b0b7ef85eda17d03d6199a96808037 Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Mon, 13 Jan 2020 07:08:39 -0800 Subject: [PATCH 109/689] Remove padding of info circle of advanced gas (#7810) --- .../app/gas-customization/advanced-gas-inputs/index.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/index.scss b/ui/app/components/app/gas-customization/advanced-gas-inputs/index.scss index a2352a332..8b5913c60 100644 --- a/ui/app/components/app/gas-customization/advanced-gas-inputs/index.scss +++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/index.scss @@ -20,10 +20,9 @@ @media screen and (max-width: 576px) { font-size: 10px; } - + .fa-info-circle { color: $silver; - margin-left: 10px; cursor: pointer; } From e20163bfda6972eae123f5d3e29989df812f016b Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 13 Jan 2020 11:39:38 -0330 Subject: [PATCH 110/689] Convert TokenList component to an ES6 class (#7785) Co-authored-by: Mark Stacey --- ui/app/components/app/token-list.js | 288 ++++++++++++++-------------- 1 file changed, 145 insertions(+), 143 deletions(-) diff --git a/ui/app/components/app/token-list.js b/ui/app/components/app/token-list.js index 2f052c712..db92fcb10 100644 --- a/ui/app/components/app/token-list.js +++ b/ui/app/components/app/token-list.js @@ -1,7 +1,6 @@ import PropTypes from 'prop-types' import React, { Component } from 'react' import TokenCell from './token-cell' -import { inherits } from 'util' import TokenTracker from 'eth-token-tracker' import { connect } from 'react-redux' import { getSelectedAddress } from '../../selectors/selectors' @@ -27,166 +26,169 @@ for (const address in contracts) { } } -TokenList.contextTypes = { - t: PropTypes.func, -} - -export default connect(mapStateToProps)(TokenList) - - -inherits(TokenList, Component) -function TokenList () { - this.state = { - tokens: [], - isLoading: true, - network: null, +class TokenList extends Component { + static contextTypes = { + t: PropTypes.func, } - Component.call(this) -} -TokenList.prototype.render = function TokenList () { - const { userAddress, assetImages } = this.props - const state = this.state - const { tokens, isLoading, error } = state - if (isLoading) { - return ( -
- {this.context.t('loadingTokens')} -
- ) + static propTypes = { + tokens: PropTypes.array.isRequired, + userAddress: PropTypes.string.isRequired, + network: PropTypes.string.isRequired, + assetImages: PropTypes.object.isRequired, } - if (error) { - log.error(error) - return ( -
- {this.context.t('troubleTokenBalances')} - { - global.platform.openWindow({ - url: `https://ethplorer.io/address/${userAddress}`, - }) - }} - > - {this.context.t('here')} - -
- ) + state = { + tokens: [], + isLoading: true, } - return ( -
- {tokens.map((tokenData, index) => { - tokenData.image = assetImages[tokenData.address] - return ( - - ) - })} -
- ) -} + createFreshTokenTracker () { + if (this.tracker) { + // Clean up old trackers when refreshing: + this.tracker.stop() + this.tracker.removeListener('update', this.balanceUpdater) + this.tracker.removeListener('error', this.showError) + } + + if (!global.ethereumProvider) { + return + } + const { userAddress } = this.props + + this.tracker = new TokenTracker({ + userAddress, + provider: global.ethereumProvider, + tokens: this.props.tokens, + pollingInterval: 8000, + }) -TokenList.prototype.componentDidMount = function () { - this.createFreshTokenTracker() -} -TokenList.prototype.createFreshTokenTracker = function () { - if (this.tracker) { - // Clean up old trackers when refreshing: - this.tracker.stop() - this.tracker.removeListener('update', this.balanceUpdater) - this.tracker.removeListener('error', this.showError) + // Set up listener instances for cleaning up + this.balanceUpdater = this.updateBalances.bind(this) + this.showError = (error) => { + this.setState({ error, isLoading: false }) + } + this.tracker.on('update', this.balanceUpdater) + this.tracker.on('error', this.showError) + + this.tracker.updateBalances() + .then(() => { + this.updateBalances(this.tracker.serialize()) + }) + .catch((reason) => { + log.error(`Problem updating balances`, reason) + this.setState({ isLoading: false }) + }) } - if (!global.ethereumProvider) { - return + updateBalances = function (tokens) { + if (!this.tracker.running) { + return + } + this.setState({ tokens, isLoading: false }) } - const { userAddress } = this.props - - this.tracker = new TokenTracker({ - userAddress, - provider: global.ethereumProvider, - tokens: this.props.tokens, - pollingInterval: 8000, - }) - - // Set up listener instances for cleaning up - this.balanceUpdater = this.updateBalances.bind(this) - this.showError = (error) => { - this.setState({ error, isLoading: false }) + componentDidMount () { + this.createFreshTokenTracker() } - this.tracker.on('update', this.balanceUpdater) - this.tracker.on('error', this.showError) - this.tracker.updateBalances() - .then(() => { - this.updateBalances(this.tracker.serialize()) - }) - .catch((reason) => { - log.error(`Problem updating balances`, reason) - this.setState({ isLoading: false }) - }) -} + componentDidUpdate (prevProps) { + const { + network: oldNet, + userAddress: oldAddress, + tokens, + } = prevProps + const { + network: newNet, + userAddress: newAddress, + tokens: newTokens, + } = this.props + + const isLoading = newNet === 'loading' + const missingInfo = !oldNet || !newNet || !oldAddress || !newAddress + const sameUserAndNetwork = oldAddress === newAddress && oldNet === newNet + const shouldUpdateTokens = isLoading || missingInfo || sameUserAndNetwork + + const oldTokensLength = tokens ? tokens.length : 0 + const tokensLengthUnchanged = oldTokensLength === newTokens.length + + if (tokensLengthUnchanged && shouldUpdateTokens) { + return + } + + this.setState({ isLoading: true }) + this.createFreshTokenTracker() + } -TokenList.prototype.componentDidUpdate = function (prevProps) { - const { - network: oldNet, - userAddress: oldAddress, - tokens, - } = prevProps - const { - network: newNet, - userAddress: newAddress, - tokens: newTokens, - } = this.props - - const isLoading = newNet === 'loading' - const missingInfo = !oldNet || !newNet || !oldAddress || !newAddress - const sameUserAndNetwork = oldAddress === newAddress && oldNet === newNet - const shouldUpdateTokens = isLoading || missingInfo || sameUserAndNetwork - - const oldTokensLength = tokens ? tokens.length : 0 - const tokensLengthUnchanged = oldTokensLength === newTokens.length - - if (tokensLengthUnchanged && shouldUpdateTokens) { - return + componentWillUnmount () { + if (!this.tracker) { + return + } + this.tracker.stop() + this.tracker.removeListener('update', this.balanceUpdater) + this.tracker.removeListener('error', this.showError) } - this.setState({ isLoading: true }) - this.createFreshTokenTracker() -} + render () { + const { userAddress, assetImages } = this.props + const state = this.state + const { tokens, isLoading, error } = state + if (isLoading) { + return ( +
+ {this.context.t('loadingTokens')} +
+ ) + } + + if (error) { + log.error(error) + return ( +
+ {this.context.t('troubleTokenBalances')} + { + global.platform.openWindow({ + url: `https://ethplorer.io/address/${userAddress}`, + }) + }} + > + {this.context.t('here')} + +
+ ) + } -TokenList.prototype.updateBalances = function (tokens) { - if (!this.tracker.running) { - return + return ( +
+ {tokens.map((tokenData, index) => { + tokenData.image = assetImages[tokenData.address] + return ( + + ) + })} +
+ ) } - this.setState({ tokens, isLoading: false }) } -TokenList.prototype.componentWillUnmount = function () { - if (!this.tracker) { - return - } - this.tracker.stop() - this.tracker.removeListener('update', this.balanceUpdater) - this.tracker.removeListener('error', this.showError) -} +export default connect(mapStateToProps)(TokenList) From 3b3325d191bdad512d7d14b826f1b1591f17de67 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 13 Jan 2020 11:41:51 -0330 Subject: [PATCH 111/689] Convert ReadOnlyInput to functional component (#7788) Co-authored-by: Mark Stacey --- ui/app/components/ui/readonly-input.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/ui/app/components/ui/readonly-input.js b/ui/app/components/ui/readonly-input.js index 65eea7307..f78c48027 100644 --- a/ui/app/components/ui/readonly-input.js +++ b/ui/app/components/ui/readonly-input.js @@ -1,21 +1,14 @@ -import React, { Component } from 'react' -import { inherits } from 'util' +import PropTypes from 'prop-types' +import React from 'react' -export default ReadOnlyInput - -inherits(ReadOnlyInput, Component) -function ReadOnlyInput () { - Component.call(this) -} - -ReadOnlyInput.prototype.render = function ReadOnlyInput () { +export default function ReadOnlyInput (props) { const { wrapperClass = '', inputClass = '', value, textarea, onClick, - } = this.props + } = props const InputType = textarea ? 'textarea' : 'input' @@ -32,3 +25,10 @@ ReadOnlyInput.prototype.render = function ReadOnlyInput () { ) } +ReadOnlyInput.propTypes = { + wrapperClass: PropTypes.string, + inputClass: PropTypes.string, + value: PropTypes.string, + textarea: PropTypes.bool, + onClick: PropTypes.func, +} From 789dd196779d07b54ee86ada705fd5669477f08c Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 13 Jan 2020 11:42:11 -0330 Subject: [PATCH 112/689] Convert Network component to an ES6 class (#7784) Co-authored-by: Mark Stacey --- ui/app/components/app/network.js | 324 ++++++++++++++++--------------- 1 file changed, 164 insertions(+), 160 deletions(-) diff --git a/ui/app/components/app/network.js b/ui/app/components/app/network.js index 563e2e164..51543c3a2 100644 --- a/ui/app/components/app/network.js +++ b/ui/app/components/app/network.js @@ -2,175 +2,179 @@ import PropTypes from 'prop-types' import React, { Component } from 'react' import classnames from 'classnames' -import { inherits } from 'util' import NetworkDropdownIcon from './dropdowns/components/network-dropdown-icon' -Network.contextTypes = { - t: PropTypes.func, -} - -export default Network - -inherits(Network, Component) - -function Network () { - Component.call(this) -} - -Network.prototype.render = function Network () { - const context = this.context - const networkNumber = this.props.network - let providerName, providerNick, providerUrl - try { - providerName = this.props.provider.type - providerNick = this.props.provider.nickname || '' - providerUrl = this.props.provider.rpcTarget - } catch (e) { - providerName = null +export default class Network extends Component { + static contextTypes = { + t: PropTypes.func, } - const providerId = providerNick || providerName || providerUrl || null - let iconName - let hoverText - if (providerName === 'mainnet') { - hoverText = context.t('mainnet') - iconName = 'ethereum-network' - } else if (providerName === 'ropsten') { - hoverText = context.t('ropsten') - iconName = 'ropsten-test-network' - } else if (providerName === 'kovan') { - hoverText = context.t('kovan') - iconName = 'kovan-test-network' - } else if (providerName === 'rinkeby') { - hoverText = context.t('rinkeby') - iconName = 'rinkeby-test-network' - } else if (providerName === 'goerli') { - hoverText = context.t('goerli') - iconName = 'goerli-test-network' - } else { - hoverText = providerId - iconName = 'private-network' + static propTypes = { + network: PropTypes.string.isRequired, + provider: PropTypes.shape({ + type: PropTypes.string, + nickname: PropTypes.string, + rpcTarget: PropTypes.string, + }).isRequired, + disabled: PropTypes.bool, + onClick: PropTypes.func.isRequired, } - return ( -
{ - if (!this.props.disabled) { - this.props.onClick(event) - } - }} - > - {(function () { - switch (iconName) { - case 'ethereum-network': - return ( -
- -
- {context.t('mainnet')} + render () { + const context = this.context + const networkNumber = this.props.network + let providerName, providerNick, providerUrl + try { + providerName = this.props.provider.type + providerNick = this.props.provider.nickname || '' + providerUrl = this.props.provider.rpcTarget + } catch (e) { + providerName = null + } + const providerId = providerNick || providerName || providerUrl || null + let iconName + let hoverText + + if (providerName === 'mainnet') { + hoverText = context.t('mainnet') + iconName = 'ethereum-network' + } else if (providerName === 'ropsten') { + hoverText = context.t('ropsten') + iconName = 'ropsten-test-network' + } else if (providerName === 'kovan') { + hoverText = context.t('kovan') + iconName = 'kovan-test-network' + } else if (providerName === 'rinkeby') { + hoverText = context.t('rinkeby') + iconName = 'rinkeby-test-network' + } else if (providerName === 'goerli') { + hoverText = context.t('goerli') + iconName = 'goerli-test-network' + } else { + hoverText = providerId + iconName = 'private-network' + } + + return ( +
{ + if (!this.props.disabled) { + this.props.onClick(event) + } + }} + > + {(function () { + switch (iconName) { + case 'ethereum-network': + return ( +
+ +
+ {context.t('mainnet')} +
+
-
-
- ) - case 'ropsten-test-network': - return ( -
- -
- {context.t('ropsten')} + ) + case 'ropsten-test-network': + return ( +
+ +
+ {context.t('ropsten')} +
+
-
-
- ) - case 'kovan-test-network': - return ( -
- -
- {context.t('kovan')} + ) + case 'kovan-test-network': + return ( +
+ +
+ {context.t('kovan')} +
+
-
-
- ) - case 'rinkeby-test-network': - return ( -
- -
- {context.t('rinkeby')} + ) + case 'rinkeby-test-network': + return ( +
+ +
+ {context.t('rinkeby')} +
+
-
-
- ) - case 'goerli-test-network': - return ( -
- -
{context.t('goerli')}
-
-
- ) - default: - return ( -
- {networkNumber === 'loading' - ? ( - this.props.onClick(event)} - > - - - ) - : ( - - )} -
- { - providerName === 'localhost' - ? context.t('localhost') - : providerNick || context.t('privateNetwork') - } + ) + case 'goerli-test-network': + return ( +
+ +
{context.t('goerli')}
+
-
-
- ) - } - })()} -
- ) + ) + default: + return ( +
+ {networkNumber === 'loading' + ? ( + this.props.onClick(event)} + > + + + ) + : ( + + )} +
+ { + providerName === 'localhost' + ? context.t('localhost') + : providerNick || context.t('privateNetwork') + } +
+
+
+ ) + } + })()} +
+ ) + } } From f850a17f630d53dd93667338e03786c2b26dfd64 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 13 Jan 2020 11:42:26 -0330 Subject: [PATCH 113/689] Convert FiatValue component to ES6 class (#7786) Co-authored-by: Mark Stacey --- ui/app/components/ui/fiat-value.js | 48 +++++++++++++++--------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/ui/app/components/ui/fiat-value.js b/ui/app/components/ui/fiat-value.js index bd217dc47..a029b2559 100644 --- a/ui/app/components/ui/fiat-value.js +++ b/ui/app/components/ui/fiat-value.js @@ -1,36 +1,36 @@ +import PropTypes from 'prop-types' import React, { Component } from 'react' -import { inherits } from 'util' import { formatBalance } from '../../helpers/utils/util' -export default FiatValue +export default class FiatValue extends Component { + static propTypes = { + conversionRate: PropTypes.number.isRequired, + currentCurrency: PropTypes.string, + style: PropTypes.object, + value: PropTypes.string.isRequired, + } -inherits(FiatValue, Component) -function FiatValue () { - Component.call(this) -} + render () { + const { conversionRate, currentCurrency, style } = this.props + const renderedCurrency = currentCurrency || '' -FiatValue.prototype.render = function () { - const props = this.props - const { conversionRate, currentCurrency, style } = props - const renderedCurrency = currentCurrency || '' + const value = formatBalance(this.props.value, 6) - const value = formatBalance(props.value, 6) + if (value === 'None') { + return value + } + let fiatDisplayNumber, fiatTooltipNumber + const splitBalance = value.split(' ') - if (value === 'None') { - return value - } - let fiatDisplayNumber, fiatTooltipNumber - const splitBalance = value.split(' ') + if (conversionRate !== 0) { + fiatTooltipNumber = Number(splitBalance[0]) * conversionRate + fiatDisplayNumber = fiatTooltipNumber.toFixed(2) + } else { + fiatDisplayNumber = 'N/A' + } - if (conversionRate !== 0) { - fiatTooltipNumber = Number(splitBalance[0]) * conversionRate - fiatDisplayNumber = fiatTooltipNumber.toFixed(2) - } else { - fiatDisplayNumber = 'N/A' - fiatTooltipNumber = 'Unknown' + return fiatDisplay(fiatDisplayNumber, renderedCurrency.toUpperCase(), style) } - - return fiatDisplay(fiatDisplayNumber, renderedCurrency.toUpperCase(), style) } function fiatDisplay (fiatDisplayNumber, fiatSuffix, styleOveride = {}) { From b9757f5563568fb4914d1211071ae22e73f33002 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 13 Jan 2020 11:42:53 -0330 Subject: [PATCH 114/689] Convert account import components to ES6 classes (#7791) Co-authored-by: Mark Stacey --- .../create-account/import-account/index.js | 140 ++++++------- .../import-account/private-key.js | 195 +++++++++--------- 2 files changed, 166 insertions(+), 169 deletions(-) diff --git a/ui/app/pages/create-account/import-account/index.js b/ui/app/pages/create-account/import-account/index.js index 915734048..832d762d3 100644 --- a/ui/app/pages/create-account/import-account/index.js +++ b/ui/app/pages/create-account/import-account/index.js @@ -1,5 +1,4 @@ import React, { Component } from 'react' -import { inherits } from 'util' import PropTypes from 'prop-types' import Select from 'react-select' @@ -8,86 +7,79 @@ import JsonImportView from './json.js' import PrivateKeyImportView from './private-key.js' +export default class AccountImportSubview extends Component { + static contextTypes = { + t: PropTypes.func, + } -AccountImportSubview.contextTypes = { - t: PropTypes.func, -} - -export default AccountImportSubview + state = {} + getMenuItemTexts () { + return [ + this.context.t('privateKey'), + this.context.t('jsonFile'), + ] + } -inherits(AccountImportSubview, Component) -function AccountImportSubview () { - Component.call(this) -} + renderImportView () { + const { type } = this.state + const menuItems = this.getMenuItemTexts() + const current = type || menuItems[0] -AccountImportSubview.prototype.getMenuItemTexts = function () { - return [ - this.context.t('privateKey'), - this.context.t('jsonFile'), - ] -} + switch (current) { + case this.context.t('privateKey'): + return + case this.context.t('jsonFile'): + return + default: + return + } + } -AccountImportSubview.prototype.render = function () { - const state = this.state || {} - const menuItems = this.getMenuItemTexts() - const { type } = state + render () { + const menuItems = this.getMenuItemTexts() + const { type } = this.state - return ( -
-
- {this.context.t('importAccountMsg')} - { - global.platform.openWindow({ - url: 'https://metamask.zendesk.com/hc/en-us/articles/360015289932', - }) - }} - > - {this.context.t('here')} - -
-
-
- {this.context.t('selectType')} + return ( +
+
+ {this.context.t('importAccountMsg')} + { + global.platform.openWindow({ + url: 'https://metamask.zendesk.com/hc/en-us/articles/360015289932', + }) + }} + > + {this.context.t('here')} + +
+
+
+ {this.context.t('selectType')} +
+ { - return { - value: type, - label: type, - } - })} - onChange={(opt) => { - this.setState({ type: opt.value }) - }} - /> + {this.renderImportView()}
- {this.renderImportView()} -
- ) -} - -AccountImportSubview.prototype.renderImportView = function () { - const state = this.state || {} - const { type } = state - const menuItems = this.getMenuItemTexts() - const current = type || menuItems[0] - - switch (current) { - case this.context.t('privateKey'): - return - case this.context.t('jsonFile'): - return - default: - return + ) } } diff --git a/ui/app/pages/create-account/import-account/private-key.js b/ui/app/pages/create-account/import-account/private-key.js index ab0c14a9e..988c42e6b 100644 --- a/ui/app/pages/create-account/import-account/private-key.js +++ b/ui/app/pages/create-account/import-account/private-key.js @@ -1,5 +1,4 @@ import React, { Component } from 'react' -import { inherits } from 'util' import { withRouter } from 'react-router-dom' import { compose } from 'recompose' import PropTypes from 'prop-types' @@ -9,9 +8,106 @@ import { DEFAULT_ROUTE } from '../../../helpers/constants/routes' import { getMetaMaskAccounts } from '../../../selectors/selectors' import Button from '../../../components/ui/button' -PrivateKeyImportView.contextTypes = { - t: PropTypes.func, - metricsEvent: PropTypes.func, +class PrivateKeyImportView extends Component { + static contextTypes = { + t: PropTypes.func, + metricsEvent: PropTypes.func, + } + + static propTypes = { + importNewAccount: PropTypes.func.isRequired, + history: PropTypes.object.isRequired, + displayWarning: PropTypes.func.isRequired, + setSelectedAddress: PropTypes.func.isRequired, + firstAddress: PropTypes.string.isRequired, + error: PropTypes.node, + } + + + createNewKeychain () { + const input = document.getElementById('private-key-box') + const privateKey = input.value + const { importNewAccount, history, displayWarning, setSelectedAddress, firstAddress } = this.props + + importNewAccount('Private Key', [ privateKey ]) + .then(({ selectedAddress }) => { + if (selectedAddress) { + this.context.metricsEvent({ + eventOpts: { + category: 'Accounts', + action: 'Import Account', + name: 'Imported Account with Private Key', + }, + }) + history.push(DEFAULT_ROUTE) + displayWarning(null) + } else { + displayWarning('Error importing account.') + this.context.metricsEvent({ + eventOpts: { + category: 'Accounts', + action: 'Import Account', + name: 'Error importing with Private Key', + }, + }) + setSelectedAddress(firstAddress) + } + }) + .catch(err => err && displayWarning(err.message || err)) + } + + createKeyringOnEnter = (event) => { + if (event.key === 'Enter') { + event.preventDefault() + this.createNewKeychain() + } + } + + render () { + const { error, displayWarning } = this.props + + return ( +
+ + {this.context.t('pastePrivateKey')} + +
+ this.createKeyringOnEnter(e)} + /> +
+
+ + +
+ { + error + ? {error} + : null + } +
+ ) + } } export default compose( @@ -36,94 +132,3 @@ function mapDispatchToProps (dispatch) { setSelectedAddress: (address) => dispatch(actions.setSelectedAddress(address)), } } - -inherits(PrivateKeyImportView, Component) -function PrivateKeyImportView () { - this.createKeyringOnEnter = this.createKeyringOnEnter.bind(this) - Component.call(this) -} - -PrivateKeyImportView.prototype.render = function PrivateKeyImportView () { - const { error, displayWarning } = this.props - - return ( -
- - {this.context.t('pastePrivateKey')} - -
- this.createKeyringOnEnter(e)} - /> -
-
- - -
- { - error - ? {error} - : null - } -
- ) -} - -PrivateKeyImportView.prototype.createKeyringOnEnter = function (event) { - if (event.key === 'Enter') { - event.preventDefault() - this.createNewKeychain() - } -} - -PrivateKeyImportView.prototype.createNewKeychain = function () { - const input = document.getElementById('private-key-box') - const privateKey = input.value - const { importNewAccount, history, displayWarning, setSelectedAddress, firstAddress } = this.props - - importNewAccount('Private Key', [ privateKey ]) - .then(({ selectedAddress }) => { - if (selectedAddress) { - this.context.metricsEvent({ - eventOpts: { - category: 'Accounts', - action: 'Import Account', - name: 'Imported Account with Private Key', - }, - }) - history.push(DEFAULT_ROUTE) - displayWarning(null) - } else { - displayWarning('Error importing account.') - this.context.metricsEvent({ - eventOpts: { - category: 'Accounts', - action: 'Import Account', - name: 'Error importing with Private Key', - }, - }) - setSelectedAddress(firstAddress) - } - }) - .catch(err => err && displayWarning(err.message || err)) -} From 61d18097509a8f36ec074c5b28d94b982a4a18c7 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 13 Jan 2020 12:59:21 -0330 Subject: [PATCH 115/689] Purge xtend from the UI (#7795) --- .../app/dropdowns/components/dropdown.js | 3 +- ui/app/ducks/app/app.js | 268 +++++++++++------- ui/app/ducks/index.js | 3 +- ui/app/ducks/locale/locale.js | 8 +- ui/app/ducks/metamask/metamask.js | 205 ++++++++------ ui/app/ducks/send/send.duck.js | 31 +- .../confirm-add-suggested-token.container.js | 4 +- 7 files changed, 304 insertions(+), 218 deletions(-) diff --git a/ui/app/components/app/dropdowns/components/dropdown.js b/ui/app/components/app/dropdowns/components/dropdown.js index bcc91b4cf..323bad186 100644 --- a/ui/app/components/app/dropdowns/components/dropdown.js +++ b/ui/app/components/app/dropdowns/components/dropdown.js @@ -1,7 +1,6 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import MenuDroppo from '../../menu-droppo' -import extend from 'xtend' export class Dropdown extends Component { render () { @@ -15,7 +14,7 @@ export class Dropdown extends Component { useCssTransition, } = this.props - const innerStyleDefaults = extend({ + const innerStyleDefaults = Object.assign({ borderRadius: '4px', padding: '8px 16px', background: 'rgba(0, 0, 0, 0.8)', diff --git a/ui/app/ducks/app/app.js b/ui/app/ducks/app/app.js index d6535d5d7..c1bcc57ae 100644 --- a/ui/app/ducks/app/app.js +++ b/ui/app/ducks/app/app.js @@ -1,4 +1,3 @@ -import extend from 'xtend' import txHelper from '../../../lib/tx-helper' import log from 'loglevel' import { actionConstants } from '../../store/actions' @@ -30,7 +29,7 @@ export default function reduceApp (state, action) { } // default state - const appState = extend({ + const appState = Object.assign({ shouldClose: false, menuOpen: false, modal: { @@ -85,57 +84,65 @@ export default function reduceApp (state, action) { switch (action.type) { // dropdown methods case actions.NETWORK_DROPDOWN_OPEN: - return extend(appState, { + return { + ...appState, networkDropdownOpen: true, - }) + } case actions.NETWORK_DROPDOWN_CLOSE: - return extend(appState, { + return { + ...appState, networkDropdownOpen: false, - }) + } // sidebar methods case actions.SIDEBAR_OPEN: - return extend(appState, { + return { + ...appState, sidebar: { ...action.value, isOpen: true, }, - }) + } case actions.SIDEBAR_CLOSE: - return extend(appState, { + return { + ...appState, sidebar: { ...appState.sidebar, isOpen: false, }, - }) + } // alert methods case actions.ALERT_OPEN: - return extend(appState, { + return { + ...appState, alertOpen: true, alertMessage: action.value, - }) + } case actions.ALERT_CLOSE: - return extend(appState, { + return { + ...appState, alertOpen: false, alertMessage: null, - }) + } // qr scanner methods case actions.QR_CODE_DETECTED: - return extend(appState, { + return { + ...appState, qrCodeData: action.value, - }) + } // modal methods: case actions.MODAL_OPEN: const { name, ...modalProps } = action.payload - return extend(appState, { + return { + ...appState, modal: { open: true, modalState: { @@ -144,28 +151,31 @@ export default function reduceApp (state, action) { }, previousModalState: { ...appState.modal.modalState }, }, - }) + } case actions.MODAL_CLOSE: - return extend(appState, { + return { + ...appState, modal: Object.assign( state.appState.modal, { open: false }, { modalState: { name: null, props: {} } }, { previousModalState: appState.modal.modalState }, ), - }) + } // transition methods case actions.TRANSITION_FORWARD: - return extend(appState, { + return { + ...appState, transForward: true, - }) + } case actions.FORGOT_PASSWORD: - const newState = extend(appState, { + const newState = { + ...appState, forgottenPassword: action.value, - }) + } if (action.value) { newState.currentView = { @@ -176,85 +186,95 @@ export default function reduceApp (state, action) { return newState case actions.SHOW_CONFIG_PAGE: - return extend(appState, { + return { + ...appState, currentView: { name: 'config', context: appState.currentView.context, }, transForward: action.value, - }) + } case actions.SHOW_ADD_TOKEN_PAGE: - return extend(appState, { + return { + ...appState, currentView: { name: 'add-token', context: appState.currentView.context, }, transForward: action.value, - }) + } case actions.SET_NEW_ACCOUNT_FORM: - return extend(appState, { + return { + ...appState, currentView: { name: appState.currentView.name, context: action.formToSelect, }, - }) + } case actions.SHOW_INFO_PAGE: - return extend(appState, { + return { + ...appState, currentView: { name: 'info', context: appState.currentView.context, }, transForward: true, - }) + } case actions.SHOW_SEND_PAGE: - return extend(appState, { + return { + ...appState, currentView: { name: 'sendTransaction', context: appState.currentView.context, }, transForward: true, warning: null, - }) + } case actions.SHOW_SEND_TOKEN_PAGE: - return extend(appState, { + return { + ...appState, currentView: { name: 'sendToken', context: appState.currentView.context, }, transForward: true, warning: null, - }) + } // unlock case actions.UNLOCK_METAMASK: - return extend(appState, { + return { + ...appState, forgottenPassword: appState.forgottenPassword ? !appState.forgottenPassword : null, detailView: {}, transForward: true, isLoading: false, warning: null, - }) + } case actions.LOCK_METAMASK: - return extend(appState, { + return { + ...appState, currentView: defaultView, transForward: false, warning: null, - }) + } // accounts case actions.GO_HOME: - return extend(appState, { - currentView: extend(appState.currentView, { + return { + ...appState, + currentView: { + ...appState.currentView, name: 'accountDetail', - }), + }, accountDetail: { subview: 'transactions', accountExport: 'none', @@ -262,10 +282,11 @@ export default function reduceApp (state, action) { }, transForward: false, warning: null, - }) + } case actions.SHOW_ACCOUNT_DETAIL: - return extend(appState, { + return { + ...appState, forgottenPassword: appState.forgottenPassword ? !appState.forgottenPassword : null, currentView: { name: 'accountDetail', @@ -277,10 +298,11 @@ export default function reduceApp (state, action) { privateKey: '', }, transForward: false, - }) + } case actions.SHOW_ACCOUNTS_PAGE: - return extend(appState, { + return { + ...appState, currentView: { name: 'accounts', }, @@ -289,10 +311,11 @@ export default function reduceApp (state, action) { warning: null, scrollToBottom: false, forgottenPassword: false, - }) + } case actions.SHOW_CONF_TX_PAGE: - return extend(appState, { + return { + ...appState, currentView: { name: 'confTx', context: action.id ? indexForPending(state, action.id) : 0, @@ -300,7 +323,7 @@ export default function reduceApp (state, action) { transForward: action.transForward, warning: null, isLoading: false, - }) + } case actions.COMPLETED_TX: log.debug('reducing COMPLETED_TX for tx ' + action.value) @@ -310,17 +333,19 @@ export default function reduceApp (state, action) { if (hasOtherUnconfActions) { log.debug('reducer detected txs - rendering confTx view') - return extend(appState, { + return { + ...appState, transForward: false, currentView: { name: 'confTx', context: 0, }, warning: null, - }) + } } else { log.debug('attempting to close popup') - return extend(appState, { + return { + ...appState, // indicate notification should close shouldClose: true, transForward: false, @@ -332,79 +357,91 @@ export default function reduceApp (state, action) { accountDetail: { subview: 'transactions', }, - }) + } } case actions.TRANSACTION_ERROR: - return extend(appState, { + return { + ...appState, currentView: { name: 'confTx', errorMessage: 'There was a problem submitting this transaction.', }, - }) + } case actions.UNLOCK_FAILED: - return extend(appState, { + return { + ...appState, warning: action.value || 'Incorrect password. Try again.', - }) + } case actions.UNLOCK_SUCCEEDED: - return extend(appState, { + return { + ...appState, warning: '', - }) + } case actions.SET_HARDWARE_WALLET_DEFAULT_HD_PATH: const { device, path } = action.value const newDefaults = { ...appState.defaultHdPaths } newDefaults[device] = path - return extend(appState, { + return { + ...appState, defaultHdPaths: newDefaults, - }) + } case actions.SHOW_LOADING: - return extend(appState, { + return { + ...appState, isLoading: true, loadingMessage: action.value, - }) + } case actions.HIDE_LOADING: - return extend(appState, { + return { + ...appState, isLoading: false, - }) + } case actions.SHOW_SUB_LOADING_INDICATION: - return extend(appState, { + return { + ...appState, isSubLoading: true, - }) + } case actions.HIDE_SUB_LOADING_INDICATION: - return extend(appState, { + return { + ...appState, isSubLoading: false, - }) + } case actions.DISPLAY_WARNING: - return extend(appState, { + return { + ...appState, warning: action.value, isLoading: false, - }) + } case actions.HIDE_WARNING: - return extend(appState, { + return { + ...appState, warning: undefined, - }) + } case actions.SHOW_PRIVATE_KEY: - return extend(appState, { + return { + ...appState, accountDetail: { subview: 'export', accountExport: 'completed', privateKey: action.value, }, - }) + } case actions.PAIR_UPDATE: - return extend(appState, { + return { + ...appState, buyView: { subview: 'ShapeShift', formView: { @@ -417,10 +454,11 @@ export default function reduceApp (state, action) { amount: appState.buyView.amount, warning: null, }, - }) + } case actions.SHOW_QR: - return extend(appState, { + return { + ...appState, qrRequested: true, transForward: true, @@ -428,10 +466,11 @@ export default function reduceApp (state, action) { message: action.value.message, data: action.value.data, }, - }) + } case actions.SHOW_QR_VIEW: - return extend(appState, { + return { + ...appState, currentView: { name: 'qr', context: appState.currentView.context, @@ -441,75 +480,88 @@ export default function reduceApp (state, action) { message: action.value.message, data: action.value.data, }, - }) + } case actions.SET_MOUSE_USER_STATE: - return extend(appState, { + return { + ...appState, isMouseUser: action.value, - }) + } case actions.GAS_LOADING_STARTED: - return extend(appState, { + return { + ...appState, gasIsLoading: true, - }) + } case actions.GAS_LOADING_FINISHED: - return extend(appState, { + return { + ...appState, gasIsLoading: false, - }) + } case actions.SET_NETWORK_NONCE: - return extend(appState, { + return { + ...appState, networkNonce: action.value, - }) + } case actions.SET_PREVIOUS_PROVIDER: if (action.value === 'loading') { return appState } - return extend(appState, { + return { + ...appState, lastSelectedProvider: action.value, - }) + } case actions.SET_SELECTED_SETTINGS_RPC_URL: - return extend(appState, { + return { + ...appState, networksTabSelectedRpcUrl: action.value, - }) + } case actions.SET_NETWORKS_TAB_ADD_MODE: - return extend(appState, { + return { + ...appState, networksTabIsInAddMode: action.value, - }) + } case actions.LOADING_METHOD_DATA_STARTED: - return extend(appState, { + return { + ...appState, loadingMethodData: true, - }) + } case actions.LOADING_METHOD_DATA_FINISHED: - return extend(appState, { + return { + ...appState, loadingMethodData: false, - }) + } case SET_THREEBOX_LAST_UPDATED: - return extend(appState, { + return { + ...appState, threeBoxLastUpdated: action.value, - }) + } case actions.SET_REQUEST_ACCOUNT_TABS: - return extend(appState, { + return { + ...appState, requestAccountTabs: action.value, - }) + } case actions.SET_OPEN_METAMASK_TAB_IDS: - return extend(appState, { + return { + ...appState, openMetaMaskTabs: action.value, - }) + } case actions.SET_CURRENT_WINDOW_TAB: - return extend(appState, { + return { + ...appState, currentWindowTab: action.value, - }) + } default: return appState diff --git a/ui/app/ducks/index.js b/ui/app/ducks/index.js index 2b864947f..3ceb529c1 100644 --- a/ui/app/ducks/index.js +++ b/ui/app/ducks/index.js @@ -1,5 +1,4 @@ import clone from 'clone' -import extend from 'xtend' import copyToClipboard from 'copy-to-clipboard' // @@ -19,7 +18,7 @@ export default rootReducer function rootReducer (state, action) { // clone - state = extend(state) + state = { ...state } if (action.type === 'GLOBAL_FORCE_UPDATE') { return action.value diff --git a/ui/app/ducks/locale/locale.js b/ui/app/ducks/locale/locale.js index f50c6447c..cbb334f1c 100644 --- a/ui/app/ducks/locale/locale.js +++ b/ui/app/ducks/locale/locale.js @@ -1,16 +1,16 @@ -import extend from 'xtend' import { actionConstants } from '../../store/actions' export default reduceMetamask function reduceMetamask (state, action) { - const localeMessagesState = extend({}, state.localeMessages) + const localeMessagesState = { ...state.localeMessages } switch (action.type) { case actionConstants.SET_CURRENT_LOCALE: - return extend(localeMessagesState, { + return { + ...localeMessagesState, current: action.value.messages, - }) + } default: return localeMessagesState } diff --git a/ui/app/ducks/metamask/metamask.js b/ui/app/ducks/metamask/metamask.js index 1ccf88ebe..e22e7e17f 100644 --- a/ui/app/ducks/metamask/metamask.js +++ b/ui/app/ducks/metamask/metamask.js @@ -1,4 +1,3 @@ -import extend from 'xtend' import { actionConstants } from '../../store/actions' import { getEnvironmentType } from '../../../../app/scripts/lib/util' import { ENVIRONMENT_TYPE_POPUP } from '../../../../app/scripts/lib/enums' @@ -11,7 +10,7 @@ function reduceMetamask (state, action) { let newState // clone + defaults - const metamaskState = extend({ + const metamaskState = Object.assign({ isInitialized: false, isUnlocked: false, isAccountMenuOpen: false, @@ -65,41 +64,46 @@ function reduceMetamask (state, action) { switch (action.type) { case actions.UPDATE_METAMASK_STATE: - return extend(metamaskState, action.value) + return { ...metamaskState, ...action.value } case actions.UNLOCK_METAMASK: - return extend(metamaskState, { + return { + ...metamaskState, isUnlocked: true, isInitialized: true, selectedAddress: action.value, - }) + } case actions.LOCK_METAMASK: - return extend(metamaskState, { + return { + ...metamaskState, isUnlocked: false, - }) + } case actions.SET_RPC_TARGET: - return extend(metamaskState, { + return { + ...metamaskState, provider: { type: 'rpc', rpcTarget: action.value, }, - }) + } case actions.SET_PROVIDER_TYPE: - return extend(metamaskState, { + return { + ...metamaskState, provider: { type: action.value, }, - }) + } case actions.COMPLETED_TX: const stringId = String(action.id) - newState = extend(metamaskState, { + newState = { + ...metamaskState, unapprovedTxs: {}, unapprovedMsgs: {}, - }) + } for (const id in metamaskState.unapprovedTxs) { if (id !== stringId) { newState.unapprovedTxs[id] = metamaskState.unapprovedTxs[id] @@ -113,28 +117,31 @@ function reduceMetamask (state, action) { return newState case actions.SHOW_ACCOUNT_DETAIL: - newState = extend(metamaskState, { + return { + ...metamaskState, isUnlocked: true, isInitialized: true, selectedAddress: action.value, - }) - return newState + } case actions.SET_SELECTED_TOKEN: - newState = extend(metamaskState, { + newState = { + ...metamaskState, selectedTokenAddress: action.value, - }) - const newSend = extend(metamaskState.send) + } + const newSend = { ...metamaskState.send } if (metamaskState.send.editingTransactionId && !action.value) { delete newSend.token const unapprovedTx = newState.unapprovedTxs[newSend.editingTransactionId] || {} const txParams = unapprovedTx.txParams || {} - newState.unapprovedTxs = extend(newState.unapprovedTxs, { - [newSend.editingTransactionId]: extend(unapprovedTx, { - txParams: extend(txParams, { data: '' }), - }), - }) + newState.unapprovedTxs = { + ...newState.unapprovedTxs, + [newSend.editingTransactionId]: { + ...unapprovedTx, + txParams: { ...txParams, data: '' }, + }, + } newSend.tokenBalance = null newSend.balance = '0' } @@ -146,98 +153,109 @@ function reduceMetamask (state, action) { const account = action.value.account const name = action.value.label const id = {} - id[account] = extend(metamaskState.identities[account], { name }) - const identities = extend(metamaskState.identities, id) - return extend(metamaskState, { identities }) + id[account] = Object.assign({}, metamaskState.identities[account], { name }) + const identities = Object.assign({}, metamaskState.identities, id) + return Object.assign(metamaskState, { identities }) case actions.SET_CURRENT_FIAT: - return extend(metamaskState, { + return Object.assign(metamaskState, { currentCurrency: action.value.currentCurrency, conversionRate: action.value.conversionRate, conversionDate: action.value.conversionDate, }) case actions.UPDATE_TOKENS: - return extend(metamaskState, { + return { + ...metamaskState, tokens: action.newTokens, - }) + } // metamask.send case actions.UPDATE_GAS_LIMIT: - return extend(metamaskState, { + return { + ...metamaskState, send: { ...metamaskState.send, gasLimit: action.value, }, - }) + } case actions.UPDATE_CUSTOM_NONCE: - return extend(metamaskState, { + return { + ...metamaskState, customNonceValue: action.value, - }) + } case actions.UPDATE_GAS_PRICE: - return extend(metamaskState, { + return { + ...metamaskState, send: { ...metamaskState.send, gasPrice: action.value, }, - }) + } case actions.TOGGLE_ACCOUNT_MENU: - return extend(metamaskState, { + return { + ...metamaskState, isAccountMenuOpen: !metamaskState.isAccountMenuOpen, - }) + } case actions.UPDATE_GAS_TOTAL: - return extend(metamaskState, { + return { + ...metamaskState, send: { ...metamaskState.send, gasTotal: action.value, }, - }) + } case actions.UPDATE_SEND_TOKEN_BALANCE: - return extend(metamaskState, { + return { + ...metamaskState, send: { ...metamaskState.send, tokenBalance: action.value, }, - }) + } case actions.UPDATE_SEND_HEX_DATA: - return extend(metamaskState, { + return { + ...metamaskState, send: { ...metamaskState.send, data: action.value, }, - }) + } case actions.UPDATE_SEND_TO: - return extend(metamaskState, { + return { + ...metamaskState, send: { ...metamaskState.send, to: action.value.to, toNickname: action.value.nickname, }, - }) + } case actions.UPDATE_SEND_AMOUNT: - return extend(metamaskState, { + return { + ...metamaskState, send: { ...metamaskState.send, amount: action.value, }, - }) + } case actions.UPDATE_MAX_MODE: - return extend(metamaskState, { + return { + ...metamaskState, send: { ...metamaskState.send, maxModeOn: action.value, }, - }) + } case actions.UPDATE_SEND: - return extend(metamaskState, { + return Object.assign(metamaskState, { send: { ...metamaskState.send, ...action.value, @@ -245,25 +263,28 @@ function reduceMetamask (state, action) { }) case actions.UPDATE_SEND_ENS_RESOLUTION: - return extend(metamaskState, { + return { + ...metamaskState, send: { ...metamaskState.send, ensResolution: action.payload, ensResolutionError: '', }, - }) + } case actions.UPDATE_SEND_ENS_RESOLUTION_ERROR: - return extend(metamaskState, { + return { + ...metamaskState, send: { ...metamaskState.send, ensResolution: null, ensResolutionError: action.payload, }, - }) + } case actions.CLEAR_SEND: - return extend(metamaskState, { + return { + ...metamaskState, send: { gasLimit: null, gasPrice: null, @@ -279,7 +300,7 @@ function reduceMetamask (state, action) { forceGasMin: null, toNickname: '', }, - }) + } case actions.UPDATE_TRANSACTION_PARAMS: const { id: txId, value } = action @@ -293,85 +314,99 @@ function reduceMetamask (state, action) { return tx }) - return extend(metamaskState, { + return { + ...metamaskState, selectedAddressTxList, - }) + } case actions.PAIR_UPDATE: const { value: { marketinfo: pairMarketInfo } } = action - return extend(metamaskState, { + return { + ...metamaskState, tokenExchangeRates: { ...metamaskState.tokenExchangeRates, [pairMarketInfo.pair]: pairMarketInfo, }, - }) + } case actions.SET_PARTICIPATE_IN_METAMETRICS: - return extend(metamaskState, { + return { + ...metamaskState, participateInMetaMetrics: action.value, - }) + } case actions.SET_METAMETRICS_SEND_COUNT: - return extend(metamaskState, { + return { + ...metamaskState, metaMetricsSendCount: action.value, - }) + } case actions.SET_USE_BLOCKIE: - return extend(metamaskState, { + return { + ...metamaskState, useBlockie: action.value, - }) + } case actions.UPDATE_FEATURE_FLAGS: - return extend(metamaskState, { + return { + ...metamaskState, featureFlags: action.value, - }) + } case actions.CLOSE_WELCOME_SCREEN: - return extend(metamaskState, { + return { + ...metamaskState, welcomeScreenSeen: true, - }) + } case actions.SET_CURRENT_LOCALE: - return extend(metamaskState, { + return { + ...metamaskState, currentLocale: action.value.locale, - }) + } case actions.SET_PENDING_TOKENS: - return extend(metamaskState, { + return { + ...metamaskState, pendingTokens: { ...action.payload }, - }) + } case actions.CLEAR_PENDING_TOKENS: { - return extend(metamaskState, { + return { + ...metamaskState, pendingTokens: {}, - }) + } } case actions.UPDATE_PREFERENCES: { - return extend(metamaskState, { + return { + ...metamaskState, preferences: { ...metamaskState.preferences, ...action.payload, }, - }) + } } case actions.COMPLETE_ONBOARDING: { - return extend(metamaskState, { + return { + ...metamaskState, completedOnboarding: true, - }) + } } case actions.SET_FIRST_TIME_FLOW_TYPE: { - return extend(metamaskState, { + return { + ...metamaskState, firstTimeFlowType: action.value, - }) + } } case actions.SET_NEXT_NONCE: { - return extend(metamaskState, { + return { + ...metamaskState, nextNonce: action.value, - }) + } } default: diff --git a/ui/app/ducks/send/send.duck.js b/ui/app/ducks/send/send.duck.js index 543b0a911..385b80dab 100644 --- a/ui/app/ducks/send/send.duck.js +++ b/ui/app/ducks/send/send.duck.js @@ -1,5 +1,3 @@ -import extend from 'xtend' - // Actions const OPEN_TO_DROPDOWN = 'metamask/send/OPEN_TO_DROPDOWN' const CLOSE_TO_DROPDOWN = 'metamask/send/CLOSE_TO_DROPDOWN' @@ -17,34 +15,39 @@ const initState = { // Reducer export default function reducer ({ send: sendState = initState }, action = {}) { - const newState = extend({}, sendState) + const newState = { ...sendState } switch (action.type) { case OPEN_TO_DROPDOWN: - return extend(newState, { + return { + ...newState, toDropdownOpen: true, - }) + } case CLOSE_TO_DROPDOWN: - return extend(newState, { + return { + ...newState, toDropdownOpen: false, - }) + } case UPDATE_SEND_ERRORS: - return extend(newState, { + return { + ...newState, errors: { ...newState.errors, ...action.value, }, - }) + } case SHOW_GAS_BUTTON_GROUP: - return extend(newState, { + return { + ...newState, gasButtonGroupShown: true, - }) + } case HIDE_GAS_BUTTON_GROUP: - return extend(newState, { + return { + ...newState, gasButtonGroupShown: false, - }) + } case RESET_SEND_STATE: - return extend({}, initState) + return { ...initState } default: return newState } diff --git a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js index 361895a5d..c3b576f25 100644 --- a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js +++ b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js @@ -2,13 +2,11 @@ import { connect } from 'react-redux' import { compose } from 'recompose' import ConfirmAddSuggestedToken from './confirm-add-suggested-token.component' import { withRouter } from 'react-router-dom' - -import extend from 'xtend' import { addToken, removeSuggestedTokens } from '../../store/actions' const mapStateToProps = ({ metamask }) => { const { pendingTokens, suggestedTokens } = metamask - const params = extend(pendingTokens, suggestedTokens) + const params = { ...pendingTokens, ...suggestedTokens } return { pendingTokens: params, From 2c3b1a0fe04eb5c7ef028b003a416b4b65418d6b Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 13 Jan 2020 13:32:54 -0330 Subject: [PATCH 116/689] Convert ConfirmTxScreen to an ES6 class (#7790) Co-authored-by: Mark Stacey --- ui/app/pages/confirm-transaction/conf-tx.js | 348 +++++++++++--------- 1 file changed, 184 insertions(+), 164 deletions(-) diff --git a/ui/app/pages/confirm-transaction/conf-tx.js b/ui/app/pages/confirm-transaction/conf-tx.js index 392b70d05..60ea55e99 100644 --- a/ui/app/pages/confirm-transaction/conf-tx.js +++ b/ui/app/pages/confirm-transaction/conf-tx.js @@ -1,5 +1,5 @@ +import PropTypes from 'prop-types' import React, { Component } from 'react' -import { inherits } from 'util' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' import { compose } from 'recompose' @@ -12,11 +12,6 @@ import SignatureRequestOriginal from '../../components/app/signature-request-ori import Loading from '../../components/ui/loading-screen' import { DEFAULT_ROUTE } from '../../helpers/constants/routes' -export default compose( - withRouter, - connect(mapStateToProps) -)(ConfirmTxScreen) - function mapStateToProps (state) { const { metamask } = state const { @@ -45,188 +40,213 @@ function mapStateToProps (state) { } } -inherits(ConfirmTxScreen, Component) -function ConfirmTxScreen () { - Component.call(this) -} - -ConfirmTxScreen.prototype.getUnapprovedMessagesTotal = function () { - const { - unapprovedMsgCount = 0, - unapprovedPersonalMsgCount = 0, - unapprovedTypedMessagesCount = 0, - } = this.props - - return unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount -} - -ConfirmTxScreen.prototype.componentDidMount = function () { - const { - unapprovedTxs = {}, - network, - send, - } = this.props - const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network) - - if (unconfTxList.length === 0 && !send.to && this.getUnapprovedMessagesTotal() === 0) { - this.props.history.push(DEFAULT_ROUTE) +class ConfirmTxScreen extends Component { + static propTypes = { + unapprovedMsgCount: PropTypes.number, + unapprovedPersonalMsgCount: PropTypes.number, + unapprovedTypedMessagesCount: PropTypes.number, + network: PropTypes.string, + index: PropTypes.number, + unapprovedTxs: PropTypes.object, + unapprovedMsgs: PropTypes.object, + unapprovedPersonalMsgs: PropTypes.object, + unapprovedTypedMessages: PropTypes.object, + match: PropTypes.shape({ + params: PropTypes.shape({ + id: PropTypes.number, + }), + }), + + selectedAddressTxList: PropTypes.array, + currentCurrency: PropTypes.string, + blockGasLimit: PropTypes.string, + history: PropTypes.object, + identities: PropTypes.object, + dispatch: PropTypes.func.isRequired, + send: PropTypes.shape({ + to: PropTypes.string, + }).isRequired, } -} -ConfirmTxScreen.prototype.componentDidUpdate = function (prevProps) { - const { - unapprovedTxs = {}, - network, - selectedAddressTxList, - send, - history, - match: { params: { id: transactionId } = {} }, - } = this.props - - let prevTx - - if (transactionId) { - prevTx = R.find(({ id }) => id + '' === transactionId)(selectedAddressTxList) - } else { - const { index: prevIndex, unapprovedTxs: prevUnapprovedTxs } = prevProps - const prevUnconfTxList = txHelper(prevUnapprovedTxs, {}, {}, {}, network) - const prevTxData = prevUnconfTxList[prevIndex] || {} - prevTx = selectedAddressTxList.find(({ id }) => id === prevTxData.id) || {} + getUnapprovedMessagesTotal () { + const { + unapprovedMsgCount = 0, + unapprovedPersonalMsgCount = 0, + unapprovedTypedMessagesCount = 0, + } = this.props + + return unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount } - const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network) + getTxData () { + const { + network, + index, + unapprovedTxs, + unapprovedMsgs, + unapprovedPersonalMsgs, + unapprovedTypedMessages, + match: { params: { id: transactionId } = {} }, + } = this.props + + const unconfTxList = txHelper( + unapprovedTxs, + unapprovedMsgs, + unapprovedPersonalMsgs, + unapprovedTypedMessages, + network + ) - if (prevTx && prevTx.status === 'dropped') { - this.props.dispatch(actions.showModal({ - name: 'TRANSACTION_CONFIRMED', - onSubmit: () => history.push(DEFAULT_ROUTE), - })) + log.info(`rendering a combined ${unconfTxList.length} unconf msgs & txs`) - return + return transactionId + ? R.find(({ id }) => id + '' === transactionId)(unconfTxList) + : unconfTxList[index] } - if (unconfTxList.length === 0 && !send.to && this.getUnapprovedMessagesTotal() === 0) { - this.props.history.push(DEFAULT_ROUTE) + signatureSelect (type, version) { + // Temporarily direct only v3 and v4 requests to new code. + if (type === 'eth_signTypedData' && (version === 'V3' || version === 'V4')) { + return SignatureRequest + } + + return SignatureRequestOriginal } -} -ConfirmTxScreen.prototype.getTxData = function () { - const { - network, - index, - unapprovedTxs, - unapprovedMsgs, - unapprovedPersonalMsgs, - unapprovedTypedMessages, - match: { params: { id: transactionId } = {} }, - } = this.props - - const unconfTxList = txHelper( - unapprovedTxs, - unapprovedMsgs, - unapprovedPersonalMsgs, - unapprovedTypedMessages, - network - ) - - log.info(`rendering a combined ${unconfTxList.length} unconf msgs & txs`) - - return transactionId - ? R.find(({ id }) => id + '' === transactionId)(unconfTxList) - : unconfTxList[index] -} + signMessage (msgData, event) { + log.info('conf-tx.js: signing message') + const params = msgData.msgParams + params.metamaskId = msgData.id + this.stopPropagation(event) + return this.props.dispatch(actions.signMsg(params)) + } -ConfirmTxScreen.prototype.signatureSelect = function (type, version) { - // Temporarily direct only v3 and v4 requests to new code. - if (type === 'eth_signTypedData' && (version === 'V3' || version === 'V4')) { - return SignatureRequest + stopPropagation (event) { + if (event.stopPropagation) { + event.stopPropagation() + } } - return SignatureRequestOriginal -} + signPersonalMessage (msgData, event) { + log.info('conf-tx.js: signing personal message') + const params = msgData.msgParams + params.metamaskId = msgData.id + this.stopPropagation(event) + return this.props.dispatch(actions.signPersonalMsg(params)) + } -ConfirmTxScreen.prototype.render = function () { - const { - currentCurrency, - blockGasLimit, - conversionRate, - } = this.props + signTypedMessage (msgData, event) { + log.info('conf-tx.js: signing typed message') + const params = msgData.msgParams + params.metamaskId = msgData.id + this.stopPropagation(event) + return this.props.dispatch(actions.signTypedMsg(params)) + } - const txData = this.getTxData() || {} - const { msgParams, type, msgParams: { version } } = txData - log.debug('msgParams detected, rendering pending msg') + cancelMessage (msgData, event) { + log.info('canceling message') + this.stopPropagation(event) + return this.props.dispatch(actions.cancelMsg(msgData)) + } - if (!msgParams) { - return ( - - ) + cancelPersonalMessage (msgData, event) { + log.info('canceling personal message') + this.stopPropagation(event) + return this.props.dispatch(actions.cancelPersonalMsg(msgData)) } - const SigComponent = this.signatureSelect(type, version) - return ( - - ) -} + cancelTypedMessage (msgData, event) { + log.info('canceling typed message') + this.stopPropagation(event) + return this.props.dispatch(actions.cancelTypedMsg(msgData)) + } -ConfirmTxScreen.prototype.signMessage = function (msgData, event) { - log.info('conf-tx.js: signing message') - const params = msgData.msgParams - params.metamaskId = msgData.id - this.stopPropagation(event) - return this.props.dispatch(actions.signMsg(params)) -} + componentDidMount () { + const { + unapprovedTxs = {}, + network, + send, + } = this.props + const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network) + + if (unconfTxList.length === 0 && !send.to && this.getUnapprovedMessagesTotal() === 0) { + this.props.history.push(DEFAULT_ROUTE) + } + } -ConfirmTxScreen.prototype.stopPropagation = function (event) { - if (event.stopPropagation) { - event.stopPropagation() + componentDidUpdate (prevProps) { + const { + unapprovedTxs = {}, + network, + selectedAddressTxList, + send, + history, + match: { params: { id: transactionId } = {} }, + } = this.props + + let prevTx + + if (transactionId) { + prevTx = R.find(({ id }) => id + '' === transactionId)(selectedAddressTxList) + } else { + const { index: prevIndex, unapprovedTxs: prevUnapprovedTxs } = prevProps + const prevUnconfTxList = txHelper(prevUnapprovedTxs, {}, {}, {}, network) + const prevTxData = prevUnconfTxList[prevIndex] || {} + prevTx = selectedAddressTxList.find(({ id }) => id === prevTxData.id) || {} + } + + const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network) + + if (prevTx && prevTx.status === 'dropped') { + this.props.dispatch(actions.showModal({ + name: 'TRANSACTION_CONFIRMED', + onSubmit: () => history.push(DEFAULT_ROUTE), + })) + + return + } + + if (unconfTxList.length === 0 && !send.to && this.getUnapprovedMessagesTotal() === 0) { + this.props.history.push(DEFAULT_ROUTE) + } } -} -ConfirmTxScreen.prototype.signPersonalMessage = function (msgData, event) { - log.info('conf-tx.js: signing personal message') - const params = msgData.msgParams - params.metamaskId = msgData.id - this.stopPropagation(event) - return this.props.dispatch(actions.signPersonalMsg(params)) -} + render () { + const { + currentCurrency, + blockGasLimit, + } = this.props -ConfirmTxScreen.prototype.signTypedMessage = function (msgData, event) { - log.info('conf-tx.js: signing typed message') - const params = msgData.msgParams - params.metamaskId = msgData.id - this.stopPropagation(event) - return this.props.dispatch(actions.signTypedMsg(params)) -} + const txData = this.getTxData() || {} + const { msgParams, type, msgParams: { version } } = txData + log.debug('msgParams detected, rendering pending msg') -ConfirmTxScreen.prototype.cancelMessage = function (msgData, event) { - log.info('canceling message') - this.stopPropagation(event) - return this.props.dispatch(actions.cancelMsg(msgData)) -} + if (!msgParams) { + return ( + + ) + } -ConfirmTxScreen.prototype.cancelPersonalMessage = function (msgData, event) { - log.info('canceling personal message') - this.stopPropagation(event) - return this.props.dispatch(actions.cancelPersonalMsg(msgData)) + const SigComponent = this.signatureSelect(type, version) + return ( + + ) + } } -ConfirmTxScreen.prototype.cancelTypedMessage = function (msgData, event) { - log.info('canceling typed message') - this.stopPropagation(event) - return this.props.dispatch(actions.cancelTypedMsg(msgData)) -} +export default compose( + withRouter, + connect(mapStateToProps) +)(ConfirmTxScreen) From b19481b2596316493b8f5e7d893fa7d516512b41 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 13 Jan 2020 13:42:38 -0330 Subject: [PATCH 117/689] Update COs for tx module (#7812) --- .github/CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 90936ceea..9c62ba36f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,5 +4,5 @@ package.json @danjm @whymarrh @Gudahtt yarn.lock @danjm @whymarrh @Gudahtt ui/ @danjm @whymarrh @Gudahtt -app/scripts/controllers/transactions @frankiebee -.circleci/scripts/deps-install.sh @kumavis @Gudahtt \ No newline at end of file +app/scripts/controllers/transactions @frankiebee @whymarrh +.circleci/scripts/deps-install.sh @kumavis @Gudahtt From ac01c5c89a58654f85f878af73a6412c097c86b9 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 13 Jan 2020 14:36:36 -0400 Subject: [PATCH 118/689] Consistent jsdoc syntax (#7755) * Specify type before parameter name Various JSDoc `@param` entries were specified as `name {type}` rather than `{type} name`. A couple of `@return` entries have been given types as well. * Use JSDoc optional syntax rather than Closure syntax * Use @returns rather than @return * Use consistent built-in type capitalization Primitive types are lower-case, and Object is upper-case. * Separate param/return description with a dash --- app/scripts/background.js | 10 +- app/scripts/contentscript.js | 14 +-- app/scripts/controllers/ab-test.js | 8 +- app/scripts/controllers/app-state.js | 8 +- app/scripts/controllers/balance.js | 10 +- app/scripts/controllers/cached-balances.js | 2 +- app/scripts/controllers/detect-tokens.js | 4 +- app/scripts/controllers/permissions/index.js | 6 +- app/scripts/controllers/preferences.js | 118 +++++++++--------- app/scripts/controllers/recent-blocks.js | 16 +-- app/scripts/controllers/transactions/index.js | 62 ++++----- .../lib/recipient-blacklist-checker.js | 4 +- .../lib/tx-state-history-helper.js | 12 +- .../controllers/transactions/lib/util.js | 12 +- .../transactions/pending-tx-tracker.js | 18 +-- .../controllers/transactions/tx-gas-utils.js | 22 ++-- .../transactions/tx-state-manager.js | 78 ++++++------ app/scripts/lib/account-tracker.js | 16 +-- app/scripts/lib/buy-eth-url.js | 4 +- app/scripts/lib/cleanErrorStack.js | 2 +- app/scripts/lib/extractEthjsErrorMessage.js | 4 +- app/scripts/lib/freezeGlobals.js | 2 +- .../lib/get-first-preferred-lang-code.js | 2 +- app/scripts/lib/getObjStructure.js | 10 +- app/scripts/lib/local-store.js | 14 +-- app/scripts/lib/message-manager.js | 44 +++---- app/scripts/lib/migrator/index.js | 2 +- app/scripts/lib/network-store.js | 6 +- app/scripts/lib/nodeify.js | 4 +- app/scripts/lib/notification-manager.js | 6 +- app/scripts/lib/pending-balance-calculator.js | 14 +-- app/scripts/lib/personal-message-manager.js | 44 +++---- app/scripts/lib/seed-phrase-verifier.js | 6 +- app/scripts/lib/stream-utils.js | 2 +- app/scripts/lib/typed-message-manager.js | 44 +++---- app/scripts/lib/util.js | 26 ++-- app/scripts/metamask-controller.js | 42 +++---- app/scripts/ui.js | 10 +- test/e2e/webdriver/chrome.js | 6 +- test/e2e/webdriver/driver.js | 4 +- test/e2e/webdriver/firefox.js | 14 +-- .../app/dropdowns/components/menu.js | 2 +- .../higher-order-components/i18n-provider.js | 6 +- ui/app/helpers/utils/conversion-util.js | 2 +- ui/app/helpers/utils/i18n-helper.js | 10 +- ui/app/helpers/utils/metametrics.util.js | 2 +- ui/app/helpers/utils/switch-direction.js | 2 +- ui/app/helpers/utils/util.js | 4 +- ui/app/store/actions.js | 6 +- 49 files changed, 383 insertions(+), 383 deletions(-) diff --git a/app/scripts/background.js b/app/scripts/background.js index 54914c140..2acb3ad66 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -150,7 +150,7 @@ const { submitMeshMetricsEntry } = setupMetamaskMeshMetrics() /** * Initializes the MetaMask controller, and sets up all platform configuration. - * @returns {Promise} Setup complete. + * @returns {Promise} - Setup complete. */ async function initialize () { const initState = await loadStateFromPersistence() @@ -166,7 +166,7 @@ async function initialize () { /** * Loads any stored data, prioritizing the latest storage strategy. * Migrates that data schema in case it was last loaded on an older version. - * @returns {Promise} Last data emitted from previous instance of MetaMask. + * @returns {Promise} - Last data emitted from previous instance of MetaMask. */ async function loadStateFromPersistence () { // migrations @@ -224,8 +224,8 @@ async function loadStateFromPersistence () { * Creates platform listeners for new Dapps/Contexts, and sets up their data connections to the controller. * * @param {Object} initState - The initial state to start the controller with, matches the state that is emitted from the controller. - * @param {String} initLangCode - The region code for the language preferred by the current user. - * @returns {Promise} After setup is complete. + * @param {string} initLangCode - The region code for the language preferred by the current user. + * @returns {Promise} - After setup is complete. */ function setupController (initState, initLangCode) { // @@ -289,7 +289,7 @@ function setupController (initState, initLangCode) { /** * Assigns the given state to the versioned object (with metadata), and returns that. * @param {Object} state - The state object as emitted by the MetaMaskController. - * @returns {VersionedData} The state object wrapped in an object that includes a metadata key. + * @returns {VersionedData} - The state object wrapped in an object that includes a metadata key. */ function versionifyData (state) { versionedData.data = state diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 4cc8a7409..8b2040b16 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -109,8 +109,8 @@ function forwardTrafficBetweenMuxers (channelName, muxA, muxB) { /** * Error handler for page to extension stream disconnections * - * @param {string} remoteLabel Remote stream name - * @param {Error} err Stream connection error + * @param {string} remoteLabel - Remote stream name + * @param {Error} err - Stream connection error */ function logStreamDisconnectWarning (remoteLabel, err) { let warningMsg = `MetamaskContentscript - lost connection to ${remoteLabel}` @@ -123,7 +123,7 @@ function logStreamDisconnectWarning (remoteLabel, err) { /** * Determines if the provider should be injected * - * @returns {boolean} {@code true} if the provider should be injected + * @returns {boolean} {@code true} - if the provider should be injected */ function shouldInjectProvider () { return doctypeCheck() && suffixCheck() && @@ -133,7 +133,7 @@ function shouldInjectProvider () { /** * Checks the doctype of the current document if it exists * - * @returns {boolean} {@code true} if the doctype is html or if none exists + * @returns {boolean} {@code true} - if the doctype is html or if none exists */ function doctypeCheck () { const doctype = window.document.doctype @@ -151,7 +151,7 @@ function doctypeCheck () { * that we should not inject the provider into. This check is indifferent of * query parameters in the location. * - * @returns {boolean} whether or not the extension of the current document is prohibited + * @returns {boolean} - whether or not the extension of the current document is prohibited */ function suffixCheck () { const prohibitedTypes = [ @@ -170,7 +170,7 @@ function suffixCheck () { /** * Checks the documentElement of the current document * - * @returns {boolean} {@code true} if the documentElement is an html node or if none exists + * @returns {boolean} {@code true} - if the documentElement is an html node or if none exists */ function documentElementCheck () { const documentElement = document.documentElement.nodeName @@ -183,7 +183,7 @@ function documentElementCheck () { /** * Checks if the current domain is blacklisted * - * @returns {boolean} {@code true} if the current domain is blacklisted + * @returns {boolean} {@code true} - if the current domain is blacklisted */ function blacklistedDomainCheck () { const blacklistedDomains = [ diff --git a/app/scripts/controllers/ab-test.js b/app/scripts/controllers/ab-test.js index e414fccf5..9d677236b 100644 --- a/app/scripts/controllers/ab-test.js +++ b/app/scripts/controllers/ab-test.js @@ -30,8 +30,8 @@ class ABTestController { /** * Returns the name of the test group to which the current user has been assigned - * @param {string} abTestKey the key of the a/b test - * @return {string} the name of the assigned test group + * @param {string} abTestKey - the key of the a/b test + * @returns {string} - the name of the assigned test group */ getAssignedABTestGroupName (abTestKey) { return this.store.getState().abTests[abTestKey] @@ -39,8 +39,8 @@ class ABTestController { /** * Returns a randomly chosen name of a test group from a given a/b test - * @param {string} abTestKey the key of the a/b test - * @return {string} the name of the randomly selected test group + * @param {string} abTestKey - the key of the a/b test + * @returns {string} - the name of the randomly selected test group * @private */ _getRandomizedTestGroupName (abTestKey) { diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index caa01b687..4fd1d651e 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -32,7 +32,7 @@ class AppStateController { /** * Sets the last active time to the current time - * @return {void} + * @returns {void} */ setLastActiveTime () { this._resetTimer() @@ -40,8 +40,8 @@ class AppStateController { /** * Sets the inactive timeout for the app - * @param {number} timeoutMinutes the inactive timeout in minutes - * @return {void} + * @param {number} timeoutMinutes - the inactive timeout in minutes + * @returns {void} * @private */ _setInactiveTimeout (timeoutMinutes) { @@ -58,7 +58,7 @@ class AppStateController { * If the {@code timeoutMinutes} state is falsy (i.e., zero) then a new * timer will not be created. * - * @return {void} + * @returns {void} * @private */ _resetTimer () { diff --git a/app/scripts/controllers/balance.js b/app/scripts/controllers/balance.js index 2f9c637de..0ade23b5b 100644 --- a/app/scripts/controllers/balance.js +++ b/app/scripts/controllers/balance.js @@ -8,7 +8,7 @@ class BalanceController { * Controller responsible for storing and updating an account's balance. * * @typedef {Object} BalanceController - * @param {Object} opts Initialize various properties of the class. + * @param {Object} opts - Initialize various properties of the class. * @property {string} address A base 16 hex string. The account address which has the balance managed by this * BalanceController. * @property {AccountTracker} accountTracker Stores and updates the users accounts @@ -47,7 +47,7 @@ class BalanceController { /** * Updates the ethBalance property to the current pending balance * - * @returns {Promise} Promises undefined + * @returns {Promise} - Promises undefined */ async updateBalance () { const balance = await this.balanceCalc.getBalance() @@ -87,7 +87,7 @@ class BalanceController { * Gets the balance, as a base 16 hex string, of the account at this BalanceController's current address. * If the current account has no balance, returns undefined. * - * @returns {Promise} Promises a BN with a value equal to the balance of the current account, or undefined + * @returns {Promise} - Promises a BN with a value equal to the balance of the current account, or undefined * if the current account has no balance * */ @@ -103,7 +103,7 @@ class BalanceController { * TransactionController passed to this BalanceController during construction. * * @private - * @returns {Promise} Promises an array of transaction objects. + * @returns {Promise} - Promises an array of transaction objects. * */ async _getPendingTransactions () { @@ -118,7 +118,7 @@ class BalanceController { /** * Validates that the passed options have all required properties. * - * @param {Object} opts The options object to validate + * @param {Object} opts - The options object to validate * @throws {string} Throw a custom error indicating that address, accountTracker, txController and blockTracker are * missing and at least one is required * diff --git a/app/scripts/controllers/cached-balances.js b/app/scripts/controllers/cached-balances.js index c41dc02cb..2ef1dd2ef 100644 --- a/app/scripts/controllers/cached-balances.js +++ b/app/scripts/controllers/cached-balances.js @@ -36,7 +36,7 @@ class CachedBalancesController { * Updates the cachedBalances property for the current network. Cached balances will be updated to those in the passed accounts * if balances in the passed accounts are truthy. * - * @param {Object} obj The the recently updated accounts object for the current network + * @param {Object} obj - The the recently updated accounts object for the current network * @returns {Promise} */ async updateCachedBalances ({ accounts }) { diff --git a/app/scripts/controllers/detect-tokens.js b/app/scripts/controllers/detect-tokens.js index 318bf59a6..9ecf3582f 100644 --- a/app/scripts/controllers/detect-tokens.js +++ b/app/scripts/controllers/detect-tokens.js @@ -62,8 +62,8 @@ class DetectTokensController { /** * Find if selectedAddress has tokens with contract in contractAddress. * - * @param {string} contractAddress Hex address of the token contract to explore. - * @returns {boolean} If balance is detected, token is added. + * @param {string} contractAddress - Hex address of the token contract to explore. + * @returns {boolean} - If balance is detected, token is added. * */ async detectTokenBalance (contractAddress) { diff --git a/app/scripts/controllers/permissions/index.js b/app/scripts/controllers/permissions/index.js index c104d66a0..5b7a1318f 100644 --- a/app/scripts/controllers/permissions/index.js +++ b/app/scripts/controllers/permissions/index.js @@ -134,7 +134,7 @@ export class PermissionsController { /** * User approval callback. The request can fail if the request is invalid. * - * @param {object} approved - the approved request object + * @param {Object} approved - the approved request object * @param {Array} accounts - The accounts to expose, if any */ async approvePermissionsRequest (approved, accounts) { @@ -167,7 +167,7 @@ export class PermissionsController { /** * User rejection callback. * - * @param {string} id the id of the rejected request + * @param {string} id - the id of the rejected request */ async rejectPermissionsRequest (id) { const approval = this.pendingApprovals[id] @@ -299,7 +299,7 @@ export class PermissionsController { /** * Removes the given permissions for the given domain. - * @param {object} domains { origin: [permissions] } + * @param {Object} domains { origin: [permissions] } */ removePermissionsFor (domains) { diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 9ed76f738..4db8df51f 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -10,7 +10,7 @@ class PreferencesController { /** * * @typedef {Object} PreferencesController - * @param {object} opts Overrides the defaults for the initial state of this.store + * @param {Object} opts - Overrides the defaults for the initial state of this.store * @property {object} store The stored object containing a users preferences, stored in local storage * @property {array} store.frequentRpcList A list of custom rpcs to provide the user * @property {string} store.currentAccountTab Indicates the selected tab in the ui @@ -79,7 +79,7 @@ class PreferencesController { /** * Sets the {@code forgottenPassword} state property - * @param {boolean} forgottenPassword whether or not the user has forgotten their password + * @param {boolean} forgottenPassword - whether or not the user has forgotten their password */ setPasswordForgotten (forgottenPassword) { this.store.updateState({ forgottenPassword }) @@ -88,7 +88,7 @@ class PreferencesController { /** * Setter for the `useBlockie` property * - * @param {boolean} val Whether or not the user prefers blockie indicators + * @param {boolean} val - Whether or not the user prefers blockie indicators * */ setUseBlockie (val) { @@ -98,7 +98,7 @@ class PreferencesController { /** * Setter for the `useNonceField` property * - * @param {boolean} val Whether or not the user prefers to set nonce + * @param {boolean} val - Whether or not the user prefers to set nonce * */ setUseNonceField (val) { @@ -108,8 +108,8 @@ class PreferencesController { /** * Setter for the `participateInMetaMetrics` property * - * @param {boolean} bool Whether or not the user wants to participate in MetaMetrics - * @returns {string|null} the string of the new metametrics id, or null if not set + * @param {boolean} bool - Whether or not the user wants to participate in MetaMetrics + * @returns {string|null} - the string of the new metametrics id, or null if not set * */ setParticipateInMetaMetrics (bool) { @@ -135,7 +135,7 @@ class PreferencesController { /** * Setter for the `firstTimeFlowType` property * - * @param {String} type Indicates the type of first time flow - create or import - the user wishes to follow + * @param {string} type - Indicates the type of first time flow - create or import - the user wishes to follow * */ setFirstTimeFlowType (type) { @@ -164,8 +164,8 @@ class PreferencesController { /** * Add new methodData to state, to avoid requesting this information again through Infura * - * @param {string} fourBytePrefix Four-byte method signature - * @param {string} methodData Corresponding data method + * @param {string} fourBytePrefix - Four-byte method signature + * @param {string} methodData - Corresponding data method */ addKnownMethodData (fourBytePrefix, methodData) { const knownMethodData = this.store.getState().knownMethodData @@ -208,7 +208,7 @@ class PreferencesController { /** * Setter for the `currentLocale` property * - * @param {string} key he preferred language locale key + * @param {string} key - he preferred language locale key * */ setCurrentLocale (key) { @@ -224,7 +224,7 @@ class PreferencesController { * Updates identities to only include specified addresses. Removes identities * not included in addresses array * - * @param {string[]} addresses An array of hex addresses + * @param {string[]} addresses - An array of hex addresses * */ setAddresses (addresses) { @@ -247,8 +247,8 @@ class PreferencesController { /** * Removes an address from state * - * @param {string} address A hex address - * @returns {string} the address that was removed + * @param {string} address - A hex address + * @returns {string} - the address that was removed */ removeAddress (address) { const identities = this.store.getState().identities @@ -273,7 +273,7 @@ class PreferencesController { /** * Adds addresses to the identities object without removing identities * - * @param {string[]} addresses An array of hex addresses + * @param {string[]} addresses - An array of hex addresses * */ addAddresses (addresses) { @@ -297,8 +297,8 @@ class PreferencesController { * Synchronizes identity entries with known accounts. * Removes any unknown identities, and returns the resulting selected address. * - * @param {Array} addresses known to the vault. - * @returns {Promise} selectedAddress the selected address. + * @param {Array} addresses - known to the vault. + * @returns {Promise} - selectedAddress the selected address. */ syncAddresses (addresses) { const { identities, lostIdentities } = this.store.getState() @@ -349,8 +349,8 @@ class PreferencesController { /** * Setter for the `selectedAddress` property * - * @param {string} _address A new hex address for an account - * @returns {Promise} Promise resolves with tokens + * @param {string} _address - A new hex address for an account + * @returns {Promise} - Promise resolves with tokens * */ setSelectedAddress (_address) { @@ -364,7 +364,7 @@ class PreferencesController { /** * Getter for the `selectedAddress` property * - * @returns {string} The hex address for the currently selected account + * @returns {string} - The hex address for the currently selected account * */ getSelectedAddress () { @@ -386,10 +386,10 @@ class PreferencesController { * Modifies the existing tokens array from the store. All objects in the tokens array array AddedToken objects. * @see AddedToken {@link AddedToken} * - * @param {string} rawAddress Hex address of the token contract. May or may not be a checksum address. - * @param {string} symbol The symbol of the token - * @param {number} decimals The number of decimals the token uses. - * @returns {Promise} Promises the new array of AddedToken objects. + * @param {string} rawAddress - Hex address of the token contract. May or may not be a checksum address. + * @param {string} symbol - The symbol of the token + * @param {number} decimals - The number of decimals the token uses. + * @returns {Promise} - Promises the new array of AddedToken objects. * */ async addToken (rawAddress, symbol, decimals, image) { @@ -415,8 +415,8 @@ class PreferencesController { /** * Removes a specified token from the tokens array. * - * @param {string} rawAddress Hex address of the token contract to remove. - * @returns {Promise} The new array of AddedToken objects + * @param {string} rawAddress - Hex address of the token contract to remove. + * @returns {Promise} - The new array of AddedToken objects * */ removeToken (rawAddress) { @@ -431,7 +431,7 @@ class PreferencesController { /** * A getter for the `tokens` property * - * @returns {array} The current array of AddedToken objects + * @returns {array} - The current array of AddedToken objects * */ getTokens () { @@ -440,9 +440,9 @@ class PreferencesController { /** * Sets a custom label for an account - * @param {string} account the account to set a label for - * @param {string} label the custom label for the account - * @return {Promise} + * @param {string} account - the account to set a label for + * @param {string} label - the custom label for the account + * @returns {Promise} */ setAccountLabel (account, label) { if (!account) { @@ -459,8 +459,8 @@ class PreferencesController { /** * Setter for the `currentAccountTab` property * - * @param {string} currentAccountTab Specifies the new tab to be marked as current - * @returns {Promise} Promise resolves with undefined + * @param {string} currentAccountTab - Specifies the new tab to be marked as current + * @returns {Promise} - Promise resolves with undefined * */ setCurrentAccountTab (currentAccountTab) { @@ -473,11 +473,11 @@ class PreferencesController { /** * updates custom RPC details * - * @param {string} url The RPC url to add to frequentRpcList. - * @param {number} chainId Optional chainId of the selected network. - * @param {string} ticker Optional ticker symbol of the selected network. - * @param {string} nickname Optional nickname of the selected network. - * @returns {Promise} Promise resolving to updated frequentRpcList. + * @param {string} url - The RPC url to add to frequentRpcList. + * @param {number} chainId - Optional chainId of the selected network. + * @param {string} ticker - Optional ticker symbol of the selected network. + * @param {string} nickname - Optional nickname of the selected network. + * @returns {Promise} - Promise resolving to updated frequentRpcList. * */ @@ -501,11 +501,11 @@ class PreferencesController { /** * Adds custom RPC url to state. * - * @param {string} url The RPC url to add to frequentRpcList. - * @param {number} chainId Optional chainId of the selected network. - * @param {string} ticker Optional ticker symbol of the selected network. - * @param {string} nickname Optional nickname of the selected network. - * @returns {Promise} Promise resolving to updated frequentRpcList. + * @param {string} url - The RPC url to add to frequentRpcList. + * @param {number} chainId - Optional chainId of the selected network. + * @param {string} ticker - Optional ticker symbol of the selected network. + * @param {string} nickname - Optional nickname of the selected network. + * @returns {Promise} - Promise resolving to updated frequentRpcList. * */ addToFrequentRpcList (url, chainId, ticker = 'ETH', nickname = '', rpcPrefs = {}) { @@ -530,8 +530,8 @@ class PreferencesController { /** * Removes custom RPC url from state. * - * @param {string} url The RPC url to remove from frequentRpcList. - * @returns {Promise} Promise resolving to updated frequentRpcList. + * @param {string} url - The RPC url to remove from frequentRpcList. + * @returns {Promise} - Promise resolving to updated frequentRpcList. * */ removeFromFrequentRpcList (url) { @@ -549,7 +549,7 @@ class PreferencesController { /** * Getter for the `frequentRpcListDetail` property. * - * @returns {array} An array of rpc urls. + * @returns {array} - An array of rpc urls. * */ getFrequentRpcListDetail () { @@ -559,9 +559,9 @@ class PreferencesController { /** * Updates the `featureFlags` property, which is an object. One property within that object will be set to a boolean. * - * @param {string} feature A key that corresponds to a UI feature. - * @param {boolean} activated Indicates whether or not the UI feature should be displayed - * @returns {Promise} Promises a new object; the updated featureFlags object. + * @param {string} feature - A key that corresponds to a UI feature. + * @param {boolean} activated - Indicates whether or not the UI feature should be displayed + * @returns {Promise} - Promises a new object; the updated featureFlags object. * */ setFeatureFlag (feature, activated) { @@ -579,9 +579,9 @@ class PreferencesController { /** * Updates the `preferences` property, which is an object. These are user-controlled features * found in the settings page. - * @param {string} preference The preference to enable or disable. - * @param {boolean} value Indicates whether or not the preference should be enabled or disabled. - * @returns {Promise} Promises a new object; the updated preferences object. + * @param {string} preference - The preference to enable or disable. + * @param {boolean} value - Indicates whether or not the preference should be enabled or disabled. + * @returns {Promise} - Promises a new object; the updated preferences object. */ setPreference (preference, value) { const currentPreferences = this.getPreferences() @@ -596,7 +596,7 @@ class PreferencesController { /** * A getter for the `preferences` property - * @returns {object} A key-boolean map of user-selected preferences. + * @returns {Object} - A key-boolean map of user-selected preferences. */ getPreferences () { return this.store.getState().preferences @@ -613,7 +613,7 @@ class PreferencesController { /** * A getter for the `ipfsGateway` property - * @returns {string} The current IPFS gateway domain + * @returns {string} - The current IPFS gateway domain */ getIpfsGateway () { return this.store.getState().ipfsGateway @@ -621,8 +621,8 @@ class PreferencesController { /** * A setter for the `ipfsGateway` property - * @param {string} domain The new IPFS gateway domain - * @returns {Promise} A promise of the update IPFS gateway domain + * @param {string} domain - The new IPFS gateway domain + * @returns {Promise} - A promise of the update IPFS gateway domain */ setIpfsGateway (domain) { this.store.updateState({ ipfsGateway: domain }) @@ -648,7 +648,7 @@ class PreferencesController { /** * Updates `accountTokens` and `tokens` of current account and network according to it. * - * @param {array} tokens Array of tokens to be updated. + * @param {array} tokens - Array of tokens to be updated. * */ _updateAccountTokens (tokens, assetImages) { @@ -660,7 +660,7 @@ class PreferencesController { /** * Updates `tokens` of current account and network. * - * @param {string} selectedAddress Account address to be updated with. + * @param {string} selectedAddress - Account address to be updated with. * */ _updateTokens (selectedAddress) { @@ -672,7 +672,7 @@ class PreferencesController { * A getter for `tokens` and `accountTokens` related states. * * @param {string} [selectedAddress] A new hex address for an account - * @returns {Object.} States to interact with tokens in `accountTokens` + * @returns {Object.} - States to interact with tokens in `accountTokens` * */ _getTokenRelatedStates (selectedAddress) { @@ -694,7 +694,7 @@ class PreferencesController { /** * Handle the suggestion of an ERC20 asset through `watchAsset` * * - * @param {Promise} promise Promise according to addition of ERC20 token + * @param {Promise} promise - Promise according to addition of ERC20 token * */ async _handleWatchAssetERC20 (options) { @@ -716,7 +716,7 @@ class PreferencesController { /** * Validates that the passed options for suggested token have all required properties. * - * @param {Object} opts The options object to validate + * @param {Object} opts - The options object to validate * @throws {string} Throw a custom error indicating that address, symbol and/or decimals * doesn't fulfill requirements * diff --git a/app/scripts/controllers/recent-blocks.js b/app/scripts/controllers/recent-blocks.js index ff7c38ea4..5a4ac39eb 100644 --- a/app/scripts/controllers/recent-blocks.js +++ b/app/scripts/controllers/recent-blocks.js @@ -16,7 +16,7 @@ class RecentBlocksController { * (indicating that there is a new block to process). * * @typedef {Object} RecentBlocksController - * @param {object} opts Contains objects necessary for tracking blocks and querying the blockchain + * @param {Object} opts - Contains objects necessary for tracking blocks and querying the blockchain * @param {BlockTracker} opts.blockTracker Contains objects necessary for tracking blocks and querying the blockchain * @param {BlockTracker} opts.provider The provider used to create a new EthQuery instance. * @property {BlockTracker} blockTracker Points to the passed BlockTracker. On RecentBlocksController construction, @@ -69,7 +69,7 @@ class RecentBlocksController { * Receives a new block and modifies it with this.mapTransactionsToPrices. Then adds that block to the recentBlocks * array in storage. If the recentBlocks array contains the maximum number of blocks, the oldest block is removed. * - * @param {object} newBlock The new block to modify and add to the recentBlocks array + * @param {Object} newBlock - The new block to modify and add to the recentBlocks array * */ async processBlock (newBlockNumberHex) { @@ -97,7 +97,7 @@ class RecentBlocksController { * * Unlike this.processBlock, backfillBlock adds the modified new block to the beginning of the recent block array. * - * @param {object} newBlock The new block to modify and add to the beginning of the recentBlocks array + * @param {Object} newBlock - The new block to modify and add to the beginning of the recentBlocks array * */ backfillBlock (newBlock) { @@ -116,8 +116,8 @@ class RecentBlocksController { * Receives a block and gets the gasPrice of each of its transactions. These gas prices are added to the block at a * new property, and the block's transactions are removed. * - * @param {object} newBlock The block to modify. It's transaction array will be replaced by a gasPrices array. - * @returns {object} The modified block. + * @param {Object} newBlock - The block to modify. It's transaction array will be replaced by a gasPrices array. + * @returns {Object} - The modified block. * */ mapTransactionsToPrices (newBlock) { @@ -138,7 +138,7 @@ class RecentBlocksController { * * Each iteration over the block numbers is delayed by 100 milliseconds. * - * @returns {Promise} Promises undefined + * @returns {Promise} - Promises undefined */ async backfill () { this.blockTracker.once('latest', async (blockNumberHex) => { @@ -164,8 +164,8 @@ class RecentBlocksController { /** * Uses EthQuery to get a block that has a given block number. * - * @param {number} number The number of the block to get - * @returns {Promise} Promises A block with the passed number + * @param {number} number - The number of the block to get + * @returns {Promise} - Promises A block with the passed number * */ async getBlockByNumber (number) { diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index adc504769..4b5ad2e9a 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -52,16 +52,16 @@ import { hexToBn, bnToHex, BnMultiplyByFraction } from '../../lib/util' @class - @param {object} - opts - @param {object} opts.initState - initial transaction list default is an empty array + @param {Object} - opts + @param {Object} opts.initState - initial transaction list default is an empty array @param {Object} opts.networkStore - an observable store for network number @param {Object} opts.blockTracker - An instance of eth-blocktracker @param {Object} opts.provider - A network provider. @param {Function} opts.signTransaction - function the signs an ethereumjs-tx - @param {object} opts.getPermittedAccounts - get accounts that an origin has permissions for + @param {Object} opts.getPermittedAccounts - get accounts that an origin has permissions for @param {Function} [opts.getGasPrice] - optional gas price calculator @param {Function} opts.signTransaction - ethTx signer that returns a rawTx - @param {Number} [opts.txHistoryLimit] - number *optional* for limiting how many transactions are in state + @param {number} [opts.txHistoryLimit] - number *optional* for limiting how many transactions are in state @param {Object} opts.preferencesStore */ @@ -125,7 +125,7 @@ class TransactionController extends EventEmitter { this._updatePendingTxsAfterFirstBlock() } - /** @returns {number} the chainId*/ + /** @returns {number} - the chainId*/ getChainId () { const networkState = this.networkStore.getState() const getChainId = parseInt(networkState) @@ -156,9 +156,9 @@ class TransactionController extends EventEmitter { /** * Add a new unapproved transaction to the pipeline * - * @returns {Promise} the hash of the transaction after being submitted to the network - * @param txParams {object} - txParams for the transaction - * @param opts {object} - with the key origin to put the origin on the txMeta + * @returns {Promise} - the hash of the transaction after being submitted to the network + * @param {Object} txParams - txParams for the transaction + * @param {Object} opts - with the key origin to put the origin on the txMeta */ async newUnapprovedTransaction (txParams, opts = {}) { @@ -256,8 +256,8 @@ class TransactionController extends EventEmitter { /** * Adds the tx gas defaults: gas && gasPrice - * @param txMeta {Object} - the txMeta object - * @returns {Promise} resolves with txMeta + * @param {Object} txMeta - the txMeta object + * @returns {Promise} - resolves with txMeta */ async addTxGasDefaults (txMeta, getCodeResponse) { const txParams = txMeta.txParams @@ -276,11 +276,11 @@ class TransactionController extends EventEmitter { /** Creates a new txMeta with the same txParams as the original to allow the user to resign the transaction with a higher gas values - @param originalTxId {number} - the id of the txMeta that + @param {number} originalTxId - the id of the txMeta that you want to attempt to retry - @param gasPrice {string=} - Optional gas price to be increased to use as the retry + @param {string} [gasPrice] - Optional gas price to be increased to use as the retry transaction's gas price - @return {txMeta} + @returns {txMeta} */ async retryTransaction (originalTxId, gasPrice) { @@ -311,7 +311,7 @@ class TransactionController extends EventEmitter { * new transaction contains the same nonce as the previous, is a basic ETH transfer of 0x value to * the sender's address, and has a higher gasPrice than that of the previous transaction. * @param {number} originalTxId - the id of the txMeta that you want to attempt to cancel - * @param {string=} customGasPrice - the hex value to use for the cancel transaction + * @param {string} [customGasPrice] - the hex value to use for the cancel transaction * @returns {txMeta} */ async createCancelTransaction (originalTxId, customGasPrice) { @@ -365,7 +365,7 @@ class TransactionController extends EventEmitter { /** updates the txMeta in the txStateManager - @param txMeta {Object} - the updated txMeta + @param {Object} txMeta - the updated txMeta */ async updateTransaction (txMeta) { this.txStateManager.updateTx(txMeta, 'confTx: user updated transaction') @@ -373,7 +373,7 @@ class TransactionController extends EventEmitter { /** updates and approves the transaction - @param txMeta {Object} + @param {Object} txMeta */ async updateAndApproveTransaction (txMeta) { this.txStateManager.updateTx(txMeta, 'confTx: user approved transaction') @@ -386,7 +386,7 @@ class TransactionController extends EventEmitter { signs the transaction publishes the transaction if any of these steps fails the tx status will be set to failed - @param txId {number} - the tx's Id + @param {number} txId - the tx's Id */ async approveTransaction (txId) { // TODO: Move this safety out of this function. @@ -447,8 +447,8 @@ class TransactionController extends EventEmitter { /** adds the chain id and signs the transaction and set the status to signed - @param txId {number} - the tx's Id - @returns - rawTx {string} + @param {number} txId - the tx's Id + @returns {string} - rawTx */ async signTransaction (txId) { const txMeta = this.txStateManager.getTx(txId) @@ -476,8 +476,8 @@ class TransactionController extends EventEmitter { /** publishes the raw tx and sets the txMeta to submitted - @param txId {number} - the tx's Id - @param rawTx {string} - the hex string of the serialized signed transaction + @param {number} txId - the tx's Id + @param {string} rawTx - the hex string of the serialized signed transaction @returns {Promise} */ async publishTransaction (txId, rawTx) { @@ -539,7 +539,7 @@ class TransactionController extends EventEmitter { /** Convenience method for the ui thats sets the transaction to rejected - @param txId {number} - the tx's Id + @param {number} txId - the tx's Id @returns {Promise} */ async cancelTransaction (txId) { @@ -548,8 +548,8 @@ class TransactionController extends EventEmitter { /** Sets the txHas on the txMeta - @param txId {number} - the tx's Id - @param txHash {string} - the hash for the txMeta + @param {number} txId - the tx's Id + @param {string} txHash - the hash for the txMeta */ setTxHash (txId, txHash) { // Add the tx hash to the persisted meta-tx object @@ -563,17 +563,17 @@ class TransactionController extends EventEmitter { // /** maps methods for convenience*/ _mapMethods () { - /** @returns the state in transaction controller */ + /** @returns {Object} - the state in transaction controller */ this.getState = () => this.memStore.getState() - /** @returns the network number stored in networkStore */ + /** @returns {string|number} - the network number stored in networkStore */ this.getNetwork = () => this.networkStore.getState() - /** @returns the user selected address */ + /** @returns {string} - the user selected address */ this.getSelectedAddress = () => this.preferencesStore.getState().selectedAddress - /** Returns an array of transactions whos status is unapproved */ + /** @returns {array} - transactions whos status is unapproved */ this.getUnapprovedTxCount = () => Object.keys(this.txStateManager.getUnapprovedTxList()).length /** - @returns a number that represents how many transactions have the status submitted - @param account {String} - hex prefixed account + @returns {number} - number of transactions that have the status submitted + @param {string} account - hex prefixed account */ this.getPendingTxCount = (account) => this.txStateManager.getPendingTransactions(account).length /** see txStateManager */ @@ -687,7 +687,7 @@ class TransactionController extends EventEmitter { Sets other txMeta statuses to dropped if the txMeta that has been confirmed has other transactions in the list have the same nonce - @param txId {Number} - the txId of the transaction that has been confirmed in a block + @param {number} txId - the txId of the transaction that has been confirmed in a block */ _markNonceDuplicatesDropped (txId) { // get the confirmed transactions nonce and from address diff --git a/app/scripts/controllers/transactions/lib/recipient-blacklist-checker.js b/app/scripts/controllers/transactions/lib/recipient-blacklist-checker.js index db10e0b3e..6b101fbc9 100644 --- a/app/scripts/controllers/transactions/lib/recipient-blacklist-checker.js +++ b/app/scripts/controllers/transactions/lib/recipient-blacklist-checker.js @@ -7,8 +7,8 @@ export default { /** * Checks if a specified account on a specified network is blacklisted. - @param networkId {number} - @param account {string} + @param {number} networkId + @param {string} account */ function checkAccount (networkId, account) { diff --git a/app/scripts/controllers/transactions/lib/tx-state-history-helper.js b/app/scripts/controllers/transactions/lib/tx-state-history-helper.js index 0d413ac4d..cd2e3e432 100644 --- a/app/scripts/controllers/transactions/lib/tx-state-history-helper.js +++ b/app/scripts/controllers/transactions/lib/tx-state-history-helper.js @@ -11,7 +11,7 @@ export default { /** converts non-initial history entries into diffs - @param longHistory {array} + @param {array} longHistory @returns {array} */ function migrateFromSnapshotsToDiffs (longHistory) { @@ -34,8 +34,8 @@ function migrateFromSnapshotsToDiffs (longHistory) { path (the key and if a nested object then each key will be seperated with a `/`) value with the first entry having the note and a timestamp when the change took place - @param previousState {object} - the previous state of the object - @param newState {object} - the update object + @param {Object} previousState - the previous state of the object + @param {Object} newState - the update object @param {string} [note] - a optional note for the state change @returns {array} */ @@ -54,7 +54,7 @@ function generateHistoryEntry (previousState, newState, note) { /** Recovers previous txMeta state obj - @returns {object} + @returns {Object} */ function replayHistory (_shortHistory) { const shortHistory = clone(_shortHistory) @@ -62,8 +62,8 @@ function replayHistory (_shortHistory) { } /** - @param txMeta {Object} - @returns {object} a clone object of the txMeta with out history + @param {Object} txMeta + @returns {Object} - a clone object of the txMeta with out history */ function snapshotFromTxMeta (txMeta) { // create txMeta snapshot for history diff --git a/app/scripts/controllers/transactions/lib/util.js b/app/scripts/controllers/transactions/lib/util.js index f2467180b..7df8e4764 100644 --- a/app/scripts/controllers/transactions/lib/util.js +++ b/app/scripts/controllers/transactions/lib/util.js @@ -14,8 +14,8 @@ const normalizers = { /** normalizes txParams - @param txParams {object} - @returns {object} normalized txParams + @param {Object} txParams + @returns {Object} - normalized txParams */ export function normalizeTxParams (txParams, LowerCase) { // apply only keys in the normalizers @@ -30,7 +30,7 @@ export function normalizeTxParams (txParams, LowerCase) { /** validates txParams - @param txParams {object} + @param {Object} txParams */ export function validateTxParams (txParams) { validateFrom(txParams) @@ -49,7 +49,7 @@ export function validateTxParams (txParams) { /** validates the from field in txParams - @param txParams {object} + @param {Object} txParams */ export function validateFrom (txParams) { if (!(typeof txParams.from === 'string')) { @@ -62,7 +62,7 @@ export function validateFrom (txParams) { /** validates the to field in txParams - @param txParams {object} + @param {Object} txParams */ export function validateRecipient (txParams) { if (txParams.to === '0x' || txParams.to === null) { @@ -78,7 +78,7 @@ export function validateRecipient (txParams) { } /** - @returns an {array} of states that can be considered final + @returns {array} - states that can be considered final */ export function getFinalStates () { return [ diff --git a/app/scripts/controllers/transactions/pending-tx-tracker.js b/app/scripts/controllers/transactions/pending-tx-tracker.js index fa2ef1de9..233fef697 100644 --- a/app/scripts/controllers/transactions/pending-tx-tracker.js +++ b/app/scripts/controllers/transactions/pending-tx-tracker.js @@ -9,7 +9,7 @@ import EthQuery from 'ethjs-query'
As well as continues broadcast while in the pending state
-@param config {object} - non optional configuration object consists of: +@param {Object} config - non optional configuration object consists of: @param {Object} config.provider - A network provider. @param {Object} config.nonceTracker see nonce tracker @param {function} config.getPendingTransactions a function for getting an array of transactions, @@ -50,7 +50,7 @@ class PendingTransactionTracker extends EventEmitter { /** Will resubmit any transactions who have not been confirmed in a block - @param block {object} - a block object + @param {Object} block - a block object @emits tx:warning */ resubmitPendingTxs (blockNumber) { @@ -95,10 +95,10 @@ class PendingTransactionTracker extends EventEmitter { /** resubmits the individual txMeta used in resubmitPendingTxs - @param txMeta {Object} - txMeta object - @param latestBlockNumber {string} - hex string for the latest block number + @param {Object} txMeta - txMeta object + @param {string} latestBlockNumber - hex string for the latest block number @emits tx:retry - @returns txHash {string} + @returns {string} - txHash */ async _resubmitTx (txMeta, latestBlockNumber) { if (!txMeta.firstRetryBlockNumber) { @@ -130,7 +130,7 @@ class PendingTransactionTracker extends EventEmitter { /** Ask the network for the transaction to see if it has been include in a block - @param txMeta {Object} - the txMeta object + @param {Object} txMeta - the txMeta object @emits tx:failed @emits tx:dropped @emits tx:confirmed @@ -209,8 +209,8 @@ class PendingTransactionTracker extends EventEmitter { } /** checks to see if if the tx's nonce has been used by another transaction - @param txMeta {Object} - txMeta object - @param transactionReceipt {Object} - transactionReceipt object + @param {Object} txMeta - txMeta object + @param {Object} transactionReceipt - transactionReceipt object @emits tx:dropped @returns {boolean} */ @@ -226,7 +226,7 @@ class PendingTransactionTracker extends EventEmitter { /** checks local txs to see if a confirmed txMeta has the same nonce - @param txMeta {Object} - txMeta object + @param {Object} txMeta - txMeta object @returns {boolean} */ diff --git a/app/scripts/controllers/transactions/tx-gas-utils.js b/app/scripts/controllers/transactions/tx-gas-utils.js index 9f5d5c8b6..51528867a 100644 --- a/app/scripts/controllers/transactions/tx-gas-utils.js +++ b/app/scripts/controllers/transactions/tx-gas-utils.js @@ -22,8 +22,8 @@ class TxGasUtil { } /** - @param txMeta {Object} - the txMeta object - @returns {object} the txMeta object with the gas written to the txParams + @param {Object} txMeta - the txMeta object + @returns {Object} - the txMeta object with the gas written to the txParams */ async analyzeGasUsage (txMeta, getCodeResponse) { const block = await this.query.getBlockByNumber('latest', false) @@ -50,9 +50,9 @@ class TxGasUtil { /** Estimates the tx's gas usage - @param txMeta {Object} - the txMeta object - @param blockGasLimitHex {string} - hex string of the block's gas limit - @returns {string} the estimated gas limit as a hex string + @param {Object} txMeta - the txMeta object + @param {string} blockGasLimitHex - hex string of the block's gas limit + @returns {string} - the estimated gas limit as a hex string */ async estimateTxGas (txMeta, blockGasLimitHex, getCodeResponse) { const txParams = txMeta.txParams @@ -104,9 +104,9 @@ class TxGasUtil { /** Writes the gas on the txParams in the txMeta - @param txMeta {Object} - the txMeta object to write to - @param blockGasLimitHex {string} - the block gas limit hex - @param estimatedGasHex {string} - the estimated gas hex + @param {Object} txMeta - the txMeta object to write to + @param {string} blockGasLimitHex - the block gas limit hex + @param {string} estimatedGasHex - the estimated gas hex */ setTxGas (txMeta, blockGasLimitHex, estimatedGasHex) { txMeta.estimatedGas = addHexPrefix(estimatedGasHex) @@ -128,9 +128,9 @@ class TxGasUtil { /** Adds a gas buffer with out exceeding the block gas limit - @param initialGasLimitHex {string} - the initial gas limit to add the buffer too - @param blockGasLimitHex {string} - the block gas limit - @returns {string} the buffered gas limit as a hex string + @param {string} initialGasLimitHex - the initial gas limit to add the buffer too + @param {string} blockGasLimitHex - the block gas limit + @returns {string} - the buffered gas limit as a hex string */ addGasBuffer (initialGasLimitHex, blockGasLimitHex) { const initialGasLimitBn = hexToBn(initialGasLimitHex) diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index 379d67d47..7fce8f97a 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -20,8 +20,8 @@ import { getFinalStates, normalizeTxParams } from './lib/util'
- `'confirmed'` the tx has been included in a block.
- `'failed'` the tx failed for some reason, included on tx data.
- `'dropped'` the tx nonce was already used - @param opts {object} - @param {object} [opts.initState={ transactions: [] }] initial transactions list with the key transaction {array} + @param {Object} opts + @param {Object} [opts.initState={ transactions: [] }] initial transactions list with the key transaction {array} @param {number} [opts.txHistoryLimit] limit for how many finished transactions can hang around in state @param {function} opts.getNetwork return network number @@ -40,8 +40,8 @@ class TransactionStateManager extends EventEmitter { } /** - @param opts {object} - the object to use when overwriting defaults - @returns {txMeta} the default txMeta object + @param {Object} opts - the object to use when overwriting defaults + @returns {txMeta} - the default txMeta object */ generateTxMeta (opts) { const netId = this.getNetwork() @@ -58,7 +58,7 @@ class TransactionStateManager extends EventEmitter { } /** - @returns {array} of txMetas that have been filtered for only the current network + @returns {array} - of txMetas that have been filtered for only the current network */ getTxList () { const network = this.getNetwork() @@ -67,14 +67,14 @@ class TransactionStateManager extends EventEmitter { } /** - @returns {array} of all the txMetas in store + @returns {array} - of all the txMetas in store */ getFullTxList () { return this.store.getState().transactions } /** - @returns {array} the tx list whos status is unapproved + @returns {array} - the tx list whos status is unapproved */ getUnapprovedTxList () { const txList = this.getTxsByMetaData('status', 'unapproved') @@ -86,7 +86,7 @@ class TransactionStateManager extends EventEmitter { /** @param [address] {string} - hex prefixed address to sort the txMetas for [optional] - @returns {array} the tx list whos status is approved if no address is provide + @returns {array} - the tx list whos status is approved if no address is provide returns all txMetas who's status is approved for the current network */ getApprovedTransactions (address) { @@ -99,7 +99,7 @@ class TransactionStateManager extends EventEmitter { /** @param [address] {string} - hex prefixed address to sort the txMetas for [optional] - @returns {array} the tx list whos status is submitted if no address is provide + @returns {array} - the tx list whos status is submitted if no address is provide returns all txMetas who's status is submitted for the current network */ getPendingTransactions (address) { @@ -112,7 +112,7 @@ class TransactionStateManager extends EventEmitter { /** @param [address] {string} - hex prefixed address to sort the txMetas for [optional] - @returns {array} the tx list whos status is confirmed if no address is provide + @returns {array} - the tx list whos status is confirmed if no address is provide returns all txMetas who's status is confirmed for the current network */ getConfirmedTransactions (address) { @@ -129,8 +129,8 @@ class TransactionStateManager extends EventEmitter { is in its final state it will allso add the key `history` to the txMeta with the snap shot of the original object - @param txMeta {Object} - @returns {object} the txMeta + @param {Object} txMeta + @returns {Object} - the txMeta */ addTx (txMeta) { // normalize and validate txParams if present @@ -177,8 +177,8 @@ class TransactionStateManager extends EventEmitter { return txMeta } /** - @param txId {number} - @returns {object} the txMeta who matches the given id if none found + @param {number} txId + @returns {Object} - the txMeta who matches the given id if none found for the network returns undefined */ getTx (txId) { @@ -188,8 +188,8 @@ class TransactionStateManager extends EventEmitter { /** updates the txMeta in the list and adds a history entry - @param txMeta {Object} - the txMeta to update - @param [note] {string} - a note about the update for history + @param {Object} txMeta - the txMeta to update + @param {string} [note] - a note about the update for history */ updateTx (txMeta, note) { // normalize and validate txParams if present @@ -217,8 +217,8 @@ class TransactionStateManager extends EventEmitter { /** merges txParams obj onto txMeta.txParams use extend to ensure that all fields are filled - @param txId {number} - the id of the txMeta - @param txParams {object} - the updated txParams + @param {number} txId - the id of the txMeta + @param {Object} txParams - the updated txParams */ updateTxParams (txId, txParams) { const txMeta = this.getTx(txId) @@ -228,7 +228,7 @@ class TransactionStateManager extends EventEmitter { /** * normalize and validate txParams members - * @param txParams {object} - txParams + * @param {Object} txParams - txParams */ normalizeAndValidateTxParams (txParams) { if (typeof txParams.data === 'undefined') { @@ -241,7 +241,7 @@ class TransactionStateManager extends EventEmitter { /** validates txParams members by type - @param txParams {object} - txParams to validate + @param {Object} txParams - txParams to validate */ validateTxParams (txParams) { Object.keys(txParams).forEach((key) => { @@ -263,7 +263,7 @@ class TransactionStateManager extends EventEmitter { } /** - @param opts {object} - an object of fields to search for eg:
+ @param {Object} opts - an object of fields to search for eg:
let thingsToLookFor = {
to: '0x0..',
from: '0x0..',
@@ -273,7 +273,7 @@ class TransactionStateManager extends EventEmitter { optionally the values of the keys can be functions for situations like where you want all but one status. @param [initialList=this.getTxList()] - @returns a {array} of txMeta with all + @returns {array} - array of txMeta with all options matching */ /* @@ -299,11 +299,11 @@ class TransactionStateManager extends EventEmitter { } /** - @param key {string} - the key to check + @param {string} key - the key to check @param value - the value your looking for can also be a function that returns a bool @param [txList=this.getTxList()] {array} - the list to search. default is the txList from txStateManager#getTxList - @returns {array} a list of txMetas who matches the search params + @returns {array} - a list of txMetas who matches the search params */ getTxsByMetaData (key, value, txList = this.getTxList()) { const filter = typeof value === 'function' ? value : (v) => v === value @@ -320,8 +320,8 @@ class TransactionStateManager extends EventEmitter { // get::set status /** - @param txId {number} - the txMeta Id - @return {string} the status of the tx. + @param {number} txId - the txMeta Id + @returns {string} - the status of the tx. */ getTxStatus (txId) { const txMeta = this.getTx(txId) @@ -330,7 +330,7 @@ class TransactionStateManager extends EventEmitter { /** should update the status of the tx to 'rejected'. - @param txId {number} - the txMeta Id + @param {number} txId - the txMeta Id */ setTxStatusRejected (txId) { this._setTxStatus(txId, 'rejected') @@ -339,14 +339,14 @@ class TransactionStateManager extends EventEmitter { /** should update the status of the tx to 'unapproved'. - @param txId {number} - the txMeta Id + @param {number} txId - the txMeta Id */ setTxStatusUnapproved (txId) { this._setTxStatus(txId, 'unapproved') } /** should update the status of the tx to 'approved'. - @param txId {number} - the txMeta Id + @param {number} txId - the txMeta Id */ setTxStatusApproved (txId) { this._setTxStatus(txId, 'approved') @@ -354,7 +354,7 @@ class TransactionStateManager extends EventEmitter { /** should update the status of the tx to 'signed'. - @param txId {number} - the txMeta Id + @param {number} txId - the txMeta Id */ setTxStatusSigned (txId) { this._setTxStatus(txId, 'signed') @@ -363,7 +363,7 @@ class TransactionStateManager extends EventEmitter { /** should update the status of the tx to 'submitted'. and add a time stamp for when it was called - @param txId {number} - the txMeta Id + @param {number} txId - the txMeta Id */ setTxStatusSubmitted (txId) { const txMeta = this.getTx(txId) @@ -374,7 +374,7 @@ class TransactionStateManager extends EventEmitter { /** should update the status of the tx to 'confirmed'. - @param txId {number} - the txMeta Id + @param {number} txId - the txMeta Id */ setTxStatusConfirmed (txId) { this._setTxStatus(txId, 'confirmed') @@ -382,7 +382,7 @@ class TransactionStateManager extends EventEmitter { /** should update the status of the tx to 'dropped'. - @param txId {number} - the txMeta Id + @param {number} txId - the txMeta Id */ setTxStatusDropped (txId) { this._setTxStatus(txId, 'dropped') @@ -392,8 +392,8 @@ class TransactionStateManager extends EventEmitter { /** should update the status of the tx to 'failed'. and put the error on the txMeta - @param txId {number} - the txMeta Id - @param err {erroObject} - error object + @param {number} txId - the txMeta Id + @param {erroObject} err - error object */ setTxStatusFailed (txId, err) { const error = !err ? new Error('Internal metamask failure') : err @@ -411,7 +411,7 @@ class TransactionStateManager extends EventEmitter { /** Removes transaction from the given address for the current network from the txList - @param address {string} - hex string of the from address on the txParams to remove + @param {string} address - hex string of the from address on the txParams to remove */ wipeTransactions (address) { // network only tx @@ -440,8 +440,8 @@ class TransactionStateManager extends EventEmitter { // - `'dropped'` the tx nonce was already used /** - @param txId {number} - the txMeta Id - @param status {string} - the status to set on the txMeta + @param {number} txId - the txMeta Id + @param {string} status - the status to set on the txMeta @emits tx:status-update - passes txId and status @emits ${txMeta.id}:finished - if it is a finished state. Passes the txMeta @emits update:badge @@ -471,7 +471,7 @@ class TransactionStateManager extends EventEmitter { /** Saves the new/updated txList. - @param transactions {array} - the list of transactions to save + @param {array} transactions - the list of transactions to save */ // Function is intended only for internal use _saveTxList (transactions) { diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js index 6c424ea37..c18807479 100644 --- a/app/scripts/lib/account-tracker.js +++ b/app/scripts/lib/account-tracker.js @@ -34,7 +34,7 @@ class AccountTracker { * It also tracks transaction hashes, and checks their inclusion status on each new block. * * @typedef {Object} AccountTracker - * @param {Object} opts Initialize various properties of the class. + * @param {Object} opts - Initialize various properties of the class. * @property {Object} store The stored object containing all accounts to track, as well as the current block's gas limit. * @property {Object} store.accounts The accounts currently stored in this AccountTracker * @property {string} store.currentBlockGasLimit A hex string indicating the gas limit of the current block @@ -88,7 +88,7 @@ class AccountTracker { * Once this AccountTracker's accounts are up to date with those referenced by the passed addresses, each * of these accounts are given an updated balance via EthQuery. * - * @param {array} address The array of hex addresses for accounts with which this AccountTracker's accounts should be + * @param {array} address - The array of hex addresses for accounts with which this AccountTracker's accounts should be * in sync * */ @@ -118,7 +118,7 @@ class AccountTracker { * Adds new addresses to track the balances of * given a balance as long this._currentBlockNumber is defined. * - * @param {array} addresses An array of hex addresses of new accounts to track + * @param {array} addresses - An array of hex addresses of new accounts to track * */ addAccounts (addresses) { @@ -139,7 +139,7 @@ class AccountTracker { /** * Removes accounts from being tracked * - * @param {array} an array of hex addresses to stop tracking + * @param {array} an - array of hex addresses to stop tracking * */ removeAccount (addresses) { @@ -157,7 +157,7 @@ class AccountTracker { * via EthQuery * * @private - * @param {number} blockNumber the block number to update to. + * @param {number} blockNumber - the block number to update to. * @fires 'block' The updated state, if all account updates are successful * */ @@ -183,7 +183,7 @@ class AccountTracker { * balanceChecker is deployed on main eth (test)nets and requires a single call * for all other networks, calls this._updateAccount for each account in this.store * - * @returns {Promise} after all account balances updated + * @returns {Promise} - after all account balances updated * */ async _updateAccounts () { @@ -217,8 +217,8 @@ class AccountTracker { * Updates the current balance of an account. * * @private - * @param {string} address A hex address of a the account to be updated - * @returns {Promise} after the account balance is updated + * @param {string} address - A hex address of a the account to be updated + * @returns {Promise} - after the account balance is updated * */ async _updateAccount (address) { diff --git a/app/scripts/lib/buy-eth-url.js b/app/scripts/lib/buy-eth-url.js index 2b4f77840..2a924ecff 100644 --- a/app/scripts/lib/buy-eth-url.js +++ b/app/scripts/lib/buy-eth-url.js @@ -3,11 +3,11 @@ export default getBuyEthUrl /** * Gives the caller a url at which the user can acquire eth, depending on the network they are in * - * @param {object} opts Options required to determine the correct url + * @param {Object} opts - Options required to determine the correct url * @param {string} opts.network The network for which to return a url * @param {string} opts.amount The amount of ETH to buy on coinbase. Only relevant if network === '1'. * @param {string} opts.address The address the bought ETH should be sent to. Only relevant if network === '1'. - * @returns {string|undefined} The url at which the user can access ETH, while in the given network. If the passed + * @returns {string|undefined} - The url at which the user can access ETH, while in the given network. If the passed * network does not match any of the specified cases, or if no network is given, returns undefined. * */ diff --git a/app/scripts/lib/cleanErrorStack.js b/app/scripts/lib/cleanErrorStack.js index ece2ce87c..daa5719bb 100644 --- a/app/scripts/lib/cleanErrorStack.js +++ b/app/scripts/lib/cleanErrorStack.js @@ -1,7 +1,7 @@ /** * Returns error without stack trace for better UI display * @param {Error} err - error - * @returns {Error} Error with clean stack trace. + * @returns {Error} - Error with clean stack trace. */ function cleanErrorStack (err) { let name = err.name diff --git a/app/scripts/lib/extractEthjsErrorMessage.js b/app/scripts/lib/extractEthjsErrorMessage.js index 6725db622..d727888ca 100644 --- a/app/scripts/lib/extractEthjsErrorMessage.js +++ b/app/scripts/lib/extractEthjsErrorMessage.js @@ -8,8 +8,8 @@ export default extractEthjsErrorMessage * Extracts the important part of an ethjs-rpc error message. If the passed error is not an isEthjsRpcError, the error * is returned unchanged. * - * @param {string} errorMessage The error message to parse - * @returns {string} Returns an error message, either the same as was passed, or the ending message portion of an isEthjsRpcError + * @param {string} errorMessage - The error message to parse + * @returns {string} - Returns an error message, either the same as was passed, or the ending message portion of an isEthjsRpcError * * @example * // returns 'Transaction Failed: replacement transaction underpriced' diff --git a/app/scripts/lib/freezeGlobals.js b/app/scripts/lib/freezeGlobals.js index 4cc1e0d7b..6599088d6 100644 --- a/app/scripts/lib/freezeGlobals.js +++ b/app/scripts/lib/freezeGlobals.js @@ -20,7 +20,7 @@ if ( * value is completely immutable. It is, however, better than nothing. * * @param {Object} target - The target object to freeze a property on. - * @param {String} key - The key to freeze. + * @param {string} key - The key to freeze. * @param {any} [value] - The value to freeze, if different from the existing value on the target. * @param {boolean} [enumerable=true] - If given a value, whether the property is enumerable. */ diff --git a/app/scripts/lib/get-first-preferred-lang-code.js b/app/scripts/lib/get-first-preferred-lang-code.js index 7e18f370e..3e052bd09 100644 --- a/app/scripts/lib/get-first-preferred-lang-code.js +++ b/app/scripts/lib/get-first-preferred-lang-code.js @@ -19,7 +19,7 @@ allLocales.forEach(locale => { * Returns a preferred language code, based on settings within the user's browser. If we have no translations for the * users preferred locales, 'en' is returned. * - * @returns {Promise} Promises a locale code, either one from the user's preferred list that we have a translation for, or 'en' + * @returns {Promise} - Promises a locale code, either one from the user's preferred list that we have a translation for, or 'en' * */ async function getFirstPreferredLangCode () { diff --git a/app/scripts/lib/getObjStructure.js b/app/scripts/lib/getObjStructure.js index fb4c74370..8cf620119 100644 --- a/app/scripts/lib/getObjStructure.js +++ b/app/scripts/lib/getObjStructure.js @@ -18,8 +18,8 @@ export default getObjStructure * Creates an object that represents the structure of the given object. It replaces all values with the result of their * type. * - * @param {object} obj The object for which a 'structure' will be returned. Usually a plain object and not a class. - * @returns {object} The "mapped" version of a deep clone of the passed object, with each non-object property value + * @param {Object} obj - The object for which a 'structure' will be returned. Usually a plain object and not a class. + * @returns {Object} - The "mapped" version of a deep clone of the passed object, with each non-object property value * replaced with the javascript type of that value. * */ @@ -34,9 +34,9 @@ function getObjStructure (obj) { * Modifies all the properties and deeply nested of a passed object. Iterates recursively over all nested objects and * their properties, and covers the entire depth of the object. At each property value which is not an object is modified. * - * @param {object} target The object to modify - * @param {Function} visit The modifier to apply to each non-object property value - * @returns {object} The modified object + * @param {Object} target - The object to modify + * @param {Function} visit - The modifier to apply to each non-object property value + * @returns {Object} - The modified object */ function deepMap (target = {}, visit) { Object.entries(target).forEach(([key, value]) => { diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index 56c16aed9..a0c0a667a 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -18,7 +18,7 @@ export default class ExtensionStore { /** * Returns all of the keys currently saved - * @return {Promise<*>} + * @returns {Promise<*>} */ async get () { if (!this.isSupported) { @@ -36,8 +36,8 @@ export default class ExtensionStore { /** * Sets the key in local state - * @param {object} state - The state to set - * @return {Promise} + * @param {Object} state - The state to set + * @returns {Promise} */ async set (state) { return this._set(state) @@ -46,7 +46,7 @@ export default class ExtensionStore { /** * Returns all of the keys currently saved * @private - * @return {object} the key-value map from local storage + * @returns {Object} - the key-value map from local storage */ _get () { const local = extension.storage.local @@ -64,8 +64,8 @@ export default class ExtensionStore { /** * Sets the key in local state - * @param {object} obj - The key to set - * @return {Promise} + * @param {Object} obj - The key to set + * @returns {Promise} * @private */ _set (obj) { @@ -85,7 +85,7 @@ export default class ExtensionStore { /** * Returns whether or not the given object contains no keys - * @param {object} obj - The object to check + * @param {Object} obj - The object to check * @returns {boolean} */ function isEmpty (obj) { diff --git a/app/scripts/lib/message-manager.js b/app/scripts/lib/message-manager.js index ad019aa3c..9af28663e 100644 --- a/app/scripts/lib/message-manager.js +++ b/app/scripts/lib/message-manager.js @@ -47,7 +47,7 @@ export default class MessageManager extends EventEmitter { /** * A getter for the number of 'unapproved' Messages in this.messages * - * @returns {number} The number of 'unapproved' Messages in this.messages + * @returns {number} - The number of 'unapproved' Messages in this.messages * */ get unapprovedMsgCount () { @@ -57,7 +57,7 @@ export default class MessageManager extends EventEmitter { /** * A getter for the 'unapproved' Messages in this.messages * - * @returns {Object} An index of Message ids to Messages, for all 'unapproved' Messages in this.messages + * @returns {Object} - An index of Message ids to Messages, for all 'unapproved' Messages in this.messages * */ getUnapprovedMsgs () { @@ -71,9 +71,9 @@ export default class MessageManager extends EventEmitter { * Creates a new Message with an 'unapproved' status using the passed msgParams. this.addMsg is called to add the * new Message to this.messages, and to save the unapproved Messages from that list to this.memStore. * - * @param {Object} msgParams The params for the eth_sign call to be made after the message is approved. + * @param {Object} msgParams - The params for the eth_sign call to be made after the message is approved. * @param {Object} req (optional) The original request object possibly containing the origin - * @returns {promise} after signature has been + * @returns {promise} - after signature has been * */ addUnapprovedMessageAsync (msgParams, req) { @@ -97,9 +97,9 @@ export default class MessageManager extends EventEmitter { * Creates a new Message with an 'unapproved' status using the passed msgParams. this.addMsg is called to add the * new Message to this.messages, and to save the unapproved Messages from that list to this.memStore. * - * @param {Object} msgParams The params for the eth_sign call to be made after the message is approved. + * @param {Object} msgParams - The params for the eth_sign call to be made after the message is approved. * @param {Object} req (optional) The original request object where the origin may be specificied - * @returns {number} The id of the newly created message. + * @returns {number} - The id of the newly created message. * */ addUnapprovedMessage (msgParams, req) { @@ -129,7 +129,7 @@ export default class MessageManager extends EventEmitter { * Adds a passed Message to this.messages, and calls this._saveMsgList() to save the unapproved Messages from that * list to this.memStore. * - * @param {Message} msg The Message to add to this.messages + * @param {Message} msg - The Message to add to this.messages * */ addMsg (msg) { @@ -140,8 +140,8 @@ export default class MessageManager extends EventEmitter { /** * Returns a specified Message. * - * @param {number} msgId The id of the Message to get - * @returns {Message|undefined} The Message with the id that matches the passed msgId, or undefined if no Message has that id. + * @param {number} msgId - The id of the Message to get + * @returns {Message|undefined} - The Message with the id that matches the passed msgId, or undefined if no Message has that id. * */ getMsg (msgId) { @@ -152,9 +152,9 @@ export default class MessageManager extends EventEmitter { * Approves a Message. Sets the message status via a call to this.setMsgStatusApproved, and returns a promise with * any the message params modified for proper signing. * - * @param {Object} msgParams The msgParams to be used when eth_sign is called, plus data added by MetaMask. + * @param {Object} msgParams - The msgParams to be used when eth_sign is called, plus data added by MetaMask. * @param {Object} msgParams.metamaskId Added to msgParams for tracking and identification within MetaMask. - * @returns {Promise} Promises the msgParams object with metamaskId removed. + * @returns {Promise} - Promises the msgParams object with metamaskId removed. * */ approveMessage (msgParams) { @@ -165,7 +165,7 @@ export default class MessageManager extends EventEmitter { /** * Sets a Message status to 'approved' via a call to this._setMsgStatus. * - * @param {number} msgId The id of the Message to approve. + * @param {number} msgId - The id of the Message to approve. * */ setMsgStatusApproved (msgId) { @@ -176,8 +176,8 @@ export default class MessageManager extends EventEmitter { * Sets a Message status to 'signed' via a call to this._setMsgStatus and updates that Message in this.messages by * adding the raw signature data of the signature request to the Message * - * @param {number} msgId The id of the Message to sign. - * @param {buffer} rawSig The raw data of the signature request + * @param {number} msgId - The id of the Message to sign. + * @param {buffer} rawSig - The raw data of the signature request * */ setMsgStatusSigned (msgId, rawSig) { @@ -190,8 +190,8 @@ export default class MessageManager extends EventEmitter { /** * Removes the metamaskId property from passed msgParams and returns a promise which resolves the updated msgParams * - * @param {Object} msgParams The msgParams to modify - * @returns {Promise} Promises the msgParams with the metamaskId property removed + * @param {Object} msgParams - The msgParams to modify + * @returns {Promise} - Promises the msgParams with the metamaskId property removed * */ prepMsgForSigning (msgParams) { @@ -202,7 +202,7 @@ export default class MessageManager extends EventEmitter { /** * Sets a Message status to 'rejected' via a call to this._setMsgStatus. * - * @param {number} msgId The id of the Message to reject. + * @param {number} msgId - The id of the Message to reject. * */ rejectMsg (msgId) { @@ -213,8 +213,8 @@ export default class MessageManager extends EventEmitter { * Updates the status of a Message in this.messages via a call to this._updateMsg * * @private - * @param {number} msgId The id of the Message to update. - * @param {string} status The new status of the Message. + * @param {number} msgId - The id of the Message to update. + * @param {string} status - The new status of the Message. * @throws A 'MessageManager - Message not found for id: "${msgId}".' if there is no Message in this.messages with an * id equal to the passed msgId * @fires An event with a name equal to `${msgId}:${status}`. The Message is also fired. @@ -239,7 +239,7 @@ export default class MessageManager extends EventEmitter { * storage via this._saveMsgList * * @private - * @param {msg} Message A Message that will replace an existing Message (with the same id) in this.messages + * @param {msg} Message - A Message that will replace an existing Message (with the same id) in this.messages * */ _updateMsg (msg) { @@ -269,8 +269,8 @@ export default class MessageManager extends EventEmitter { /** * A helper function that converts raw buffer data to a hex, or just returns the data if it is already formatted as a hex. * - * @param {any} data The buffer data to convert to a hex - * @returns {string} A hex string conversion of the buffer data + * @param {any} data - The buffer data to convert to a hex + * @returns {string} - A hex string conversion of the buffer data * */ function normalizeMsgData (data) { diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js index 3299a2417..8bd6f9217 100644 --- a/app/scripts/lib/migrator/index.js +++ b/app/scripts/lib/migrator/index.js @@ -77,7 +77,7 @@ class Migrator extends EventEmitter { /** * Returns the initial state for the migrator - * @param {object} [data] - The data for the initial state + * @param {Object} [data] - The data for the initial state * @returns {{meta: {version: number}, data: any}} */ generateInitialState (data) { diff --git a/app/scripts/lib/network-store.js b/app/scripts/lib/network-store.js index 975f0046d..795914912 100644 --- a/app/scripts/lib/network-store.js +++ b/app/scripts/lib/network-store.js @@ -37,7 +37,7 @@ class ReadOnlyNetworkStore { /** * Returns state - * @return {Promise} + * @returns {Promise} */ async get () { if (!this._initialized) { @@ -48,8 +48,8 @@ class ReadOnlyNetworkStore { /** * Set state - * @param {object} state - The state to set - * @return {Promise} + * @param {Object} state - The state to set + * @returns {Promise} */ async set (state) { if (!this._initialized) { diff --git a/app/scripts/lib/nodeify.js b/app/scripts/lib/nodeify.js index 93bd24782..5d4eb8c4d 100644 --- a/app/scripts/lib/nodeify.js +++ b/app/scripts/lib/nodeify.js @@ -10,8 +10,8 @@ const callbackNoop = function (err) { * A generator that returns a function which, when passed a promise, can treat that promise as a node style callback. * The prime advantage being that callbacks are better for error handling. * - * @param {Function} fn The function to handle as a callback - * @param {Object} context The context in which the fn is to be called, most often a this reference + * @param {Function} fn - The function to handle as a callback + * @param {Object} context - The context in which the fn is to be called, most often a this reference * */ export default function nodeify (fn, context) { diff --git a/app/scripts/lib/notification-manager.js b/app/scripts/lib/notification-manager.js index 1bffff4bf..12a0d3289 100644 --- a/app/scripts/lib/notification-manager.js +++ b/app/scripts/lib/notification-manager.js @@ -70,7 +70,7 @@ class NotificationManager { * type 'popup') * * @private - * @param {Function} cb A node style callback that to whcih the found notification window will be passed. + * @param {Function} cb - A node style callback that to whcih the found notification window will be passed. * */ _getPopup (cb) { @@ -86,7 +86,7 @@ class NotificationManager { * Returns all open MetaMask windows. * * @private - * @param {Function} cb A node style callback that to which the windows will be passed. + * @param {Function} cb - A node style callback that to which the windows will be passed. * */ _getWindows (cb) { @@ -104,7 +104,7 @@ class NotificationManager { * Given an array of windows, returns the 'popup' that has been opened by MetaMask, or null if no such window exists. * * @private - * @param {array} windows An array of objects containing data about the open MetaMask extension windows. + * @param {array} windows - An array of objects containing data about the open MetaMask extension windows. * */ _getPopupIn (windows) { diff --git a/app/scripts/lib/pending-balance-calculator.js b/app/scripts/lib/pending-balance-calculator.js index 786e57d99..6d1d4855b 100644 --- a/app/scripts/lib/pending-balance-calculator.js +++ b/app/scripts/lib/pending-balance-calculator.js @@ -8,8 +8,8 @@ class PendingBalanceCalculator { * pending transactions. * * @typedef {Object} PendingBalanceCalculator - * @param {Function} getBalance Returns a promise of a BN of the current balance in Wei - * @param {Function} getPendingTransactions Returns an array of TxMeta Objects, which have txParams properties, + * @param {Function} getBalance - Returns a promise of a BN of the current balance in Wei + * @param {Function} getPendingTransactions - Returns an array of TxMeta Objects, which have txParams properties, * which include value, gasPrice, and gas, all in a base=16 hex format. * */ @@ -22,7 +22,7 @@ class PendingBalanceCalculator { * Returns the users "pending balance": their current balance minus the total possible cost of all their * pending transactions. * - * @returns {Promise} Promises a base 16 hex string that contains the user's "pending balance" + * @returns {Promise} - Promises a base 16 hex string that contains the user's "pending balance" * */ async getBalance () { @@ -46,11 +46,11 @@ class PendingBalanceCalculator { /** * Calculates the maximum possible cost of a single transaction, based on the value, gas price and gas limit. * - * @param {object} tx Contains all that data about a transaction. + * @param {Object} tx - Contains all that data about a transaction. * @property {object} tx.txParams Contains data needed to calculate the maximum cost of the transaction: gas, * gasLimit and value. * - * @returns {string} Returns a base 16 hex string that contains the maximum possible cost of the transaction. + * @returns {string} - Returns a base 16 hex string that contains the maximum possible cost of the transaction. */ calculateMaxCost (tx) { const txValue = tx.txParams.value @@ -68,8 +68,8 @@ class PendingBalanceCalculator { /** * Converts a hex string to a BN object * - * @param {string} hex A number represented as a hex string - * @returns {Object} A BN object + * @param {string} hex - A number represented as a hex string + * @returns {Object} - A BN object * */ hexToBn (hex) { diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index 50b29dfaa..e708ed1c8 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -50,7 +50,7 @@ export default class PersonalMessageManager extends EventEmitter { /** * A getter for the number of 'unapproved' PersonalMessages in this.messages * - * @returns {number} The number of 'unapproved' PersonalMessages in this.messages + * @returns {number} - The number of 'unapproved' PersonalMessages in this.messages * */ get unapprovedPersonalMsgCount () { @@ -60,7 +60,7 @@ export default class PersonalMessageManager extends EventEmitter { /** * A getter for the 'unapproved' PersonalMessages in this.messages * - * @returns {Object} An index of PersonalMessage ids to PersonalMessages, for all 'unapproved' PersonalMessages in + * @returns {Object} - An index of PersonalMessage ids to PersonalMessages, for all 'unapproved' PersonalMessages in * this.messages * */ @@ -76,9 +76,9 @@ export default class PersonalMessageManager extends EventEmitter { * the new PersonalMessage to this.messages, and to save the unapproved PersonalMessages from that list to * this.memStore. * - * @param {Object} msgParams The params for the eth_sign call to be made after the message is approved. + * @param {Object} msgParams - The params for the eth_sign call to be made after the message is approved. * @param {Object} req (optional) The original request object possibly containing the origin - * @returns {promise} When the message has been signed or rejected + * @returns {promise} - When the message has been signed or rejected * */ addUnapprovedMessageAsync (msgParams, req) { @@ -105,9 +105,9 @@ export default class PersonalMessageManager extends EventEmitter { * the new PersonalMessage to this.messages, and to save the unapproved PersonalMessages from that list to * this.memStore. * - * @param {Object} msgParams The params for the eth_sign call to be made after the message is approved. + * @param {Object} msgParams - The params for the eth_sign call to be made after the message is approved. * @param {Object} req (optional) The original request object possibly containing the origin - * @returns {number} The id of the newly created PersonalMessage. + * @returns {number} - The id of the newly created PersonalMessage. * */ addUnapprovedMessage (msgParams, req) { @@ -138,7 +138,7 @@ export default class PersonalMessageManager extends EventEmitter { * Adds a passed PersonalMessage to this.messages, and calls this._saveMsgList() to save the unapproved PersonalMessages from that * list to this.memStore. * - * @param {Message} msg The PersonalMessage to add to this.messages + * @param {Message} msg - The PersonalMessage to add to this.messages * */ addMsg (msg) { @@ -149,8 +149,8 @@ export default class PersonalMessageManager extends EventEmitter { /** * Returns a specified PersonalMessage. * - * @param {number} msgId The id of the PersonalMessage to get - * @returns {PersonalMessage|undefined} The PersonalMessage with the id that matches the passed msgId, or undefined + * @param {number} msgId - The id of the PersonalMessage to get + * @returns {PersonalMessage|undefined} - The PersonalMessage with the id that matches the passed msgId, or undefined * if no PersonalMessage has that id. * */ @@ -162,9 +162,9 @@ export default class PersonalMessageManager extends EventEmitter { * Approves a PersonalMessage. Sets the message status via a call to this.setMsgStatusApproved, and returns a promise * with any the message params modified for proper signing. * - * @param {Object} msgParams The msgParams to be used when eth_sign is called, plus data added by MetaMask. + * @param {Object} msgParams - The msgParams to be used when eth_sign is called, plus data added by MetaMask. * @param {Object} msgParams.metamaskId Added to msgParams for tracking and identification within MetaMask. - * @returns {Promise} Promises the msgParams object with metamaskId removed. + * @returns {Promise} - Promises the msgParams object with metamaskId removed. * */ approveMessage (msgParams) { @@ -175,7 +175,7 @@ export default class PersonalMessageManager extends EventEmitter { /** * Sets a PersonalMessage status to 'approved' via a call to this._setMsgStatus. * - * @param {number} msgId The id of the PersonalMessage to approve. + * @param {number} msgId - The id of the PersonalMessage to approve. * */ setMsgStatusApproved (msgId) { @@ -186,8 +186,8 @@ export default class PersonalMessageManager extends EventEmitter { * Sets a PersonalMessage status to 'signed' via a call to this._setMsgStatus and updates that PersonalMessage in * this.messages by adding the raw signature data of the signature request to the PersonalMessage * - * @param {number} msgId The id of the PersonalMessage to sign. - * @param {buffer} rawSig The raw data of the signature request + * @param {number} msgId - The id of the PersonalMessage to sign. + * @param {buffer} rawSig - The raw data of the signature request * */ setMsgStatusSigned (msgId, rawSig) { @@ -200,8 +200,8 @@ export default class PersonalMessageManager extends EventEmitter { /** * Removes the metamaskId property from passed msgParams and returns a promise which resolves the updated msgParams * - * @param {Object} msgParams The msgParams to modify - * @returns {Promise} Promises the msgParams with the metamaskId property removed + * @param {Object} msgParams - The msgParams to modify + * @returns {Promise} - Promises the msgParams with the metamaskId property removed * */ prepMsgForSigning (msgParams) { @@ -212,7 +212,7 @@ export default class PersonalMessageManager extends EventEmitter { /** * Sets a PersonalMessage status to 'rejected' via a call to this._setMsgStatus. * - * @param {number} msgId The id of the PersonalMessage to reject. + * @param {number} msgId - The id of the PersonalMessage to reject. * */ rejectMsg (msgId) { @@ -223,8 +223,8 @@ export default class PersonalMessageManager extends EventEmitter { * Updates the status of a PersonalMessage in this.messages via a call to this._updateMsg * * @private - * @param {number} msgId The id of the PersonalMessage to update. - * @param {string} status The new status of the PersonalMessage. + * @param {number} msgId - The id of the PersonalMessage to update. + * @param {string} status - The new status of the PersonalMessage. * @throws A 'PersonalMessageManager - PersonalMessage not found for id: "${msgId}".' if there is no PersonalMessage * in this.messages with an id equal to the passed msgId * @fires An event with a name equal to `${msgId}:${status}`. The PersonalMessage is also fired. @@ -250,7 +250,7 @@ export default class PersonalMessageManager extends EventEmitter { * unapprovedPersonalMsgs index to storage via this._saveMsgList * * @private - * @param {msg} PersonalMessage A PersonalMessage that will replace an existing PersonalMessage (with the same + * @param {msg} PersonalMessage - A PersonalMessage that will replace an existing PersonalMessage (with the same * id) in this.messages * */ @@ -279,8 +279,8 @@ export default class PersonalMessageManager extends EventEmitter { /** * A helper function that converts raw buffer data to a hex, or just returns the data if it is already formatted as a hex. * - * @param {any} data The buffer data to convert to a hex - * @returns {string} A hex string conversion of the buffer data + * @param {any} data - The buffer data to convert to a hex + * @returns {string} - A hex string conversion of the buffer data * */ normalizeMsgData (data) { diff --git a/app/scripts/lib/seed-phrase-verifier.js b/app/scripts/lib/seed-phrase-verifier.js index 31d4cc404..6a2925c71 100644 --- a/app/scripts/lib/seed-phrase-verifier.js +++ b/app/scripts/lib/seed-phrase-verifier.js @@ -11,9 +11,9 @@ const seedPhraseVerifier = { * - The created accounts in the primary keyring are always the same. * - The keyring always creates the accounts in the same sequence. * - * @param {array} createdAccounts The accounts to restore - * @param {string} seedWords The seed words to verify - * @returns {Promise} Promises undefined + * @param {array} createdAccounts - The accounts to restore + * @param {string} seedWords - The seed words to verify + * @returns {Promise} - Promises undefined * */ verifyAccounts (createdAccounts, seedWords) { diff --git a/app/scripts/lib/stream-utils.js b/app/scripts/lib/stream-utils.js index 253836a7a..55e2c419c 100644 --- a/app/scripts/lib/stream-utils.js +++ b/app/scripts/lib/stream-utils.js @@ -4,7 +4,7 @@ import pump from 'pump' /** * Sets up stream multiplexing for the given stream * @param {any} connectionStream - the stream to mux - * @return {stream.Stream} the multiplexed stream + * @returns {stream.Stream} - the multiplexed stream */ export function setupMultiplex (connectionStream) { const mux = new ObjectMultiplex() diff --git a/app/scripts/lib/typed-message-manager.js b/app/scripts/lib/typed-message-manager.js index 157f63713..84c1864a4 100644 --- a/app/scripts/lib/typed-message-manager.js +++ b/app/scripts/lib/typed-message-manager.js @@ -42,7 +42,7 @@ export default class TypedMessageManager extends EventEmitter { /** * A getter for the number of 'unapproved' TypedMessages in this.messages * - * @returns {number} The number of 'unapproved' TypedMessages in this.messages + * @returns {number} - The number of 'unapproved' TypedMessages in this.messages * */ get unapprovedTypedMessagesCount () { @@ -52,7 +52,7 @@ export default class TypedMessageManager extends EventEmitter { /** * A getter for the 'unapproved' TypedMessages in this.messages * - * @returns {Object} An index of TypedMessage ids to TypedMessages, for all 'unapproved' TypedMessages in + * @returns {Object} - An index of TypedMessage ids to TypedMessages, for all 'unapproved' TypedMessages in * this.messages * */ @@ -68,9 +68,9 @@ export default class TypedMessageManager extends EventEmitter { * the new TypedMessage to this.messages, and to save the unapproved TypedMessages from that list to * this.memStore. Before any of this is done, msgParams are validated * - * @param {Object} msgParams The params for the eth_sign call to be made after the message is approved. + * @param {Object} msgParams - The params for the eth_sign call to be made after the message is approved. * @param {Object} req (optional) The original request object possibly containing the origin - * @returns {promise} When the message has been signed or rejected + * @returns {promise} - When the message has been signed or rejected * */ addUnapprovedMessageAsync (msgParams, req, version) { @@ -96,9 +96,9 @@ export default class TypedMessageManager extends EventEmitter { * the new TypedMessage to this.messages, and to save the unapproved TypedMessages from that list to * this.memStore. Before any of this is done, msgParams are validated * - * @param {Object} msgParams The params for the eth_sign call to be made after the message is approved. + * @param {Object} msgParams - The params for the eth_sign call to be made after the message is approved. * @param {Object} req (optional) The original request object possibly containing the origin - * @returns {number} The id of the newly created TypedMessage. + * @returns {number} - The id of the newly created TypedMessage. * */ addUnapprovedMessage (msgParams, req, version) { @@ -130,7 +130,7 @@ export default class TypedMessageManager extends EventEmitter { /** * Helper method for this.addUnapprovedMessage. Validates that the passed params have the required properties. * - * @param {Object} params The params to validate + * @param {Object} params - The params to validate * */ validateParams (params) { @@ -172,7 +172,7 @@ export default class TypedMessageManager extends EventEmitter { * Adds a passed TypedMessage to this.messages, and calls this._saveMsgList() to save the unapproved TypedMessages from that * list to this.memStore. * - * @param {Message} msg The TypedMessage to add to this.messages + * @param {Message} msg - The TypedMessage to add to this.messages * */ addMsg (msg) { @@ -183,8 +183,8 @@ export default class TypedMessageManager extends EventEmitter { /** * Returns a specified TypedMessage. * - * @param {number} msgId The id of the TypedMessage to get - * @returns {TypedMessage|undefined} The TypedMessage with the id that matches the passed msgId, or undefined + * @param {number} msgId - The id of the TypedMessage to get + * @returns {TypedMessage|undefined} - The TypedMessage with the id that matches the passed msgId, or undefined * if no TypedMessage has that id. * */ @@ -196,9 +196,9 @@ export default class TypedMessageManager extends EventEmitter { * Approves a TypedMessage. Sets the message status via a call to this.setMsgStatusApproved, and returns a promise * with any the message params modified for proper signing. * - * @param {Object} msgParams The msgParams to be used when eth_sign is called, plus data added by MetaMask. + * @param {Object} msgParams - The msgParams to be used when eth_sign is called, plus data added by MetaMask. * @param {Object} msgParams.metamaskId Added to msgParams for tracking and identification within MetaMask. - * @returns {Promise} Promises the msgParams object with metamaskId removed. + * @returns {Promise} - Promises the msgParams object with metamaskId removed. * */ approveMessage (msgParams) { @@ -209,7 +209,7 @@ export default class TypedMessageManager extends EventEmitter { /** * Sets a TypedMessage status to 'approved' via a call to this._setMsgStatus. * - * @param {number} msgId The id of the TypedMessage to approve. + * @param {number} msgId - The id of the TypedMessage to approve. * */ setMsgStatusApproved (msgId) { @@ -220,8 +220,8 @@ export default class TypedMessageManager extends EventEmitter { * Sets a TypedMessage status to 'signed' via a call to this._setMsgStatus and updates that TypedMessage in * this.messages by adding the raw signature data of the signature request to the TypedMessage * - * @param {number} msgId The id of the TypedMessage to sign. - * @param {buffer} rawSig The raw data of the signature request + * @param {number} msgId - The id of the TypedMessage to sign. + * @param {buffer} rawSig - The raw data of the signature request * */ setMsgStatusSigned (msgId, rawSig) { @@ -234,8 +234,8 @@ export default class TypedMessageManager extends EventEmitter { /** * Removes the metamaskId property from passed msgParams and returns a promise which resolves the updated msgParams * - * @param {Object} msgParams The msgParams to modify - * @returns {Promise} Promises the msgParams with the metamaskId property removed + * @param {Object} msgParams - The msgParams to modify + * @returns {Promise} - Promises the msgParams with the metamaskId property removed * */ prepMsgForSigning (msgParams) { @@ -247,7 +247,7 @@ export default class TypedMessageManager extends EventEmitter { /** * Sets a TypedMessage status to 'rejected' via a call to this._setMsgStatus. * - * @param {number} msgId The id of the TypedMessage to reject. + * @param {number} msgId - The id of the TypedMessage to reject. * */ rejectMsg (msgId) { @@ -257,7 +257,7 @@ export default class TypedMessageManager extends EventEmitter { /** * Sets a TypedMessage status to 'errored' via a call to this._setMsgStatus. * - * @param {number} msgId The id of the TypedMessage to error + * @param {number} msgId - The id of the TypedMessage to error * */ errorMessage (msgId, error) { @@ -275,8 +275,8 @@ export default class TypedMessageManager extends EventEmitter { * Updates the status of a TypedMessage in this.messages via a call to this._updateMsg * * @private - * @param {number} msgId The id of the TypedMessage to update. - * @param {string} status The new status of the TypedMessage. + * @param {number} msgId - The id of the TypedMessage to update. + * @param {string} status - The new status of the TypedMessage. * @throws A 'TypedMessageManager - TypedMessage not found for id: "${msgId}".' if there is no TypedMessage * in this.messages with an id equal to the passed msgId * @fires An event with a name equal to `${msgId}:${status}`. The TypedMessage is also fired. @@ -302,7 +302,7 @@ export default class TypedMessageManager extends EventEmitter { * unapprovedTypedMsgs index to storage via this._saveMsgList * * @private - * @param {msg} TypedMessage A TypedMessage that will replace an existing TypedMessage (with the same + * @param {msg} TypedMessage - A TypedMessage that will replace an existing TypedMessage (with the same * id) in this.messages * */ diff --git a/app/scripts/lib/util.js b/app/scripts/lib/util.js index 5b4fa5e10..1393557c6 100644 --- a/app/scripts/lib/util.js +++ b/app/scripts/lib/util.js @@ -22,7 +22,7 @@ import { * - 'notification' refers to the popup that appears in its own window when taking action outside of metamask * - 'background' refers to the background page * - * @returns {string} A single word label that represents the type of window through which the app is being viewed + * @returns {string} - A single word label that represents the type of window through which the app is being viewed * */ const getEnvironmentType = (url = window.location.href) => { @@ -41,7 +41,7 @@ const getEnvironmentType = (url = window.location.href) => { /** * Returns the platform (browser) where the extension is running. * - * @returns {string} the platform ENUM + * @returns {string} - the platform ENUM * */ const getPlatform = _ => { @@ -64,12 +64,12 @@ const getPlatform = _ => { /** * Checks whether a given balance of ETH, represented as a hex string, is sufficient to pay a value plus a gas fee * - * @param {object} txParams Contains data about a transaction + * @param {Object} txParams - Contains data about a transaction * @param {string} txParams.gas The gas for a transaction * @param {string} txParams.gasPrice The price per gas for the transaction * @param {string} txParams.value The value of ETH to send - * @param {string} hexBalance A balance of ETH represented as a hex string - * @returns {boolean} Whether the balance is greater than or equal to the value plus the value of gas times gasPrice + * @param {string} hexBalance - A balance of ETH represented as a hex string + * @returns {boolean} - Whether the balance is greater than or equal to the value plus the value of gas times gasPrice * */ function sufficientBalance (txParams, hexBalance) { @@ -89,8 +89,8 @@ function sufficientBalance (txParams, hexBalance) { /** * Converts a BN object to a hex string with a '0x' prefix * - * @param {BN} inputBn The BN to convert to a hex string - * @returns {string} A '0x' prefixed hex string + * @param {BN} inputBn - The BN to convert to a hex string + * @returns {string} - A '0x' prefixed hex string * */ function bnToHex (inputBn) { @@ -100,8 +100,8 @@ function bnToHex (inputBn) { /** * Converts a hex string to a BN object * - * @param {string} inputHex A number represented as a hex string - * @returns {Object} A BN object + * @param {string} inputHex - A number represented as a hex string + * @returns {Object} - A BN object * */ function hexToBn (inputHex) { @@ -111,10 +111,10 @@ function hexToBn (inputHex) { /** * Used to multiply a BN by a fraction * - * @param {BN} targetBN The number to multiply by a fraction - * @param {number|string} numerator The numerator of the fraction multiplier - * @param {number|string} denominator The denominator of the fraction multiplier - * @returns {BN} The product of the multiplication + * @param {BN} targetBN - The number to multiply by a fraction + * @param {number|string} numerator - The numerator of the fraction multiplier + * @param {number|string} denominator - The denominator of the fraction multiplier + * @returns {BN} - The product of the multiplication * */ function BnMultiplyByFraction (targetBN, numerator, denominator) { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 9af7e8d53..6ce3e05be 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -407,7 +407,7 @@ export default class MetamaskController extends EventEmitter { /** * The metamask-state of the various controllers, made available to the UI * - * @returns {Object} status + * @returns {Object} - status */ getState () { const vault = this.keyringController.store.getState().vault @@ -424,7 +424,7 @@ export default class MetamaskController extends EventEmitter { * These functions are the interface for the UI. * The API object can be transmitted over a stream with dnode. * - * @returns {Object} Object containing API functions. + * @returns {Object} - Object containing API functions. */ getApi () { const keyringController = this.keyringController @@ -581,7 +581,7 @@ export default class MetamaskController extends EventEmitter { * * @param {string} password * - * @returns {Object} vault + * @returns {Object} - vault */ async createNewVaultAndKeychain (password) { const releaseLock = await this.createVaultMutex.acquire() @@ -675,7 +675,7 @@ export default class MetamaskController extends EventEmitter { /** * Collects all the information that we want to share * with the mobile client for syncing purposes - * @returns Promise Parts of the state that we want to syncx + * @returns {Promise} - Parts of the state that we want to syncx */ async fetchInfoToSync () { // Preferences @@ -941,7 +941,7 @@ export default class MetamaskController extends EventEmitter { * * Called when the first account is created and on unlocking the vault. * - * @returns {Promise} Seed phrase to be confirmed by the user. + * @returns {Promise} - Seed phrase to be confirmed by the user. */ async verifySeedPhrase () { @@ -972,7 +972,7 @@ export default class MetamaskController extends EventEmitter { * Mostly used in development environments, when networks are restarted with * the same network ID. * - * @returns Promise The current selected address. + * @returns {Promise} - The current selected address. */ async resetAccount () { const selectedAddress = this.preferencesController.getSelectedAddress() @@ -985,7 +985,7 @@ export default class MetamaskController extends EventEmitter { /** * Removes an account from state / storage. * - * @param {string[]} address A hex address + * @param {string[]} address - A hex address * */ async removeAccount (address) { @@ -1056,8 +1056,8 @@ export default class MetamaskController extends EventEmitter { /** * Signifies user intent to complete an eth_sign method. * - * @param {Object} msgParams The params passed to eth_call. - * @returns {Promise} Full state update. + * @param {Object} msgParams - The params passed to eth_call. + * @returns {Promise} - Full state update. */ signMessage (msgParams) { log.info('MetaMaskController - signMessage') @@ -1169,7 +1169,7 @@ export default class MetamaskController extends EventEmitter { * Triggers the callback in newUnsignedTypedMessage. * * @param {Object} msgParams - The params passed to eth_signTypedData. - * @returns {Object} Full state update. + * @returns {Object} - Full state update. */ async signTypedMessage (msgParams) { log.info('MetaMaskController - eth_signTypedData') @@ -1228,8 +1228,8 @@ export default class MetamaskController extends EventEmitter { * Allows a user to attempt to cancel a previously submitted transaction by creating a new * transaction. * @param {number} originalTxId - the id of the txMeta that you want to attempt to cancel - * @param {string=} customGasPrice - the hex value to use for the cancel transaction - * @returns {object} MetaMask state + * @param {string} [customGasPrice] - the hex value to use for the cancel transaction + * @returns {Object} - MetaMask state */ async createCancelTransaction (originalTxId, customGasPrice) { try { @@ -1591,8 +1591,8 @@ export default class MetamaskController extends EventEmitter { /** * Handle a KeyringController update - * @param {object} state the KC state - * @return {Promise} + * @param {Object} state - the KC state + * @returns {Promise} * @private */ async _onKeyringControllerUpdate (state) { @@ -1636,7 +1636,7 @@ export default class MetamaskController extends EventEmitter { * Returns the lowest price that would have been included in * 50% of recent blocks. * - * @returns {string} A hex representation of the suggested wei gas price. + * @returns {string} - A hex representation of the suggested wei gas price. */ getGasPrice () { const { recentBlocksController } = this @@ -1667,8 +1667,8 @@ export default class MetamaskController extends EventEmitter { /** * Returns the nonce that will be associated with a transaction once approved - * @param address {string} - The hex string address for the transaction - * @returns Promise + * @param {string} address - The hex string address for the transaction + * @returns {Promise} */ async getPendingNonce (address) { const { nonceDetails, releaseLock } = await this.txController.nonceTracker.getNonceLock(address) @@ -1680,8 +1680,8 @@ export default class MetamaskController extends EventEmitter { /** * Returns the next nonce according to the nonce-tracker - * @param address {string} - The hex string address for the transaction - * @returns Promise + * @param {string} address - The hex string address for the transaction + * @returns {Promise} */ async getNextNonce (address) { let nonceLock @@ -1854,7 +1854,7 @@ export default class MetamaskController extends EventEmitter { /** * Sets the type of first time flow the user wishes to follow: create or import - * @param {String} type - Indicates the type of first time flow the user wishes to follow + * @param {string} type - Indicates the type of first time flow the user wishes to follow * @param {Function} cb - A callback function called when complete. */ setFirstTimeFlowType (type, cb) { @@ -1928,7 +1928,7 @@ export default class MetamaskController extends EventEmitter { /** * Adds a domain to the PhishingController whitelist - * @param {string} hostname the domain to whitelist + * @param {string} hostname - the domain to whitelist */ whitelistPhishingDomain (hostname) { return this.phishingController.bypass(hostname) diff --git a/app/scripts/ui.js b/app/scripts/ui.js index e870310c1..66c48e28d 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -131,8 +131,8 @@ function initializeUi (activeTab, container, connectionStream, cb) { /** * Establishes a connection to the background and a Web3 provider * - * @param {PortDuplexStream} connectionStream PortStream instance establishing a background connection - * @param {Function} cb Called when controller connection is established + * @param {PortDuplexStream} connectionStream - PortStream instance establishing a background connection + * @param {Function} cb - Called when controller connection is established */ function connectToAccountManager (connectionStream, cb) { const mx = setupMultiplex(connectionStream) @@ -143,7 +143,7 @@ function connectToAccountManager (connectionStream, cb) { /** * Establishes a streamed connection to a Web3 provider * - * @param {PortDuplexStream} connectionStream PortStream instance establishing a background connection + * @param {PortDuplexStream} connectionStream - PortStream instance establishing a background connection */ function setupWeb3Connection (connectionStream) { const providerStream = new StreamProvider() @@ -158,8 +158,8 @@ function setupWeb3Connection (connectionStream) { /** * Establishes a streamed connection to the background account manager * - * @param {PortDuplexStream} connectionStream PortStream instance establishing a background connection - * @param {Function} cb Called when the remote account manager connection is established + * @param {PortDuplexStream} connectionStream - PortStream instance establishing a background connection + * @param {Function} cb - Called when the remote account manager connection is established */ function setupControllerConnection (connectionStream, cb) { const eventEmitter = new EventEmitter() diff --git a/test/e2e/webdriver/chrome.js b/test/e2e/webdriver/chrome.js index ce03526c2..710f2ed20 100644 --- a/test/e2e/webdriver/chrome.js +++ b/test/e2e/webdriver/chrome.js @@ -34,7 +34,7 @@ class ChromeDriver { /** * @constructor - * @param {!ThenableWebDriver} driver a {@code WebDriver} instance + * @param {!ThenableWebDriver} driver - a {@code WebDriver} instance */ constructor (driver) { this._driver = driver @@ -42,8 +42,8 @@ class ChromeDriver { /** * Returns the extension ID for the given extension name - * @param {string} extensionName the extension name - * @return {Promise} the extension ID + * @param {string} extensionName - the extension name + * @returns {Promise} - the extension ID */ async getExtensionIdByName (extensionName) { await this._driver.get('chrome://extensions') diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index d03bccc03..9ac1063b7 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -108,8 +108,8 @@ class Driver { /** * Closes all windows except those in the given list of exceptions - * @param {Array} exceptions the list of window handle exceptions - * @param {Array?} windowHandles the full list of window handles + * @param {Array} exceptions - The list of window handle exceptions + * @param {Array} [windowHandles] - The full list of window handles * @returns {Promise} */ async closeAllWindowHandlesExcept (exceptions, windowHandles) { diff --git a/test/e2e/webdriver/firefox.js b/test/e2e/webdriver/firefox.js index e3ad2109f..b3ee1323b 100644 --- a/test/e2e/webdriver/firefox.js +++ b/test/e2e/webdriver/firefox.js @@ -22,8 +22,8 @@ const GeckoDriverCommand = { class FirefoxDriver { /** * Builds a {@link FirefoxDriver} instance - * @param {{extensionPath: string}} options the options for the build - * @return {Promise<{driver: !ThenableWebDriver, extensionUrl: string, extensionId: string}>} + * @param {{extensionPath: string}} options - the options for the build + * @returns {Promise<{driver: !ThenableWebDriver, extensionUrl: string, extensionId: string}>} */ static async build ({ extensionPath, responsive, port }) { const templateProfile = fs.mkdtempSync(TEMP_PROFILE_PATH_PREFIX) @@ -58,7 +58,7 @@ class FirefoxDriver { /** * @constructor - * @param {!ThenableWebDriver} driver a {@code WebDriver} instance + * @param {!ThenableWebDriver} driver - a {@code WebDriver} instance */ constructor (driver) { this._driver = driver @@ -66,7 +66,7 @@ class FirefoxDriver { /** * Initializes the driver - * @return {Promise} + * @returns {Promise} */ async init () { await this._driver.getExecutor() @@ -79,8 +79,8 @@ class FirefoxDriver { /** * Installs the extension at the given path - * @param {string} addonPath the path to the unpacked extension or XPI - * @return {Promise} the extension ID + * @param {string} addonPath - the path to the unpacked extension or XPI + * @returns {Promise} - the extension ID */ async installExtension (addonPath) { const cmd = new Command(GeckoDriverCommand.INSTALL_ADDON) @@ -92,7 +92,7 @@ class FirefoxDriver { /** * Returns the Internal UUID for the given extension - * @return {Promise} the Internal UUID for the given extension + * @returns {Promise} - the Internal UUID for the given extension */ async getInternalId () { await this._driver.get('about:debugging#addons') diff --git a/ui/app/components/app/dropdowns/components/menu.js b/ui/app/components/app/dropdowns/components/menu.js index b30af617d..7861ba534 100644 --- a/ui/app/components/app/dropdowns/components/menu.js +++ b/ui/app/components/app/dropdowns/components/menu.js @@ -4,7 +4,7 @@ import classnames from 'classnames' /** * Menu component - * @return {Component|null} + * @returns {Component|null} */ export function Menu (props) { const { className, children, isShowing } = props diff --git a/ui/app/helpers/higher-order-components/i18n-provider.js b/ui/app/helpers/higher-order-components/i18n-provider.js index 20b26cfbc..33f7ab862 100644 --- a/ui/app/helpers/higher-order-components/i18n-provider.js +++ b/ui/app/helpers/higher-order-components/i18n-provider.js @@ -20,9 +20,9 @@ class I18nProvider extends Component { return { /** * Returns a localized message for the given key - * @param {string} key The message key - * @param {string[]} args A list of message substitution replacements - * @return {string|undefined|null} The localized message if available + * @param {string} key - The message key + * @param {string[]} args - A list of message substitution replacements + * @returns {string|undefined|null} - The localized message if available */ t (key, ...args) { return getMessage(currentLocale, current, key, ...args) || getMessage(currentLocale, en, key, ...args) || `[${key}]` diff --git a/ui/app/helpers/utils/conversion-util.js b/ui/app/helpers/utils/conversion-util.js index 8b398f340..0c3e42a5d 100644 --- a/ui/app/helpers/utils/conversion-util.js +++ b/ui/app/helpers/utils/conversion-util.js @@ -4,7 +4,7 @@ * numeric base, denomination and currency, and the desired numeric base, denomination and * currency. It should return a single value. * -* @param {(number | string | BN)} value The value to convert. +* @param {(number | string | BN)} value - The value to convert. * @param {Object} [options] Options to specify details of the conversion * @param {string} [options.fromCurrency = 'ETH' | 'USD'] The currency of the passed value * @param {string} [options.toCurrency = 'ETH' | 'USD'] The desired currency of the result diff --git a/ui/app/helpers/utils/i18n-helper.js b/ui/app/helpers/utils/i18n-helper.js index 9433d62d0..29e068648 100644 --- a/ui/app/helpers/utils/i18n-helper.js +++ b/ui/app/helpers/utils/i18n-helper.js @@ -8,11 +8,11 @@ const missingMessageErrors = {} /** * Returns a localized message for the given key - * @param {string} localeCode The code for the current locale - * @param {object} localeMessages The map of messages for the current locale - * @param {string} key The message key - * @param {string[]} substitutions A list of message substitution replacements - * @return {null|string} The localized message + * @param {string} localeCode - The code for the current locale + * @param {Object} localeMessages - The map of messages for the current locale + * @param {string} key - The message key + * @param {string[]} substitutions - A list of message substitution replacements + * @returns {null|string} - The localized message */ export const getMessage = (localeCode, localeMessages, key, substitutions) => { if (!localeMessages) { diff --git a/ui/app/helpers/utils/metametrics.util.js b/ui/app/helpers/utils/metametrics.util.js index 7c51720db..c701b5e34 100644 --- a/ui/app/helpers/utils/metametrics.util.js +++ b/ui/app/helpers/utils/metametrics.util.js @@ -116,7 +116,7 @@ function composeParamAddition (paramValue, paramName) { * @property {string} config.url The url to track an event at. Overrides `currentPath` * @property {boolean} config.excludeMetaMetricsId Whether or not the tracked event data should be associated with a metametrics id * @property {boolean} config.isNewVisit Whether or not the event should be tracked as a new visit/user sessions - * @returns {String} Returns a url to be passed to fetch to make the appropriate request to matomo. + * @returns {string} - Returns a url to be passed to fetch to make the appropriate request to matomo. * Example: https://chromeextensionmm.innocraft.cloud/piwik.php?idsite=1&rec=1&apiv=1&e_c=Navigation&e_a=Home&e_n=Clicked%20Send:%20Eth&urlref=http%3A%2F%2Fwww.metamask.io%2Fmetametrics%2Fhome.html%23send&dimension5=3&dimension6=fullscreen&dimension7=ETH&dimension8=default&dimension9=0&dimension10=3&url=http%3A%2F%2Fwww.metamask.io%2Fmetametrics%2Fhome.html%23&_id=49c10aff19795e9a&rand=7906028754863992&pv_id=53acad&uid=49c1 */ function composeUrl (config) { diff --git a/ui/app/helpers/utils/switch-direction.js b/ui/app/helpers/utils/switch-direction.js index b0cee933e..171ead675 100644 --- a/ui/app/helpers/utils/switch-direction.js +++ b/ui/app/helpers/utils/switch-direction.js @@ -1,6 +1,6 @@ /** * Switch the CSS stylesheet used between 'rtl' and 'ltr' - * @param {('ltr' | 'rtl')} direction Text direction, either left-to-right (ltr) or right-to-left (rtl) + * @param {('ltr' | 'rtl')} direction - Text direction, either left-to-right (ltr) or right-to-left (rtl) */ const switchDirection = async (direction) => { if (direction === 'auto') { diff --git a/ui/app/helpers/utils/util.js b/ui/app/helpers/utils/util.js index bcadc5321..c9ede21d8 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/app/helpers/utils/util.js @@ -236,8 +236,8 @@ export function getTokenAddressFromTokenObject (token) { /** * Safely checksumms a potentially-null address * - * @param {String} [address] - address to checksum - * @returns {String} - checksummed address + * @param {string} [address] - address to checksum + * @returns {string} - checksummed address * */ export function checksumAddress (address) { diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 3e0541ec8..6f1717afe 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -1064,8 +1064,8 @@ export function cancelTx (txData) { /** * Cancels all of the given transactions - * @param {Array} txDataList a list of tx data objects - * @return {function(*): Promise} + * @param {Array} txDataList - a list of tx data objects + * @returns {function(*): Promise} */ export function cancelTxs (txDataList) { return async (dispatch) => { @@ -1596,7 +1596,7 @@ export function addToAddressBook (recipient, nickname = '', memo = '') { /** * @description Calls the addressBookController to remove an existing address. - * @param {String} addressToRemove - Address of the entry to remove from the address book + * @param {string} addressToRemove - Address of the entry to remove from the address book */ export function removeFromAddressBook (chainId, addressToRemove) { log.debug(`background.removeFromAddressBook`) From 25fe4adaa79e1f625e7a6e12e79799ab3746a186 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 13 Jan 2020 15:29:36 -0330 Subject: [PATCH 119/689] Remove usages of xtend from the background scripts (#7796) --- app/scripts/controllers/ab-test.js | 3 +-- app/scripts/controllers/app-state.js | 3 +-- app/scripts/controllers/cached-balances.js | 3 +-- app/scripts/controllers/infura.js | 3 +-- app/scripts/controllers/onboarding.js | 3 +-- app/scripts/controllers/preferences.js | 6 ++---- app/scripts/controllers/recent-blocks.js | 8 ++++---- app/scripts/controllers/transactions/tx-state-manager.js | 7 +++---- app/scripts/migrations/005.js | 7 +++---- app/scripts/migrations/006.js | 7 +++---- app/scripts/migrations/007.js | 7 +++---- app/scripts/migrations/008.js | 7 +++---- test/lib/mock-tx-gen.js | 3 +-- 13 files changed, 27 insertions(+), 40 deletions(-) diff --git a/app/scripts/controllers/ab-test.js b/app/scripts/controllers/ab-test.js index 9d677236b..ceeb2bc9b 100644 --- a/app/scripts/controllers/ab-test.js +++ b/app/scripts/controllers/ab-test.js @@ -1,5 +1,4 @@ import ObservableStore from 'obs-store' -import extend from 'xtend' import { getRandomArrayItem } from '../lib/util' /** @@ -21,7 +20,7 @@ class ABTestController { */ constructor (opts = {}) { const { initState } = opts - this.store = new ObservableStore(extend({ + this.store = new ObservableStore(Object.assign({ abTests: { fullScreenVsPopup: this._getRandomizedTestGroupName('fullScreenVsPopup'), }, diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index 4fd1d651e..55fbe2e76 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -1,5 +1,4 @@ import ObservableStore from 'obs-store' -import extend from 'xtend' class AppStateController { /** @@ -11,7 +10,7 @@ class AppStateController { const { preferences } = preferencesStore.getState() this.onInactiveTimeout = onInactiveTimeout || (() => {}) - this.store = new ObservableStore(extend({ + this.store = new ObservableStore(Object.assign({ timeoutMinutes: 0, mkrMigrationReminderTimestamp: null, }, initState)) diff --git a/app/scripts/controllers/cached-balances.js b/app/scripts/controllers/cached-balances.js index 2ef1dd2ef..936bda85b 100644 --- a/app/scripts/controllers/cached-balances.js +++ b/app/scripts/controllers/cached-balances.js @@ -1,5 +1,4 @@ import ObservableStore from 'obs-store' -import extend from 'xtend' /** * @typedef {Object} CachedBalancesOptions @@ -24,7 +23,7 @@ class CachedBalancesController { this.accountTracker = accountTracker this.getNetwork = getNetwork - const initState = extend({ + const initState = Object.assign({ cachedBalances: {}, }, opts.initState) this.store = new ObservableStore(initState) diff --git a/app/scripts/controllers/infura.js b/app/scripts/controllers/infura.js index e8729e37c..0e055085f 100644 --- a/app/scripts/controllers/infura.js +++ b/app/scripts/controllers/infura.js @@ -1,5 +1,4 @@ import ObservableStore from 'obs-store' -import extend from 'xtend' import log from 'loglevel' // every ten minutes @@ -8,7 +7,7 @@ const POLLING_INTERVAL = 10 * 60 * 1000 class InfuraController { constructor (opts = {}) { - const initState = extend({ + const initState = Object.assign({ infuraNetworkStatus: {}, }, opts.initState) this.store = new ObservableStore(initState) diff --git a/app/scripts/controllers/onboarding.js b/app/scripts/controllers/onboarding.js index b46e53357..def07d5cc 100644 --- a/app/scripts/controllers/onboarding.js +++ b/app/scripts/controllers/onboarding.js @@ -1,5 +1,4 @@ import ObservableStore from 'obs-store' -import extend from 'xtend' import log from 'loglevel' /** @@ -27,7 +26,7 @@ class OnboardingController { const initialTransientState = { onboardingTabs: {}, } - const initState = extend( + const initState = Object.assign( { seedPhraseBackedUp: true, }, diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 4db8df51f..76bb242f2 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -2,8 +2,6 @@ import ObservableStore from 'obs-store' import { addInternalMethodPrefix } from './permissions' import { normalize as normalizeAddress } from 'eth-sig-util' import { isValidAddress, sha3, bufferToHex } from 'ethereumjs-util' -import extend from 'xtend' - class PreferencesController { @@ -29,7 +27,7 @@ class PreferencesController { * */ constructor (opts = {}) { - const initState = extend({ + const initState = Object.assign({ frequentRpcListDetail: [], currentAccountTab: 'history', accountTokens: {}, @@ -489,7 +487,7 @@ class PreferencesController { }) if (index > -1) { const rpcDetail = rpcList[index] - const updatedRpc = extend(rpcDetail, newRpcDetails) + const updatedRpc = { ...rpcDetail, ...newRpcDetails } rpcList[index] = updatedRpc this.store.updateState({ frequentRpcListDetail: rpcList }) } else { diff --git a/app/scripts/controllers/recent-blocks.js b/app/scripts/controllers/recent-blocks.js index 5a4ac39eb..d5c9afc6a 100644 --- a/app/scripts/controllers/recent-blocks.js +++ b/app/scripts/controllers/recent-blocks.js @@ -1,5 +1,4 @@ import ObservableStore from 'obs-store' -import extend from 'xtend' import EthQuery from 'eth-query' import log from 'loglevel' import pify from 'pify' @@ -33,7 +32,7 @@ class RecentBlocksController { this.ethQuery = new EthQuery(provider) this.historyLength = opts.historyLength || 40 - const initState = extend({ + const initState = Object.assign({ recentBlocks: [], }, opts.initState) this.store = new ObservableStore(initState) @@ -121,11 +120,12 @@ class RecentBlocksController { * */ mapTransactionsToPrices (newBlock) { - const block = extend(newBlock, { + const block = { + ...newBlock, gasPrices: newBlock.transactions.map((tx) => { return tx.gasPrice }), - }) + } delete block.transactions return block } diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index 7fce8f97a..e8255841f 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -1,4 +1,3 @@ -import extend from 'xtend' import EventEmitter from 'safe-event-emitter' import ObservableStore from 'obs-store' import log from 'loglevel' @@ -32,7 +31,7 @@ class TransactionStateManager extends EventEmitter { super() this.store = new ObservableStore( - extend({ + Object.assign({ transactions: [], }, initState)) this.txHistoryLimit = txHistoryLimit @@ -48,7 +47,7 @@ class TransactionStateManager extends EventEmitter { if (netId === 'loading') { throw new Error('MetaMask is having trouble connecting to the network') } - return extend({ + return Object.assign({ id: createId(), time: (new Date()).getTime(), status: 'unapproved', @@ -222,7 +221,7 @@ class TransactionStateManager extends EventEmitter { */ updateTxParams (txId, txParams) { const txMeta = this.getTx(txId) - txMeta.txParams = extend(txMeta.txParams, txParams) + txMeta.txParams = { ...txMeta.txParams, ...txParams } this.updateTx(txMeta, `txStateManager#updateTxParams`) } diff --git a/app/scripts/migrations/005.js b/app/scripts/migrations/005.js index 9660b9347..f468afcaa 100644 --- a/app/scripts/migrations/005.js +++ b/app/scripts/migrations/005.js @@ -6,8 +6,6 @@ This migration moves state from the flat state trie into KeyringController subst */ -import extend from 'xtend' - import clone from 'clone' @@ -30,13 +28,14 @@ export default { function selectSubstateForKeyringController (state) { const config = state.config - const newState = extend(state, { + const newState = { + ...state, KeyringController: { vault: state.vault, selectedAccount: config.selectedAccount, walletNicknames: state.walletNicknames, }, - }) + } delete newState.vault delete newState.walletNicknames delete newState.config.selectedAccount diff --git a/app/scripts/migrations/006.js b/app/scripts/migrations/006.js index 9a85068ca..66a8e1605 100644 --- a/app/scripts/migrations/006.js +++ b/app/scripts/migrations/006.js @@ -6,8 +6,6 @@ This migration moves KeyringController.selectedAddress to PreferencesController. */ -import extend from 'xtend' - import clone from 'clone' export default { @@ -31,11 +29,12 @@ function migrateState (state) { const keyringSubstate = state.KeyringController // add new state - const newState = extend(state, { + const newState = { + ...state, PreferencesController: { selectedAddress: keyringSubstate.selectedAccount, }, - }) + } // rm old state delete newState.KeyringController.selectedAccount diff --git a/app/scripts/migrations/007.js b/app/scripts/migrations/007.js index a16472218..42539eae4 100644 --- a/app/scripts/migrations/007.js +++ b/app/scripts/migrations/007.js @@ -6,8 +6,6 @@ This migration breaks out the TransactionManager substate */ -import extend from 'xtend' - import clone from 'clone' export default { @@ -28,12 +26,13 @@ export default { } function transformState (state) { - const newState = extend(state, { + const newState = { + ...state, TransactionManager: { transactions: state.transactions || [], gasMultiplier: state.gasMultiplier || 1, }, - }) + } delete newState.transactions delete newState.gasMultiplier diff --git a/app/scripts/migrations/008.js b/app/scripts/migrations/008.js index d7bee8e46..c0e1ba56e 100644 --- a/app/scripts/migrations/008.js +++ b/app/scripts/migrations/008.js @@ -6,8 +6,6 @@ This migration breaks out the NoticeController substate */ -import extend from 'xtend' - import clone from 'clone' export default { @@ -28,11 +26,12 @@ export default { } function transformState (state) { - const newState = extend(state, { + const newState = { + ...state, NoticeController: { noticesList: state.noticesList || [], }, - }) + } delete newState.noticesList return newState diff --git a/test/lib/mock-tx-gen.js b/test/lib/mock-tx-gen.js index 920943083..720797d20 100644 --- a/test/lib/mock-tx-gen.js +++ b/test/lib/mock-tx-gen.js @@ -1,4 +1,3 @@ -import extend from 'xtend' import { BN } from 'ethereumjs-util' const template = { @@ -23,7 +22,7 @@ class TxGenerator { let nonce = fromNonce || this.txs.length const txs = [] for (let i = 0; i < count; i++) { - txs.push(extend(template, { + txs.push(Object.assign({}, template, { txParams: { nonce: hexify(nonce++), }, From 87b95205fc022bbe4c525ba9719c45aa6009d6f4 Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Mon, 13 Jan 2020 11:04:10 -0800 Subject: [PATCH 120/689] Update codeowners (#7813) --- .github/CODEOWNERS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9c62ba36f..6b8f079a1 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,5 +4,7 @@ package.json @danjm @whymarrh @Gudahtt yarn.lock @danjm @whymarrh @Gudahtt ui/ @danjm @whymarrh @Gudahtt -app/scripts/controllers/transactions @frankiebee @whymarrh +app/scripts/controllers/transactions @frankiebee @whymarrh @jennypollack .circleci/scripts/deps-install.sh @kumavis @Gudahtt +app/scripts/controllers/network @jennypollack @rekmarks +app/scripts/controllers/permissions @rekmarks @danjm From dd4e684f7d41643ac7a510f2740697c64cedda09 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 14 Jan 2020 13:34:38 -0400 Subject: [PATCH 121/689] Consolidate webdriver initialization (#7814) The webdriver is now instantiated directly by the webdriver module, rather than via a helper method. --- test/e2e/address-book.spec.js | 4 ++-- test/e2e/ethereum-on.spec.js | 4 ++-- test/e2e/from-import-ui.spec.js | 4 ++-- test/e2e/helpers.js | 11 ----------- test/e2e/incremental-security.spec.js | 4 ++-- test/e2e/metamask-responsive-ui.spec.js | 4 ++-- test/e2e/metamask-ui.spec.js | 4 ++-- test/e2e/permissions.spec.js | 4 ++-- test/e2e/send-edit.spec.js | 4 ++-- test/e2e/signature-request.spec.js | 4 ++-- test/e2e/threebox.spec.js | 6 +++--- test/e2e/web3.spec.js | 4 ++-- test/e2e/webdriver/index.js | 5 ++++- 13 files changed, 27 insertions(+), 35 deletions(-) diff --git a/test/e2e/address-book.spec.js b/test/e2e/address-book.spec.js index fc1738ebe..d3cadf169 100644 --- a/test/e2e/address-book.spec.js +++ b/test/e2e/address-book.spec.js @@ -2,11 +2,11 @@ const assert = require('assert') const { By, until } = require('selenium-webdriver') const { - prepareExtensionForTesting, tinyDelayMs, regularDelayMs, largeDelayMs, } = require('./helpers') +const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -29,7 +29,7 @@ describe('MetaMask', function () { }, ], }) - const result = await prepareExtensionForTesting() + const result = await buildWebDriver() driver = result.driver }) diff --git a/test/e2e/ethereum-on.spec.js b/test/e2e/ethereum-on.spec.js index 3955d5993..41a5f5c22 100644 --- a/test/e2e/ethereum-on.spec.js +++ b/test/e2e/ethereum-on.spec.js @@ -3,10 +3,10 @@ const webdriver = require('selenium-webdriver') const { By, until } = webdriver const { - prepareExtensionForTesting, regularDelayMs, largeDelayMs, } = require('./helpers') +const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -28,7 +28,7 @@ describe('MetaMask', function () { }, ], }) - const result = await prepareExtensionForTesting() + const result = await buildWebDriver() driver = result.driver }) diff --git a/test/e2e/from-import-ui.spec.js b/test/e2e/from-import-ui.spec.js index 3d742785f..3f1b68e73 100644 --- a/test/e2e/from-import-ui.spec.js +++ b/test/e2e/from-import-ui.spec.js @@ -3,11 +3,11 @@ const webdriver = require('selenium-webdriver') const { By, Key, until } = webdriver const { - prepareExtensionForTesting, tinyDelayMs, regularDelayMs, largeDelayMs, } = require('./helpers') +const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -33,7 +33,7 @@ describe('Using MetaMask with an existing account', function () { }, ], }) - const result = await prepareExtensionForTesting() + const result = await buildWebDriver() driver = result.driver }) diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 6ab427e6d..08dc1c97b 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -1,20 +1,9 @@ -const { buildWebDriver } = require('./webdriver') - const tinyDelayMs = 200 const regularDelayMs = tinyDelayMs * 2 const largeDelayMs = regularDelayMs * 2 module.exports = { - prepareExtensionForTesting, tinyDelayMs, regularDelayMs, largeDelayMs, } - -async function prepareExtensionForTesting ({ responsive, port } = {}) { - const browser = process.env.SELENIUM_BROWSER - const extensionPath = `dist/${browser}` - const { driver, extensionId, extensionUrl } = await buildWebDriver({ browser, extensionPath, responsive, port }) - - return { driver, extensionId, extensionUrl } -} diff --git a/test/e2e/incremental-security.spec.js b/test/e2e/incremental-security.spec.js index 811040452..0b75653c2 100644 --- a/test/e2e/incremental-security.spec.js +++ b/test/e2e/incremental-security.spec.js @@ -3,11 +3,11 @@ const webdriver = require('selenium-webdriver') const { By, until } = webdriver const { - prepareExtensionForTesting, tinyDelayMs, regularDelayMs, largeDelayMs, } = require('./helpers') +const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -33,7 +33,7 @@ describe('MetaMask', function () { }, ], }) - const result = await prepareExtensionForTesting() + const result = await buildWebDriver() driver = result.driver }) diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index 2e8d74f36..d014011a2 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -3,11 +3,11 @@ const webdriver = require('selenium-webdriver') const { By, until } = webdriver const { - prepareExtensionForTesting, tinyDelayMs, regularDelayMs, largeDelayMs, } = require('./helpers') +const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -23,7 +23,7 @@ describe('MetaMask', function () { before(async function () { await ganacheServer.start() - const result = await prepareExtensionForTesting({ responsive: true }) + const result = await buildWebDriver({ responsive: true }) driver = result.driver }) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index 02184d0fd..5230a9d1c 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -3,11 +3,11 @@ const webdriver = require('selenium-webdriver') const { By, Key, until } = webdriver const { - prepareExtensionForTesting, tinyDelayMs, regularDelayMs, largeDelayMs, } = require('./helpers') +const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -24,7 +24,7 @@ describe('MetaMask', function () { before(async function () { await ganacheServer.start() - const result = await prepareExtensionForTesting() + const result = await buildWebDriver() driver = result.driver }) diff --git a/test/e2e/permissions.spec.js b/test/e2e/permissions.spec.js index 95b19709d..bb15dfab6 100644 --- a/test/e2e/permissions.spec.js +++ b/test/e2e/permissions.spec.js @@ -3,10 +3,10 @@ const webdriver = require('selenium-webdriver') const { By, until } = webdriver const { - prepareExtensionForTesting, regularDelayMs, largeDelayMs, } = require('./helpers') +const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -28,7 +28,7 @@ describe('MetaMask', function () { }, ], }) - const result = await prepareExtensionForTesting() + const result = await buildWebDriver() driver = result.driver }) diff --git a/test/e2e/send-edit.spec.js b/test/e2e/send-edit.spec.js index df0d03acf..6bad4494d 100644 --- a/test/e2e/send-edit.spec.js +++ b/test/e2e/send-edit.spec.js @@ -3,11 +3,11 @@ const webdriver = require('selenium-webdriver') const { By, Key, until } = webdriver const { - prepareExtensionForTesting, tinyDelayMs, regularDelayMs, largeDelayMs, } = require('./helpers') +const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -30,7 +30,7 @@ describe('Using MetaMask with an existing account', function () { }, ], }) - const result = await prepareExtensionForTesting() + const result = await buildWebDriver() driver = result.driver }) diff --git a/test/e2e/signature-request.spec.js b/test/e2e/signature-request.spec.js index 7a05f6bec..f401d8aae 100644 --- a/test/e2e/signature-request.spec.js +++ b/test/e2e/signature-request.spec.js @@ -4,10 +4,10 @@ const webdriver = require('selenium-webdriver') const { By, Key, until } = webdriver const { - prepareExtensionForTesting, regularDelayMs, largeDelayMs, } = require('./helpers') +const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') const FixtureServer = require('./fixture-server') @@ -27,7 +27,7 @@ describe('MetaMask', function () { await fixtureServer.start() await fixtureServer.loadState(path.join(__dirname, 'fixtures', 'imported-account')) publicAddress = '0x5cfe73b6021e818b776b421b1c4db2474086a7e1' - const result = await prepareExtensionForTesting() + const result = await buildWebDriver() driver = result.driver }) diff --git a/test/e2e/threebox.spec.js b/test/e2e/threebox.spec.js index a6194e013..a9599f887 100644 --- a/test/e2e/threebox.spec.js +++ b/test/e2e/threebox.spec.js @@ -4,11 +4,11 @@ const getPort = require('get-port') const { By, until } = webdriver const { - prepareExtensionForTesting, tinyDelayMs, regularDelayMs, largeDelayMs, } = require('./helpers') +const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') const enLocaleMessages = require('../../app/_locales/en/messages.json') @@ -31,7 +31,7 @@ describe('MetaMask', function () { }, ], }) - const result = await prepareExtensionForTesting({ port: await getPort() }) + const result = await buildWebDriver({ port: await getPort() }) driver = result.driver }) @@ -171,7 +171,7 @@ describe('MetaMask', function () { let driver2 before(async function () { - const result = await prepareExtensionForTesting({ port: await getPort() }) + const result = await buildWebDriver({ port: await getPort() }) driver2 = result.driver }) diff --git a/test/e2e/web3.spec.js b/test/e2e/web3.spec.js index 6fb6027d4..b7704e463 100644 --- a/test/e2e/web3.spec.js +++ b/test/e2e/web3.spec.js @@ -3,10 +3,10 @@ const webdriver = require('selenium-webdriver') const { By } = webdriver const { - prepareExtensionForTesting, regularDelayMs, largeDelayMs, } = require('./helpers') +const { buildWebDriver } = require('./webdriver') const enLocaleMessages = require('../../app/_locales/en/messages.json') describe('Using MetaMask with an existing account', function () { @@ -30,7 +30,7 @@ describe('Using MetaMask with an existing account', function () { this.bail(true) before(async function () { - const result = await prepareExtensionForTesting() + const result = await buildWebDriver() driver = result.driver }) diff --git a/test/e2e/webdriver/index.js b/test/e2e/webdriver/index.js index 66e0403cf..17c3b2744 100644 --- a/test/e2e/webdriver/index.js +++ b/test/e2e/webdriver/index.js @@ -4,7 +4,10 @@ const ChromeDriver = require('./chrome') const FirefoxDriver = require('./firefox') const fetchMockResponses = require('../../data/fetch-mocks.json') -async function buildWebDriver ({ browser, extensionPath, responsive, port }) { +async function buildWebDriver ({ responsive, port } = {}) { + const browser = process.env.SELENIUM_BROWSER + const extensionPath = `dist/${browser}` + switch (browser) { case Browser.CHROME: { const { driver, extensionId, extensionUrl } = await ChromeDriver.build({ extensionPath, responsive, port }) From 19f10e197eb91782936979f6e894477d48815ef2 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 14 Jan 2020 14:53:02 -0400 Subject: [PATCH 122/689] Simplify e2e test transaction navigation (#7816) The transaction navigation in the e2e tests has been made simpler with the addition of data attributes to help with finding the navigation buttons. Each button is now labelled according to its purpose. --- test/e2e/metamask-ui.spec.js | 23 ++++++------------- ...irm-page-container-navigation.component.js | 4 ++++ 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index 5230a9d1c..047865e8a 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -577,46 +577,37 @@ describe('MetaMask', function () { }) it('navigates the transactions', async () => { - let navigateTxButtons = await driver.findElements(By.css('.confirm-page-container-navigation__arrow')) - assert.equal(navigateTxButtons.length, 4, 'navigation button present') - - await navigateTxButtons[2].click() + await driver.clickElement(By.css('[data-testid="next-page"]')) let navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) let navigationText = await navigationElement.getText() assert.equal(navigationText.includes('2'), true, 'changed transaction right') - navigateTxButtons = await driver.findElements(By.css('.confirm-page-container-navigation__arrow')) - await navigateTxButtons[2].click() + await driver.clickElement(By.css('[data-testid="next-page"]')) navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) navigationText = await navigationElement.getText() assert.equal(navigationText.includes('3'), true, 'changed transaction right') - navigateTxButtons = await driver.findElements(By.css('.confirm-page-container-navigation__arrow')) - await navigateTxButtons[2].click() + await driver.clickElement(By.css('[data-testid="next-page"]')) navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) navigationText = await navigationElement.getText() assert.equal(navigationText.includes('4'), true, 'changed transaction right') - navigateTxButtons = await driver.findElements(By.css('.confirm-page-container-navigation__arrow')) - await navigateTxButtons[0].click() + await driver.clickElement(By.css('[data-testid="first-page"]')) navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) navigationText = await navigationElement.getText() assert.equal(navigationText.includes('1'), true, 'navigate to first transaction') - navigateTxButtons = await driver.findElements(By.css('.confirm-page-container-navigation__arrow')) - await navigateTxButtons[3].click() + await driver.clickElement(By.css('[data-testid="last-page"]')) navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) navigationText = await navigationElement.getText() assert.equal(navigationText.split('4').length, 3, 'navigate to last transaction') - navigateTxButtons = await driver.findElements(By.css('.confirm-page-container-navigation__arrow')) - await navigateTxButtons[1].click() + await driver.clickElement(By.css('[data-testid="previous-page"]')) navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) navigationText = await navigationElement.getText() assert.equal(navigationText.includes('3'), true, 'changed transaction left') - navigateTxButtons = await driver.findElements(By.css('.confirm-page-container-navigation__arrow')) - await navigateTxButtons[1].click() + await driver.clickElement(By.css('[data-testid="previous-page"]')) navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) navigationText = await navigationElement.getText() assert.equal(navigationText.includes('2'), true, 'changed transaction left') diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js index dd1fd2da4..a3eaf3255 100755 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js @@ -19,12 +19,14 @@ const ConfirmPageContainerNavigation = props => { >
onNextTx(firstTx)} >
onNextTx(prevTxId)} > @@ -46,12 +48,14 @@ const ConfirmPageContainerNavigation = props => { >
onNextTx(nextTxId)} >
onNextTx(lastTx)} > From a891fa36b6d72ca67b66cfede7f4c3c3a11ad036 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 14 Jan 2020 15:44:12 -0330 Subject: [PATCH 123/689] Remove MetaMask Mesh testing client (#7818) --- app/scripts/background.js | 9 ------ .../controllers/network/createInfuraClient.js | 14 ++------- app/scripts/controllers/network/network.js | 1 - app/scripts/lib/setupMetamaskMeshMetrics.js | 31 ------------------- 4 files changed, 2 insertions(+), 53 deletions(-) delete mode 100644 app/scripts/lib/setupMetamaskMeshMetrics.js diff --git a/app/scripts/background.js b/app/scripts/background.js index 2acb3ad66..20e05039a 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -31,7 +31,6 @@ import MetamaskController from './metamask-controller' import rawFirstTimeState from './first-time-state' import setupSentry from './lib/setupSentry' import reportFailedTxToSentry from './lib/reportFailedTxToSentry' -import setupMetamaskMeshMetrics from './lib/setupMetamaskMeshMetrics' import getFirstPreferredLangCode from './lib/get-first-preferred-lang-code' import getObjStructure from './lib/getObjStructure' import setupEnsIpfsResolver from './lib/ens-ipfs/setup' @@ -70,9 +69,6 @@ let versionedData // initialization flow initialize().catch(log.error) -// setup metamask mesh testing container -const { submitMeshMetricsEntry } = setupMetamaskMeshMetrics() - /** * An object representing a transaction, in whatever state it is in. * @typedef TransactionMeta @@ -257,11 +253,6 @@ function setupController (initState, initLangCode) { provider: controller.provider, }) - // submit rpc requests to mesh-metrics - controller.networkController.on('rpc-req', (data) => { - submitMeshMetricsEntry({ type: 'rpc', data }) - }) - // report failed transactions to Sentry controller.txController.on(`tx:status-update`, (txId, status) => { if (status !== 'failed') { diff --git a/app/scripts/controllers/network/createInfuraClient.js b/app/scripts/controllers/network/createInfuraClient.js index 77d60045a..5ab71550d 100644 --- a/app/scripts/controllers/network/createInfuraClient.js +++ b/app/scripts/controllers/network/createInfuraClient.js @@ -11,11 +11,8 @@ import BlockTracker from 'eth-block-tracker' export default createInfuraClient -function createInfuraClient ({ network, onRequest }) { - const infuraMiddleware = mergeMiddleware([ - createRequestHookMiddleware(onRequest), - createInfuraMiddleware({ network, maxAttempts: 5, source: 'metamask' }), - ]) +function createInfuraClient ({ network }) { + const infuraMiddleware = createInfuraMiddleware({ network, maxAttempts: 5, source: 'metamask' }) const infuraProvider = providerFromMiddleware(infuraMiddleware) const blockTracker = new BlockTracker({ provider: infuraProvider }) @@ -65,10 +62,3 @@ function createNetworkAndChainIdMiddleware ({ network }) { net_version: netId, }) } - -function createRequestHookMiddleware (onRequest) { - return (req, _, next) => { - onRequest(req) - next() - } -} diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index 9a0ce2ca9..a0c19f1bd 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -189,7 +189,6 @@ export default class NetworkController extends EventEmitter { log.info('NetworkController - configureInfuraProvider', type) const networkClient = createInfuraClient({ network: type, - onRequest: (req) => this.emit('rpc-req', { network: type, req }), }) this._setNetworkClient(networkClient) // setup networkConfig diff --git a/app/scripts/lib/setupMetamaskMeshMetrics.js b/app/scripts/lib/setupMetamaskMeshMetrics.js deleted file mode 100644 index 81e5f5e4f..000000000 --- a/app/scripts/lib/setupMetamaskMeshMetrics.js +++ /dev/null @@ -1,31 +0,0 @@ - -export default setupMetamaskMeshMetrics - -/** - * Injects an iframe into the current document for testing - */ -function setupMetamaskMeshMetrics () { - const testingContainer = document.createElement('iframe') - const targetOrigin = 'https://metamask.github.io' - const targetUrl = `${targetOrigin}/mesh-testing/` - testingContainer.src = targetUrl - - let didLoad = false - testingContainer.addEventListener('load', () => { - didLoad = true - }) - - console.log('Injecting MetaMask Mesh testing client') - document.head.appendChild(testingContainer) - - return { submitMeshMetricsEntry } - - function submitMeshMetricsEntry (message) { - // ignore if we haven't loaded yet - if (!didLoad) { - return - } - // submit the message - testingContainer.contentWindow.postMessage(message, targetOrigin) - } -} From f7aea9597bdd27e5cc91a12807ede50f4f88fa84 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 14 Jan 2020 15:21:02 -0400 Subject: [PATCH 124/689] `await` all clicks during e2e tests (#7815) The `.click()` function returns a Promise, as it needs to communicate with the browser and ensure the click was successfully sent. --- test/e2e/address-book.spec.js | 8 ++++---- test/e2e/ethereum-on.spec.js | 6 +++--- test/e2e/from-import-ui.spec.js | 6 +++--- test/e2e/incremental-security.spec.js | 6 +++--- test/e2e/metamask-responsive-ui.spec.js | 6 +++--- test/e2e/metamask-ui.spec.js | 12 ++++++------ test/e2e/permissions.spec.js | 6 +++--- test/e2e/send-edit.spec.js | 6 +++--- test/e2e/threebox.spec.js | 16 ++++++++-------- test/e2e/web3.spec.js | 6 +++--- 10 files changed, 39 insertions(+), 39 deletions(-) diff --git a/test/e2e/address-book.spec.js b/test/e2e/address-book.spec.js index d3cadf169..1ce1635f8 100644 --- a/test/e2e/address-book.spec.js +++ b/test/e2e/address-book.spec.js @@ -56,19 +56,19 @@ describe('MetaMask', function () { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - welcomeScreenBtn.click() + await welcomeScreenBtn.click() await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) - customRpcButton.click() + await customRpcButton.click() await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { const optOutButton = await driver.findElement(By.css('.btn-default')) - optOutButton.click() + await optOutButton.click() await driver.delay(largeDelayMs) }) @@ -161,7 +161,7 @@ describe('MetaMask', function () { await passwordInputs[0].sendKeys('correct horse battery staple') await passwordInputs[1].sendKeys('correct horse battery staple') const restoreButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.restore.message}')]`)) - restoreButton.click() + await restoreButton.click() await driver.delay(regularDelayMs) }) diff --git a/test/e2e/ethereum-on.spec.js b/test/e2e/ethereum-on.spec.js index 41a5f5c22..0347bee9e 100644 --- a/test/e2e/ethereum-on.spec.js +++ b/test/e2e/ethereum-on.spec.js @@ -55,19 +55,19 @@ describe('MetaMask', function () { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - welcomeScreenBtn.click() + await welcomeScreenBtn.click() await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) - customRpcButton.click() + await customRpcButton.click() await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { const optOutButton = await driver.findElement(By.css('.btn-default')) - optOutButton.click() + await optOutButton.click() await driver.delay(largeDelayMs) }) diff --git a/test/e2e/from-import-ui.spec.js b/test/e2e/from-import-ui.spec.js index 3f1b68e73..d5fa0684c 100644 --- a/test/e2e/from-import-ui.spec.js +++ b/test/e2e/from-import-ui.spec.js @@ -60,19 +60,19 @@ describe('Using MetaMask with an existing account', function () { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - welcomeScreenBtn.click() + await welcomeScreenBtn.click() await driver.delay(largeDelayMs) }) it('clicks the "Import Wallet" option', async () => { const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) - customRpcButton.click() + await customRpcButton.click() await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { const optOutButton = await driver.findElement(By.css('.btn-default')) - optOutButton.click() + await optOutButton.click() await driver.delay(largeDelayMs) }) diff --git a/test/e2e/incremental-security.spec.js b/test/e2e/incremental-security.spec.js index 0b75653c2..f3708c1e1 100644 --- a/test/e2e/incremental-security.spec.js +++ b/test/e2e/incremental-security.spec.js @@ -60,19 +60,19 @@ describe('MetaMask', function () { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - welcomeScreenBtn.click() + await welcomeScreenBtn.click() await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) - customRpcButton.click() + await customRpcButton.click() await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { const optOutButton = await driver.findElement(By.css('.btn-default')) - optOutButton.click() + await optOutButton.click() await driver.delay(largeDelayMs) }) diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index d014011a2..8f991579c 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -50,19 +50,19 @@ describe('MetaMask', function () { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - welcomeScreenBtn.click() + await welcomeScreenBtn.click() await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) - customRpcButton.click() + await customRpcButton.click() await driver.delay(largeDelayMs) }) it('clicks the "I agree" option on the metametrics opt-in screen', async () => { const optOutButton = await driver.findElement(By.css('.btn-primary')) - optOutButton.click() + await optOutButton.click() await driver.delay(largeDelayMs) }) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index 047865e8a..b0eea8703 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -51,19 +51,19 @@ describe('MetaMask', function () { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - welcomeScreenBtn.click() + await welcomeScreenBtn.click() await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) - customRpcButton.click() + await customRpcButton.click() await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { const optOutButton = await driver.findElement(By.css('.btn-default')) - optOutButton.click() + await optOutButton.click() await driver.delay(largeDelayMs) }) @@ -196,7 +196,7 @@ describe('MetaMask', function () { describe('Import seed phrase', () => { it('logs out of the vault', async () => { const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) - accountMenuButton.click() + await accountMenuButton.click() await driver.delay(regularDelayMs) const logoutButton = await driver.findElement(By.css('.account-menu__logout-button')) @@ -406,7 +406,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) const settingsButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Settings')]`)) - settingsButton.click() + await settingsButton.click() // await driver.findElement(By.css('.tab-bar')) @@ -989,7 +989,7 @@ describe('MetaMask', function () { assert(confirmDataText.match(/0xa9059cbb0000000000000000000000002f318c334780961fb129d2a6c30d0763d9a5c97/)) const detailsTab = await driver.findElement(By.xpath(`//li[contains(text(), 'Details')]`)) - detailsTab.click() + await detailsTab.click() await driver.delay(regularDelayMs) }) diff --git a/test/e2e/permissions.spec.js b/test/e2e/permissions.spec.js index bb15dfab6..780a8f5d7 100644 --- a/test/e2e/permissions.spec.js +++ b/test/e2e/permissions.spec.js @@ -55,19 +55,19 @@ describe('MetaMask', function () { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - welcomeScreenBtn.click() + await welcomeScreenBtn.click() await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) - customRpcButton.click() + await customRpcButton.click() await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { const optOutButton = await driver.findElement(By.css('.btn-default')) - optOutButton.click() + await optOutButton.click() await driver.delay(largeDelayMs) }) diff --git a/test/e2e/send-edit.spec.js b/test/e2e/send-edit.spec.js index 6bad4494d..1f8ed96bb 100644 --- a/test/e2e/send-edit.spec.js +++ b/test/e2e/send-edit.spec.js @@ -57,19 +57,19 @@ describe('Using MetaMask with an existing account', function () { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - welcomeScreenBtn.click() + await welcomeScreenBtn.click() await driver.delay(largeDelayMs) }) it('clicks the "Import Wallet" option', async () => { const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) - customRpcButton.click() + await customRpcButton.click() await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { const optOutButton = await driver.findElement(By.css('.btn-default')) - optOutButton.click() + await optOutButton.click() await driver.delay(largeDelayMs) }) diff --git a/test/e2e/threebox.spec.js b/test/e2e/threebox.spec.js index a9599f887..a7c8c18fe 100644 --- a/test/e2e/threebox.spec.js +++ b/test/e2e/threebox.spec.js @@ -60,19 +60,19 @@ describe('MetaMask', function () { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - welcomeScreenBtn.click() + await welcomeScreenBtn.click() await driver.delay(largeDelayMs) }) it('clicks the "Import Wallet" option', async () => { const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) - customRpcButton.click() + await customRpcButton.click() await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { const optOutButton = await driver.findElement(By.css('.btn-default')) - optOutButton.click() + await optOutButton.click() await driver.delay(largeDelayMs) }) @@ -115,7 +115,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) const settingsButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Settings')]`)) - settingsButton.click() + await settingsButton.click() }) it('turns on threebox syncing', async () => { @@ -183,19 +183,19 @@ describe('MetaMask', function () { it('clicks the continue button on the welcome screen', async () => { await driver2.findElement(By.css('.welcome-page__header')) const welcomeScreenBtn = await driver2.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - welcomeScreenBtn.click() + await welcomeScreenBtn.click() await driver2.delay(largeDelayMs) }) it('clicks the "Import Wallet" option', async () => { const customRpcButton = await driver2.findElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) - customRpcButton.click() + await customRpcButton.click() await driver2.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { const optOutButton = await driver2.findElement(By.css('.btn-default')) - optOutButton.click() + await optOutButton.click() await driver2.delay(largeDelayMs) }) @@ -244,7 +244,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) const settingsButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Settings')]`)) - settingsButton.click() + await settingsButton.click() }) it('finds the blockies toggle turned on', async () => { diff --git a/test/e2e/web3.spec.js b/test/e2e/web3.spec.js index b7704e463..0f2c25262 100644 --- a/test/e2e/web3.spec.js +++ b/test/e2e/web3.spec.js @@ -56,19 +56,19 @@ describe('Using MetaMask with an existing account', function () { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - welcomeScreenBtn.click() + await welcomeScreenBtn.click() await driver.delay(largeDelayMs) }) it('clicks the "Import Wallet" option', async () => { const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) - customRpcButton.click() + await customRpcButton.click() await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { const optOutButton = await driver.findElement(By.css('.btn-default')) - optOutButton.click() + await optOutButton.click() await driver.delay(largeDelayMs) }) From 8b0c95cbb18941373a5004c0a3cd5ba97af2cec5 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 14 Jan 2020 17:45:54 -0330 Subject: [PATCH 125/689] Add required props for AdvancedTab component tests (#7819) --- .../tests/advanced-tab-component.test.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js b/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js index 15e5306c2..408657523 100644 --- a/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js +++ b/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js @@ -8,7 +8,15 @@ import TextField from '../../../../components/ui/text-field' describe('AdvancedTab Component', () => { it('should render correctly when threeBoxFeatureFlag', () => { const root = shallow( - , + {}} + setIpfsGateway={() => {}} + setShowFiatConversionOnTestnetsPreference={() => {}} + setThreeBoxSyncingPermission={() => {}} + threeBoxDisabled + threeBoxSyncingAllowed={false} + />, { context: { t: s => `_${s}`, @@ -23,7 +31,13 @@ describe('AdvancedTab Component', () => { const setAutoLogoutTimeLimitSpy = sinon.spy() const root = shallow( {}} + setShowFiatConversionOnTestnetsPreference={() => {}} + setThreeBoxSyncingPermission={() => {}} + threeBoxDisabled + threeBoxSyncingAllowed={false} />, { context: { From 00da0d28a0b2184dcc023fd8283a05502bfb0d10 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 14 Jan 2020 17:27:36 -0400 Subject: [PATCH 126/689] Use data attributes to reference settings in e2e tests (#7820) These rows on the Advanced Settings page were being looked up in the e2e tests by the order they appeared in. Instead they're now referenced by data id, so that we can add new settings and re-arrange them without breaking the e2e tests. --- test/e2e/metamask-ui.spec.js | 4 ++-- test/e2e/threebox.spec.js | 3 +-- .../advanced-tab/advanced-tab.component.js | 22 +++++++++---------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index b0eea8703..c2bfdb55a 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -414,13 +414,13 @@ describe('MetaMask', function () { await advancedTab.click() await driver.delay(regularDelayMs) - const showConversionToggle = await driver.findElement(By.css('.settings-page__content-row:nth-of-type(6) .settings-page__content-item-col > div > div')) + const showConversionToggle = await driver.findElement(By.css('[data-testid="advanced-setting-show-testnet-conversion"] .settings-page__content-item-col > div > div')) await showConversionToggle.click() const advancedGasTitle = await driver.findElement(By.xpath(`//span[contains(text(), 'Advanced gas controls')]`)) await driver.scrollToElement(advancedGasTitle) - const advancedGasToggle = await driver.findElement(By.css('.settings-page__content-row:nth-of-type(4) .settings-page__content-item-col > div > div')) + const advancedGasToggle = await driver.findElement(By.css('[data-testid="advanced-setting-advanced-gas-inline"] .settings-page__content-item-col > div > div')) await advancedGasToggle.click() windowHandles = await driver.getAllWindowHandles() extension = windowHandles[0] diff --git a/test/e2e/threebox.spec.js b/test/e2e/threebox.spec.js index a7c8c18fe..9167bdb5e 100644 --- a/test/e2e/threebox.spec.js +++ b/test/e2e/threebox.spec.js @@ -122,8 +122,7 @@ describe('MetaMask', function () { const advancedButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Advanced')]`)) await advancedButton.click() - const threeBoxToggle = await driver.findElements(By.css('.toggle-button')) - const threeBoxToggleButton = await threeBoxToggle[4].findElement(By.css('div')) + const threeBoxToggleButton = await driver.findElement(By.css('[data-testid="advanced-setting-3box"] .toggle-button div')) await threeBoxToggleButton.click() }) diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js index 5bb67626f..260b32b69 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js +++ b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js @@ -45,9 +45,9 @@ export default class AdvancedTab extends PureComponent { renderMobileSync () { const { t } = this.context const { history } = this.props - // + return ( -
+
{ t('syncWithMobile') }
@@ -74,7 +74,7 @@ export default class AdvancedTab extends PureComponent { const { displayWarning } = this.props return ( -
+
{ t('stateLogs') } @@ -109,7 +109,7 @@ export default class AdvancedTab extends PureComponent { const { showResetAccountConfirmationModal } = this.props return ( -
+
{ t('resetAccount') } @@ -147,7 +147,7 @@ export default class AdvancedTab extends PureComponent { const { sendHexData, setHexDataFeatureFlag } = this.props return ( -
+
{ t('showHexData') }
@@ -173,7 +173,7 @@ export default class AdvancedTab extends PureComponent { const { advancedInlineGas, setAdvancedInlineGasFeatureFlag } = this.props return ( -
+
{ t('showAdvancedGasInline') }
@@ -202,7 +202,7 @@ export default class AdvancedTab extends PureComponent { } = this.props return ( -
+
{ t('showFiatConversionInTestnets') }
@@ -228,7 +228,7 @@ export default class AdvancedTab extends PureComponent { const { useNonceField, setUseNonceField } = this.props return ( -
+
{ this.context.t('nonceField') }
@@ -276,7 +276,7 @@ export default class AdvancedTab extends PureComponent { } = this.props return ( -
+
{ t('autoLogoutTimeLimit') }
@@ -329,7 +329,7 @@ export default class AdvancedTab extends PureComponent { description = t('syncWithThreeBoxDisabled') } return ( -
+
{ t('syncWithThreeBox') }
@@ -404,7 +404,7 @@ export default class AdvancedTab extends PureComponent { const { ipfsGatewayError } = this.state return ( -
+
{ t('ipfsGateway') }
From ab7500a9407cfa5cd9db6d5a51b166f660effe3a Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 14 Jan 2020 18:23:22 -0330 Subject: [PATCH 127/689] Add required props for Send component tests (#7821) --- ui/app/pages/send/tests/send-component.test.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ui/app/pages/send/tests/send-component.test.js b/ui/app/pages/send/tests/send-component.test.js index 6e6fbe1a5..2b7a31d77 100644 --- a/ui/app/pages/send/tests/send-component.test.js +++ b/ui/app/pages/send/tests/send-component.test.js @@ -63,7 +63,12 @@ describe('Send Component', function () { tokenBalance="mockTokenBalance" tokenContract={{ method: 'mockTokenMethod' }} updateAndSetGasLimit={propsMethodSpies.updateAndSetGasLimit} + qrCodeDetected={() => {}} + scanQrCode={() => {}} + updateSendEnsResolution={() => {}} + updateSendEnsResolutionError={() => {}} updateSendErrors={propsMethodSpies.updateSendErrors} + updateSendTo={() => {}} updateSendTokenBalance={propsMethodSpies.updateSendTokenBalance} resetSendState={propsMethodSpies.resetSendState} updateToNicknameIfNecessary={propsMethodSpies.updateToNicknameIfNecessary} From 73197b43e18196e6cccbf7263c22c72d7e0bacaf Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 14 Jan 2020 23:47:56 -0330 Subject: [PATCH 128/689] Don't log Ganache Testrpc started event (#7822) --- test/helper.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/helper.js b/test/helper.js index b1f0d2ab8..0b8508d1d 100644 --- a/test/helper.js +++ b/test/helper.js @@ -13,9 +13,7 @@ enableFailureOnUnhandledPromiseRejection() // ganache server const server = Ganache.server() -server.listen(8545, () => { - console.log('Ganache Testrpc is running on "http://localhost:8545"') -}) +server.listen(8545, () => {}) log.setDefaultLevel(5) global.log = log From 74557bd68ab2591a867177e93ef43db0953f000f Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 15 Jan 2020 11:18:59 -0400 Subject: [PATCH 129/689] Delete onBlur handlers from currency and token input components (#7824) As of #7753, the `onBlur` prop is no longer used for the `token-input` and `currency-input` components, and the associated wrapper components and the shared underlying component. It as been removed from all of them. --- .../currency-input.component.js | 6 ----- .../tests/currency-input.component.test.js | 23 ++----------------- .../tests/token-input.component.test.js | 17 ++------------ .../ui/token-input/token-input.component.js | 6 ----- .../tests/unit-input.component.test.js | 21 ----------------- .../ui/unit-input/unit-input.component.js | 7 ------ 6 files changed, 4 insertions(+), 76 deletions(-) diff --git a/ui/app/components/ui/currency-input/currency-input.component.js b/ui/app/components/ui/currency-input/currency-input.component.js index 18289d4e4..398b49884 100644 --- a/ui/app/components/ui/currency-input/currency-input.component.js +++ b/ui/app/components/ui/currency-input/currency-input.component.js @@ -21,7 +21,6 @@ export default class CurrencyInput extends PureComponent { maxModeOn: PropTypes.bool, nativeCurrency: PropTypes.string, onChange: PropTypes.func, - onBlur: PropTypes.func, useFiat: PropTypes.bool, hideFiat: PropTypes.bool, value: PropTypes.string, @@ -99,10 +98,6 @@ export default class CurrencyInput extends PureComponent { onChange(hexValue) } - handleBlur = () => { - this.props.onBlur(this.state.hexValue) - } - renderConversionComponent () { const { currentCurrency, nativeCurrency, hideFiat } = this.props const { hexValue } = this.state @@ -145,7 +140,6 @@ export default class CurrencyInput extends PureComponent { {...restProps} suffix={this.shouldUseFiat() ? fiatSuffix : nativeSuffix} onChange={this.handleChange} - onBlur={this.handleBlur} value={decimalValue} maxModeOn={maxModeOn} actionComponent={( diff --git a/ui/app/components/ui/currency-input/tests/currency-input.component.test.js b/ui/app/components/ui/currency-input/tests/currency-input.component.test.js index 43fa65d3a..5c132c08c 100644 --- a/ui/app/components/ui/currency-input/tests/currency-input.component.test.js +++ b/ui/app/components/ui/currency-input/tests/currency-input.component.test.js @@ -162,7 +162,7 @@ describe('CurrencyInput Component', () => { handleBlurSpy.resetHistory() }) - it('should call onChange and onBlur on input changes with the hex value for ETH', () => { + it('should call onChange on input changes with the hex value for ETH', () => { const mockStore = { metamask: { nativeCurrency: 'ETH', @@ -175,7 +175,6 @@ describe('CurrencyInput Component', () => { { assert.equal(wrapper.find('.currency-display-component').text(), '$231.06USD') assert.equal(currencyInputInstance.state.decimalValue, 1) assert.equal(currencyInputInstance.state.hexValue, 'de0b6b3a7640000') - - assert.equal(handleBlurSpy.callCount, 0) - input.simulate('blur') - assert.equal(handleBlurSpy.callCount, 1) - assert.ok(handleBlurSpy.calledWith('de0b6b3a7640000')) }) - it('should call onChange and onBlur on input changes with the hex value for fiat', () => { + it('should call onChange on input changes with the hex value for fiat', () => { const mockStore = { metamask: { nativeCurrency: 'ETH', @@ -221,7 +215,6 @@ describe('CurrencyInput Component', () => { { assert.equal(wrapper.find('.currency-display-component').text(), '0.004328ETH') assert.equal(currencyInputInstance.state.decimalValue, 1) assert.equal(currencyInputInstance.state.hexValue, 'f602f2234d0ea') - - assert.equal(handleBlurSpy.callCount, 0) - input.simulate('blur') - assert.equal(handleBlurSpy.callCount, 1) - assert.ok(handleBlurSpy.calledWith('f602f2234d0ea')) }) it('should change the state and pass in a new decimalValue when props.value changes', () => { @@ -268,7 +256,6 @@ describe('CurrencyInput Component', () => { { { assert.equal(currencyInputInstance.state.decimalValue, 1) assert.equal(currencyInputInstance.state.hexValue, 'de0b6b3a7640000') - assert.equal(handleBlurSpy.callCount, 0) - input.simulate('blur') - assert.equal(handleBlurSpy.callCount, 1) - assert.ok(handleBlurSpy.calledWith('de0b6b3a7640000')) - const swap = wrapper.find('.currency-input__swap-component') swap.simulate('click') assert.equal(wrapper.find('.currency-display-component').text(), '0.004328ETH') diff --git a/ui/app/components/ui/token-input/tests/token-input.component.test.js b/ui/app/components/ui/token-input/tests/token-input.component.test.js index 881101880..37fcf3e68 100644 --- a/ui/app/components/ui/token-input/tests/token-input.component.test.js +++ b/ui/app/components/ui/token-input/tests/token-input.component.test.js @@ -212,7 +212,7 @@ describe('TokenInput Component', () => { handleBlurSpy.resetHistory() }) - it('should call onChange and onBlur on input changes with the hex value for ETH', () => { + it('should call onChange on input changes with the hex value for ETH', () => { const mockStore = { metamask: { currentCurrency: 'usd', @@ -224,7 +224,6 @@ describe('TokenInput Component', () => { { assert.equal(wrapper.find('.currency-display-component').text(), '2ETH') assert.equal(tokenInputInstance.state.decimalValue, 1) assert.equal(tokenInputInstance.state.hexValue, '2710') - - assert.equal(handleBlurSpy.callCount, 0) - input.simulate('blur') - assert.equal(handleBlurSpy.callCount, 1) - assert.ok(handleBlurSpy.calledWith('2710')) }) - it('should call onChange and onBlur on input changes with the hex value for fiat', () => { + it('should call onChange on input changes with the hex value for fiat', () => { const mockStore = { metamask: { currentCurrency: 'usd', @@ -272,7 +266,6 @@ describe('TokenInput Component', () => { { assert.equal(wrapper.find('.currency-display-component').text(), '$462.12USD') assert.equal(tokenInputInstance.state.decimalValue, 1) assert.equal(tokenInputInstance.state.hexValue, '2710') - - assert.equal(handleBlurSpy.callCount, 0) - input.simulate('blur') - assert.equal(handleBlurSpy.callCount, 1) - assert.ok(handleBlurSpy.calledWith('2710')) }) it('should change the state and pass in a new decimalValue when props.value changes', () => { @@ -321,7 +309,6 @@ describe('TokenInput Component', () => { { - this.props.onBlur && this.props.onBlur(this.state.hexValue) - } - renderConversionComponent () { const { selectedTokenExchangeRate, showFiat, currentCurrency, hideConversion } = this.props const { decimalValue } = this.state @@ -135,7 +130,6 @@ export default class TokenInput extends PureComponent { {...restProps} suffix={suffix} onChange={this.handleChange} - onBlur={this.handleBlur} value={decimalValue} > { this.renderConversionComponent() } diff --git a/ui/app/components/ui/unit-input/tests/unit-input.component.test.js b/ui/app/components/ui/unit-input/tests/unit-input.component.test.js index 97d987bc7..6b8dec7c8 100644 --- a/ui/app/components/ui/unit-input/tests/unit-input.component.test.js +++ b/ui/app/components/ui/unit-input/tests/unit-input.component.test.js @@ -92,27 +92,6 @@ describe('UnitInput Component', () => { assert.equal(wrapper.state('value'), 123) }) - it('should call onBlur on blur with the value', () => { - const wrapper = mount( - - ) - - assert.ok(wrapper) - assert.equal(handleChangeSpy.callCount, 0) - assert.equal(handleBlurSpy.callCount, 0) - const input = wrapper.find('input') - input.simulate('change', { target: { value: 123 } }) - assert.equal(handleChangeSpy.callCount, 1) - assert.ok(handleChangeSpy.calledWith(123)) - assert.equal(wrapper.state('value'), 123) - input.simulate('blur') - assert.equal(handleBlurSpy.callCount, 1) - assert.ok(handleBlurSpy.calledWith(123)) - }) - it('should set the component state value with props.value', () => { const wrapper = mount( { - const { onBlur } = this.props - typeof onBlur === 'function' && onBlur(this.state.value) - } - getInputWidth (value) { const valueString = String(value) const valueLength = valueString.length || 1 @@ -86,7 +80,6 @@ export default class UnitInput extends PureComponent { value={value} placeholder={placeholder} onChange={this.handleChange} - onBlur={this.handleBlur} style={{ width: this.getInputWidth(value) }} ref={ref => { this.unitInput = ref From 2525e5edaa5cda99cf919c03f83d11de3b1ef97d Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 15 Jan 2020 13:24:15 -0330 Subject: [PATCH 130/689] Fix usages of sinon deprecated APIs in MetaMaskController tests (#7827) --- test/unit/app/controllers/metamask-controller-test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index 02a1de661..c4a6e4a8b 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -10,9 +10,9 @@ import createTxMeta from '../../../lib/createTxMeta' import EthQuery from 'eth-query' const threeBoxSpies = { - init: sinon.spy(), + init: sinon.stub(), getThreeBoxSyncingState: sinon.stub().returns(true), - turnThreeBoxSyncingOn: sinon.spy(), + turnThreeBoxSyncingOn: sinon.stub(), _registerUpdates: sinon.spy(), } import proxyquire from 'proxyquire' From d0536ba9844245f48e19dfded4d790776426e792 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 15 Jan 2020 13:27:51 -0330 Subject: [PATCH 131/689] Return promises from accountImporter tests (#7826) --- test/unit/app/account-import-strategies.spec.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unit/app/account-import-strategies.spec.js b/test/unit/app/account-import-strategies.spec.js index ab7b0136d..1a8953bc1 100644 --- a/test/unit/app/account-import-strategies.spec.js +++ b/test/unit/app/account-import-strategies.spec.js @@ -13,25 +13,25 @@ describe('Account Import Strategies', function () { }) it('throws an error for empty string private key', async () => { - assert.rejects(async function () { + return assert.rejects(async function () { await accountImporter.importAccount('Private Key', [ '' ]) }, Error, 'no empty strings') }) it('throws an error for undefined string private key', async () => { - assert.rejects(async function () { + return assert.rejects(async function () { await accountImporter.importAccount('Private Key', [ undefined ]) }) }) it('throws an error for undefined string private key', async () => { - assert.rejects(async function () { + return assert.rejects(async function () { await accountImporter.importAccount('Private Key', []) }) }) it('throws an error for invalid private key', async () => { - assert.rejects(async function () { + return assert.rejects(async function () { await accountImporter.importAccount('Private Key', [ 'popcorn' ]) }) }) From c53a40c45fc3cd79522cc28af161e8db3c6a9e4a Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 15 Jan 2020 13:28:23 -0330 Subject: [PATCH 132/689] Add required props & fix propTypes for SendFooter tests (#7825) --- .../tests/send-footer-component.test.js | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/ui/app/pages/send/send-footer/tests/send-footer-component.test.js b/ui/app/pages/send/send-footer/tests/send-footer-component.test.js index b286f7caf..bda82711c 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-component.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-component.test.js @@ -44,7 +44,7 @@ describe('SendFooter Component', function () { to="mockTo" toAccounts={['mockAccount']} tokenBalance="mockTokenBalance" - unapprovedTxs={['mockTx']} + unapprovedTxs={{}} update={propsMethodSpies.update} sendErrors={{}} /> @@ -87,36 +87,36 @@ describe('SendFooter Component', function () { }, 'should return true if gasTotal is falsy': { inError: false, - gasTotal: false, + gasTotal: '', expectedResult: true, gasIsLoading: false, }, 'should return true if to is truthy': { to: '0xsomevalidAddress', inError: false, - gasTotal: false, + gasTotal: '', expectedResult: true, gasIsLoading: false, }, 'should return true if selectedToken is truthy and tokenBalance is falsy': { - selectedToken: true, - tokenBalance: null, + selectedToken: { mockProp: 'mockSelectedTokenProp' }, + tokenBalance: '', expectedResult: true, gasIsLoading: false, }, 'should return true if gasIsLoading is truthy but all other params are falsy': { inError: false, - gasTotal: null, + gasTotal: '', selectedToken: null, - tokenBalance: 0, + tokenBalance: '', expectedResult: true, gasIsLoading: true, }, 'should return false if inError is false and all other params are truthy': { inError: false, gasTotal: '0x123', - selectedToken: true, - tokenBalance: 123, + selectedToken: { mockProp: 'mockSelectedTokenProp' }, + tokenBalance: '123', expectedResult: false, gasIsLoading: false, }, @@ -154,7 +154,7 @@ describe('SendFooter Component', function () { gasPrice: 'mockGasPrice', selectedToken: { mockProp: 'mockSelectedTokenProp' }, to: 'mockTo', - unapprovedTxs: ['mockTx'], + unapprovedTxs: {}, } ) }) @@ -197,7 +197,7 @@ describe('SendFooter Component', function () { describe('render', () => { beforeEach(() => { - sinon.stub(SendFooter.prototype, 'formShouldBeDisabled').returns('formShouldBeDisabledReturn') + sinon.stub(SendFooter.prototype, 'formShouldBeDisabled').returns(true) wrapper = shallow(( ), { context: { t: str => str, metricsEvent: () => ({}) } }) @@ -237,7 +237,7 @@ describe('SendFooter Component', function () { onSubmit, disabled, } = wrapper.find(PageContainerFooter).props() - assert.equal(disabled, 'formShouldBeDisabledReturn') + assert.equal(disabled, true) assert.equal(SendFooter.prototype.onSubmit.callCount, 0) onSubmit(MOCK_EVENT) From be08cfec0c07ff8f4108f2d29b77885b30d61ae7 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 15 Jan 2020 15:34:15 -0400 Subject: [PATCH 133/689] Wait until element is clickable before clicking in e2e tests (#7823) * Wait until element is clickable before clicking in e2e tests A new `findClickableElement` has been added to the webdriver to allow finding an element and blocking until it's both visible and enabled. This is now used by the pre-existing `clickElement` method as well. All cases where something is clicked in the e2e tests have been updated to use one of these methods, to ensure we don't run into intermittent failures when loading screens take longer than usual. --- test/e2e/address-book.spec.js | 69 ++-- test/e2e/ethereum-on.spec.js | 40 +-- test/e2e/from-import-ui.spec.js | 107 +++---- test/e2e/incremental-security.spec.js | 46 +-- test/e2e/metamask-responsive-ui.spec.js | 65 ++-- test/e2e/metamask-ui.spec.js | 405 ++++++++---------------- test/e2e/permissions.spec.js | 50 +-- test/e2e/send-edit.spec.js | 45 +-- test/e2e/signature-request.spec.js | 21 +- test/e2e/threebox.spec.js | 76 ++--- test/e2e/web3.spec.js | 40 +-- test/e2e/webdriver/driver.js | 29 +- 12 files changed, 347 insertions(+), 646 deletions(-) diff --git a/test/e2e/address-book.spec.js b/test/e2e/address-book.spec.js index 1ce1635f8..8b6ef3310 100644 --- a/test/e2e/address-book.spec.js +++ b/test/e2e/address-book.spec.js @@ -55,35 +55,29 @@ describe('MetaMask', function () { describe('Going through the first time flow', () => { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) - const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - await welcomeScreenBtn.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { - const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) - await customRpcButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await driver.findElement(By.css('.btn-default')) - await optOutButton.click() + await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) it('accepts a secure password', async () => { const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) - const button = await driver.findElement(By.css('.first-time-flow__form button')) await passwordBox.sendKeys('correct horse battery staple') await passwordBoxConfirm.sendKeys('correct horse battery staple') - const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) - await tosCheckBox.click() - - await button.click() + await driver.clickElement(By.css('.first-time-flow__checkbox')) + await driver.clickElement(By.css('.first-time-flow__form button')) await driver.delay(regularDelayMs) }) @@ -91,8 +85,7 @@ describe('MetaMask', function () { it('reveals the seed phrase', async () => { const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button') - const revealSeedPhraseButton = await driver.findElement(byRevealButton, 10000) - await revealSeedPhraseButton.click() + await driver.clickElement(byRevealButton) await driver.delay(regularDelayMs) const revealedSeedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')) @@ -100,16 +93,13 @@ describe('MetaMask', function () { assert.equal(seedPhrase.split(' ').length, 12) await driver.delay(regularDelayMs) - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) await driver.delay(regularDelayMs) }) async function clickWordAndWait (word) { const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]` - const word0 = await driver.findElement(By.xpath(xpath)) - - await word0.click() + await driver.clickElement(By.xpath(xpath)) await driver.delay(tinyDelayMs) } @@ -120,33 +110,30 @@ describe('MetaMask', function () { await clickWordAndWait(word) } - const confirm = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirm.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(regularDelayMs) }) it('clicks through the success screen', async () => { await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) - await doneButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver.delay(regularDelayMs) }) }) describe('Import seed phrase', () => { it('logs out of the vault', async () => { - const accountMenu = await driver.findElement(By.css('.account-menu__icon')) - await accountMenu.click() + await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const logoutButton = await driver.findElement(By.css('.account-menu__logout-button')) + const logoutButton = await driver.findClickableElement(By.css('.account-menu__logout-button')) assert.equal(await logoutButton.getText(), 'Log out') await logoutButton.click() await driver.delay(regularDelayMs) }) it('imports seed phrase', async () => { - const restoreSeedLink = await driver.findElement(By.css('.unlock-page__link--import')) + const restoreSeedLink = await driver.findClickableElement(By.css('.unlock-page__link--import')) assert.equal(await restoreSeedLink.getText(), 'Import using account seed phrase') await restoreSeedLink.click() await driver.delay(regularDelayMs) @@ -160,8 +147,7 @@ describe('MetaMask', function () { await passwordInputs[0].sendKeys('correct horse battery staple') await passwordInputs[1].sendKeys('correct horse battery staple') - const restoreButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.restore.message}')]`)) - await restoreButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.restore.message}')]`)) await driver.delay(regularDelayMs) }) @@ -174,24 +160,21 @@ describe('MetaMask', function () { describe('Adds an entry to the address book and sends eth to that address', () => { it('starts a send transaction', async function () { - const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) - await sendButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') await driver.delay(regularDelayMs) - const addToAddressBookButton = await driver.findElement(By.css('.dialog.send__dialog.dialog--message')) - await addToAddressBookButton.click() + await driver.clickElement(By.css('.dialog.send__dialog.dialog--message')) const addressBookAddModal = await driver.findElement(By.css('span .modal')) await driver.findElement(By.css('.add-to-address-book-modal')) const addressBookInput = await driver.findElement(By.css('.add-to-address-book-modal__input')) await addressBookInput.sendKeys('Test Name 1') await driver.delay(tinyDelayMs) - const addressBookSaveButton = await driver.findElement(By.css('.add-to-address-book-modal__footer .btn-primary')) - await addressBookSaveButton.click() + await driver.clickElement(By.css('.add-to-address-book-modal__footer .btn-primary')) await driver.wait(until.stalenessOf(addressBookAddModal)) @@ -203,14 +186,12 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) // Continue to next screen - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) await driver.delay(regularDelayMs) }) it('confirms the transaction', async function () { - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(largeDelayMs * 2) }) @@ -227,16 +208,14 @@ describe('MetaMask', function () { describe('Sends to an address book entry', () => { it('starts a send transaction by clicking address book entry', async function () { - const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) - await sendButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) - const recipientRow = await driver.findElement(By.css('.send__select-recipient-wrapper__group-item')) const recipientRowTitle = await driver.findElement(By.css('.send__select-recipient-wrapper__group-item__title')) const recipientRowTitleString = await recipientRowTitle.getText() assert.equal(recipientRowTitleString, 'Test Name 1') - await recipientRow.click() + await driver.clickElement(By.css('.send__select-recipient-wrapper__group-item')) await driver.delay(regularDelayMs) const inputAmount = await driver.findElement(By.css('.unit-input__input')) @@ -244,14 +223,12 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) // Continue to next screen - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) await driver.delay(regularDelayMs) }) it('confirms the transaction', async function () { - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(largeDelayMs * 2) }) diff --git a/test/e2e/ethereum-on.spec.js b/test/e2e/ethereum-on.spec.js index 0347bee9e..30bacf16a 100644 --- a/test/e2e/ethereum-on.spec.js +++ b/test/e2e/ethereum-on.spec.js @@ -54,45 +54,37 @@ describe('MetaMask', function () { describe('Going through the first time flow, but skipping the seed phrase challenge', () => { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) - const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - await welcomeScreenBtn.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { - const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) - await customRpcButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await driver.findElement(By.css('.btn-default')) - await optOutButton.click() + await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) it('accepts a secure password', async () => { const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) - const button = await driver.findElement(By.css('.first-time-flow__form button')) await passwordBox.sendKeys('correct horse battery staple') await passwordBoxConfirm.sendKeys('correct horse battery staple') - const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) - await tosCheckBox.click() - - await button.click() + await driver.clickElement(By.css('.first-time-flow__checkbox')) + await driver.clickElement(By.css('.first-time-flow__form button')) await driver.delay(largeDelayMs) }) it('skips the seed phrase challenge', async () => { - const button = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) - await button.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) await driver.delay(regularDelayMs) - const detailsButton = await driver.findElement(By.css('.account-details__details-button')) - await detailsButton.click() + await driver.clickElement(By.css('.account-details__details-button')) await driver.delay(regularDelayMs) }) @@ -101,8 +93,7 @@ describe('MetaMask', function () { publicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) - const accountModalClose = await driver.findElement(By.css('.account-modal-close')) - await accountModalClose.click() + await driver.clickElement(By.css('.account-modal-close')) await driver.wait(until.stalenessOf(accountModal)) await driver.delay(regularDelayMs) @@ -119,8 +110,7 @@ describe('MetaMask', function () { await driver.openNewPage('http://127.0.0.1:8080/') await driver.delay(regularDelayMs) - const connectButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Connect')]`)) - await connectButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Connect')]`)) await driver.delay(regularDelayMs) @@ -135,11 +125,9 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) - const accountButton = await driver.findElement(By.css('.permissions-connect-choose-account__account')) - await accountButton.click() + await driver.clickElement(By.css('.permissions-connect-choose-account__account')) - const submitButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Submit')]`)) - await submitButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Submit')]`)) await driver.waitUntilXWindowHandles(2) await driver.switchToWindow(dapp) @@ -155,12 +143,10 @@ describe('MetaMask', function () { it('changes the network', async () => { await driver.switchToWindow(extension) - const networkDropdown = await driver.findElement(By.css('.network-name')) - await networkDropdown.click() + await driver.clickElement(By.css('.network-name')) await driver.delay(regularDelayMs) - const ropstenButton = await driver.findElement(By.xpath(`//span[contains(text(), 'Ropsten')]`)) - await ropstenButton.click() + await driver.clickElement(By.xpath(`//span[contains(text(), 'Ropsten')]`)) await driver.delay(largeDelayMs) }) diff --git a/test/e2e/from-import-ui.spec.js b/test/e2e/from-import-ui.spec.js index d5fa0684c..fa8e117a2 100644 --- a/test/e2e/from-import-ui.spec.js +++ b/test/e2e/from-import-ui.spec.js @@ -59,20 +59,17 @@ describe('Using MetaMask with an existing account', function () { describe('First time flow starting from an existing seed phrase', () => { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) - const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - await welcomeScreenBtn.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) it('clicks the "Import Wallet" option', async () => { - const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) - await customRpcButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await driver.findElement(By.css('.btn-default')) - await optOutButton.click() + await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) @@ -86,46 +83,39 @@ describe('Using MetaMask with an existing account', function () { const [confirmPassword] = await driver.findElements(By.id('confirm-password')) confirmPassword.sendKeys('correct horse battery staple') - const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) - await tosCheckBox.click() + await driver.clickElement(By.css('.first-time-flow__checkbox')) - const [importButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Import')]`)) - await importButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Import')]`)) await driver.delay(regularDelayMs) }) it('clicks through the success screen', async () => { await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) - await doneButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver.delay(regularDelayMs) }) }) describe('Show account information', () => { it('shows the correct account address', async () => { - const accountDetailsButton = await driver.findElement(By.css('.account-details__details-button')) - await accountDetailsButton.click() + await driver.clickElement(By.css('.account-details__details-button')) await driver.findVisibleElement(By.css('.qr-wrapper')) await driver.delay(regularDelayMs) const [address] = await driver.findElements(By.css('input.qr-ellip-address')) assert.equal(await address.getAttribute('value'), testAddress) - const accountModalClose = await driver.findElement(By.css('.account-modal-close')) - await accountModalClose.click() + await driver.clickElement(By.css('.account-modal-close')) await driver.delay(largeDelayMs) }) it('shows a QR code for the account', async () => { - const accountDetailsButton = await driver.findElement(By.css('.account-details__details-button')) - await accountDetailsButton.click() + await driver.clickElement(By.css('.account-details__details-button')) await driver.findVisibleElement(By.css('.qr-wrapper')) const detailModal = await driver.findElement(By.css('span .modal')) await driver.delay(regularDelayMs) - const accountModalClose = await driver.findElement(By.css('.account-modal-close')) - await accountModalClose.click() + await driver.clickElement(By.css('.account-modal-close')) await driver.wait(until.stalenessOf(detailModal)) await driver.delay(regularDelayMs) }) @@ -133,11 +123,10 @@ describe('Using MetaMask with an existing account', function () { describe('Log out and log back in', () => { it('logs out of the account', async () => { - const accountIdenticon = await driver.findElement(By.css('.account-menu__icon .identicon')) - await accountIdenticon.click() + await driver.clickElement(By.css('.account-menu__icon .identicon')) await driver.delay(regularDelayMs) - const [logoutButton] = await driver.findElements(By.css('.account-menu__logout-button')) + const logoutButton = await driver.findClickableElement(By.css('.account-menu__logout-button')) assert.equal(await logoutButton.getText(), 'Log out') await logoutButton.click() await driver.delay(regularDelayMs) @@ -153,22 +142,18 @@ describe('Using MetaMask with an existing account', function () { describe('Add an account', () => { it('switches to localhost', async () => { - const networkDropdown = await driver.findElement(By.css('.network-name')) - await networkDropdown.click() + await driver.clickElement(By.css('.network-name')) await driver.delay(regularDelayMs) - const [localhost] = await driver.findElements(By.xpath(`//span[contains(text(), 'Localhost')]`)) - await localhost.click() + await driver.clickElement(By.xpath(`//span[contains(text(), 'Localhost')]`)) await driver.delay(largeDelayMs) }) it('choose Create Account from the account menu', async () => { - const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) - await accountMenuButton.click() + await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const [createAccount] = await driver.findElements(By.xpath(`//div[contains(text(), 'Create Account')]`)) - await createAccount.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'Create Account')]`)) await driver.delay(regularDelayMs) }) @@ -177,8 +162,7 @@ describe('Using MetaMask with an existing account', function () { await accountName.sendKeys('2nd account') await driver.delay(regularDelayMs) - const [createButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Create')]`)) - await createButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Create')]`)) await driver.delay(regularDelayMs) }) @@ -191,20 +175,17 @@ describe('Using MetaMask with an existing account', function () { describe('Switch back to original account', () => { it('chooses the original account from the account menu', async () => { - const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) - await accountMenuButton.click() + await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const [originalAccountMenuItem] = await driver.findElements(By.css('.account-menu__name')) - await originalAccountMenuItem.click() + await driver.clickElement(By.css('.account-menu__name')) await driver.delay(regularDelayMs) }) }) describe('Send ETH from inside MetaMask', () => { it('starts a send transaction', async function () { - const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) - await sendButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) @@ -214,25 +195,21 @@ describe('Using MetaMask with an existing account', function () { await inputAmount.sendKeys('1') // Set the gas limit - const configureGas = await driver.findElement(By.css('.advanced-gas-options-btn')) - await configureGas.click() + await driver.clickElement(By.css('.advanced-gas-options-btn')) await driver.delay(regularDelayMs) const gasModal = await driver.findElement(By.css('span .modal')) - const save = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await save.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) await driver.wait(until.stalenessOf(gasModal)) await driver.delay(regularDelayMs) // Continue to next screen - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) await driver.delay(regularDelayMs) }) it('confirms the transaction', async function () { - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(regularDelayMs) }) @@ -250,12 +227,10 @@ describe('Using MetaMask with an existing account', function () { describe('Imports an account with private key', () => { it('choose Create Account from the account menu', async () => { - const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) - await accountMenuButton.click() + await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const [importAccount] = await driver.findElements(By.xpath(`//div[contains(text(), 'Import Account')]`)) - await importAccount.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'Import Account')]`)) await driver.delay(regularDelayMs) }) @@ -263,8 +238,7 @@ describe('Using MetaMask with an existing account', function () { const privateKeyInput = await driver.findElement(By.css('#private-key-box')) await privateKeyInput.sendKeys(testPrivateKey2) await driver.delay(regularDelayMs) - const importButtons = await driver.findElements(By.xpath(`//button[contains(text(), 'Import')]`)) - await importButtons[0].click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Import')]`)) await driver.delay(regularDelayMs) }) @@ -283,12 +257,10 @@ describe('Using MetaMask with an existing account', function () { describe('Imports and removes an account', () => { it('choose Create Account from the account menu', async () => { - const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) - await accountMenuButton.click() + await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const [importAccount] = await driver.findElements(By.xpath(`//div[contains(text(), 'Import Account')]`)) - await importAccount.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'Import Account')]`)) await driver.delay(regularDelayMs) }) @@ -296,8 +268,7 @@ describe('Using MetaMask with an existing account', function () { const privateKeyInput = await driver.findElement(By.css('#private-key-box')) await privateKeyInput.sendKeys(testPrivateKey3) await driver.delay(regularDelayMs) - const importButtons = await driver.findElements(By.xpath(`//button[contains(text(), 'Import')]`)) - await importButtons[0].click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Import')]`)) await driver.delay(regularDelayMs) }) @@ -306,23 +277,20 @@ describe('Using MetaMask with an existing account', function () { assert.equal(await accountName.getText(), 'Account 5') await driver.delay(regularDelayMs) - const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) - await accountMenuButton.click() + await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) const accountListItems = await driver.findElements(By.css('.account-menu__account')) assert.equal(accountListItems.length, 5) - const removeAccountIcons = await driver.findElements(By.css('.remove-account-icon')) - await removeAccountIcons[1].click() + await driver.clickElement(By.css('.account-menu__account:last-of-type > .remove-account-icon')) await driver.delay(tinyDelayMs) await driver.findElement(By.css('.confirm-remove-account__account')) }) it('should remove the account', async () => { - const removeButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Remove')]`)) - await removeButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Remove')]`)) await driver.delay(regularDelayMs) @@ -337,17 +305,14 @@ describe('Using MetaMask with an existing account', function () { describe('Connects to a Hardware wallet', () => { it('choose Connect Hardware Wallet from the account menu', async () => { - const [connectAccount] = await driver.findElements(By.xpath(`//div[contains(text(), 'Connect Hardware Wallet')]`)) - await connectAccount.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'Connect Hardware Wallet')]`)) await driver.delay(regularDelayMs) }) it('should open the TREZOR Connect popup', async () => { - const trezorButton = await driver.findElements(By.css('.hw-connect__btn')) - await trezorButton[1].click() + await driver.clickElement(By.css('.hw-connect__btn:nth-of-type(2)')) await driver.delay(regularDelayMs) - const connectButtons = await driver.findElements(By.xpath(`//button[contains(text(), 'Connect')]`)) - await connectButtons[0].click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Connect')]`)) await driver.delay(regularDelayMs) const allWindows = await driver.getAllWindowHandles() assert.equal(allWindows.length, 2) diff --git a/test/e2e/incremental-security.spec.js b/test/e2e/incremental-security.spec.js index f3708c1e1..197c94152 100644 --- a/test/e2e/incremental-security.spec.js +++ b/test/e2e/incremental-security.spec.js @@ -59,45 +59,38 @@ describe('MetaMask', function () { describe('Going through the first time flow, but skipping the seed phrase challenge', () => { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) - const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - await welcomeScreenBtn.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { - const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) - await customRpcButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await driver.findElement(By.css('.btn-default')) - await optOutButton.click() + await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) it('accepts a secure password', async () => { const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) - const button = await driver.findElement(By.css('.first-time-flow__form button')) await passwordBox.sendKeys('correct horse battery staple') await passwordBoxConfirm.sendKeys('correct horse battery staple') - const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) - await tosCheckBox.click() + await driver.clickElement(By.css('.first-time-flow__checkbox')) - await button.click() + await driver.clickElement(By.css('.first-time-flow__form button')) await driver.delay(regularDelayMs) }) it('skips the seed phrase challenge', async () => { - const button = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) - await button.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) await driver.delay(regularDelayMs) - const detailsButton = await driver.findElement(By.css('.account-details__details-button')) - await detailsButton.click() + await driver.clickElement(By.css('.account-details__details-button')) await driver.delay(regularDelayMs) }) @@ -107,8 +100,7 @@ describe('MetaMask', function () { const accountModal = await driver.findElement(By.css('span .modal')) - const accountModalClose = await driver.findElement(By.css('.account-modal-close')) - await accountModalClose.click() + await driver.clickElement(By.css('.account-modal-close')) await driver.wait(until.stalenessOf(accountModal)) await driver.delay(regularDelayMs) @@ -132,8 +124,7 @@ describe('MetaMask', function () { await addressInput.sendKeys(publicAddress) await driver.delay(regularDelayMs) - const sendButton = await driver.findElement(By.css('#send')) - await sendButton.click() + await driver.clickElement(By.css('#send')) const txStatus = await driver.findElement(By.css('#success')) await driver.wait(until.elementTextMatches(txStatus, /Success/), 15000) @@ -159,8 +150,7 @@ describe('MetaMask', function () { }) it('should take the user to the seedphrase backup screen', async () => { - const backupButton = await driver.findElement(By.css('.home-notification__accept-button')) - await backupButton.click() + await driver.clickElement(By.css('.home-notification__accept-button')) await driver.delay(regularDelayMs) }) @@ -168,8 +158,7 @@ describe('MetaMask', function () { it('reveals the seed phrase', async () => { const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button') - const revealSeedPhraseButton = await driver.findElement(byRevealButton) - await revealSeedPhraseButton.click() + await driver.clickElement(byRevealButton) await driver.delay(regularDelayMs) const revealedSeedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')) @@ -177,16 +166,13 @@ describe('MetaMask', function () { assert.equal(seedPhrase.split(' ').length, 12) await driver.delay(regularDelayMs) - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) await driver.delay(regularDelayMs) }) async function clickWordAndWait (word) { const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]` - const word0 = await driver.findElement(By.xpath(xpath)) - - await word0.click() + await driver.clickElement(By.xpath(xpath)) await driver.delay(tinyDelayMs) } @@ -197,14 +183,12 @@ describe('MetaMask', function () { await clickWordAndWait(word) } - const confirm = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirm.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(regularDelayMs) }) it('can click through the success screen', async () => { - const confirm = await driver.findElement(By.xpath(`//button[contains(text(), 'All Done')]`)) - await confirm.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'All Done')]`)) await driver.delay(regularDelayMs) }) diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index 8f991579c..b06c11f8e 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -49,35 +49,30 @@ describe('MetaMask', function () { describe('Going through the first time flow', () => { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) - const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - await welcomeScreenBtn.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { - const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) - await customRpcButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) await driver.delay(largeDelayMs) }) it('clicks the "I agree" option on the metametrics opt-in screen', async () => { - const optOutButton = await driver.findElement(By.css('.btn-primary')) - await optOutButton.click() + await driver.clickElement(By.css('.btn-primary')) await driver.delay(largeDelayMs) }) it('accepts a secure password', async () => { const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) - const button = await driver.findElement(By.css('.first-time-flow__form button')) await passwordBox.sendKeys('correct horse battery staple') await passwordBoxConfirm.sendKeys('correct horse battery staple') - const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) - await tosCheckBox.click() + await driver.clickElement(By.css('.first-time-flow__checkbox')) - await button.click() + await driver.clickElement(By.css('.first-time-flow__form button')) await driver.delay(regularDelayMs) }) @@ -85,8 +80,7 @@ describe('MetaMask', function () { it('reveals the seed phrase', async () => { const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button') - const revealSeedPhraseButton = await driver.findElement(byRevealButton) - await revealSeedPhraseButton.click() + await driver.clickElement(byRevealButton) await driver.delay(regularDelayMs) const revealedSeedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')) @@ -94,16 +88,13 @@ describe('MetaMask', function () { assert.equal(seedPhrase.split(' ').length, 12) await driver.delay(regularDelayMs) - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) await driver.delay(regularDelayMs) }) async function clickWordAndWait (word) { const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]` - const word0 = await driver.findElement(By.xpath(xpath)) - - await word0.click() + await driver.clickElement(By.xpath(xpath)) await driver.delay(tinyDelayMs) } @@ -114,23 +105,20 @@ describe('MetaMask', function () { await clickWordAndWait(word) } - const confirm = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirm.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(regularDelayMs) }) it('clicks through the success screen', async () => { await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) - await doneButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver.delay(regularDelayMs) }) }) describe('Show account information', () => { it('show account details dropdown menu', async () => { - const openInBrowser = await driver.findElement(By.css('div.menu-bar__open-in-browser')) - await openInBrowser.click() + await driver.clickElement(By.css('div.menu-bar__open-in-browser')) const options = await driver.findElements(By.css('div.menu.account-details-dropdown div.menu__item')) assert.equal(options.length, 4) // HD Wallet type does not have to show the Remove Account option await driver.delay(regularDelayMs) @@ -139,18 +127,17 @@ describe('MetaMask', function () { describe('Import seed phrase', () => { it('logs out of the vault', async () => { - const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) - await accountMenuButton.click() + await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const logoutButton = await driver.findElement(By.css('.account-menu__logout-button')) + const logoutButton = await driver.findClickableElement(By.css('.account-menu__logout-button')) assert.equal(await logoutButton.getText(), 'Log out') await logoutButton.click() await driver.delay(regularDelayMs) }) it('imports seed phrase', async () => { - const restoreSeedLink = await driver.findElement(By.css('.unlock-page__link--import')) + const restoreSeedLink = await driver.findClickableElement(By.css('.unlock-page__link--import')) assert.equal(await restoreSeedLink.getText(), 'Import using account seed phrase') await restoreSeedLink.click() await driver.delay(regularDelayMs) @@ -164,18 +151,15 @@ describe('MetaMask', function () { await passwordInputs[0].sendKeys('correct horse battery staple') await passwordInputs[1].sendKeys('correct horse battery staple') - const restoreButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.restore.message}')]`)) - await restoreButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.restore.message}')]`)) await driver.delay(regularDelayMs) }) it('switches to localhost', async () => { - const networkDropdown = await driver.findElement(By.css('.network-name')) - await networkDropdown.click() + await driver.clickElement(By.css('.network-name')) await driver.delay(regularDelayMs) - const [localhost] = await driver.findElements(By.xpath(`//span[contains(text(), 'Localhost')]`)) - await localhost.click() + await driver.clickElement(By.xpath(`//span[contains(text(), 'Localhost')]`)) await driver.delay(largeDelayMs * 2) }) @@ -188,8 +172,7 @@ describe('MetaMask', function () { describe('Send ETH from inside MetaMask', () => { it('starts to send a transaction', async function () { - const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) - await sendButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) @@ -205,28 +188,24 @@ describe('MetaMask', function () { it('opens and closes the gas modal', async function () { // Set the gas limit - const configureGas = await driver.findElement(By.css('.advanced-gas-options-btn')) - await configureGas.click() + await driver.clickElement(By.css('.advanced-gas-options-btn')) await driver.delay(regularDelayMs) const gasModal = await driver.findElement(By.css('span .modal')) - const save = await driver.findElement(By.css('.page-container__header-close-text')) - await save.click() + await driver.clickElement(By.css('.page-container__header-close-text')) await driver.wait(until.stalenessOf(gasModal), 10000) await driver.delay(regularDelayMs) }) it('clicks through to the confirm screen', async function () { // Continue to next screen - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) await driver.delay(regularDelayMs) }) it('confirms the transaction', async function () { - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(largeDelayMs) }) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index c2bfdb55a..3433d68ed 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -50,35 +50,30 @@ describe('MetaMask', function () { describe('Going through the first time flow', () => { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) - const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - await welcomeScreenBtn.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { - const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) - await customRpcButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await driver.findElement(By.css('.btn-default')) - await optOutButton.click() + await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) it('accepts a secure password', async () => { const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) - const button = await driver.findElement(By.css('.first-time-flow__form button')) await passwordBox.sendKeys('correct horse battery staple') await passwordBoxConfirm.sendKeys('correct horse battery staple') - const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) - await tosCheckBox.click() + await driver.clickElement(By.css('.first-time-flow__checkbox')) - await button.click() + await driver.clickElement(By.css('.first-time-flow__form button')) await driver.delay(regularDelayMs) }) @@ -87,8 +82,7 @@ describe('MetaMask', function () { it('reveals the seed phrase', async () => { const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button') await driver.findElement(byRevealButton) - const revealSeedPhraseButton = await driver.findElement(byRevealButton) - await revealSeedPhraseButton.click() + await driver.clickElement(byRevealButton) await driver.delay(regularDelayMs) const revealedSeedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')) @@ -96,16 +90,13 @@ describe('MetaMask', function () { assert.equal(seedPhrase.split(' ').length, 12) await driver.delay(regularDelayMs) - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`)) await driver.delay(regularDelayMs) }) async function clickWordAndWait (word) { const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]` - const word0 = await driver.findElement(By.xpath(xpath)) - - await word0.click() + await driver.clickElement(By.xpath(xpath)) await driver.delay(tinyDelayMs) } @@ -116,29 +107,25 @@ describe('MetaMask', function () { await clickWordAndWait(word) } - const confirm = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirm.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(regularDelayMs) }) it('clicks through the success screen', async () => { await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) - await doneButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver.delay(regularDelayMs) }) }) describe('Show account information', () => { it('shows the QR code for the account', async () => { - const accountDetailsButton = await driver.findElement(By.css('.account-details__details-button')) - await accountDetailsButton.click() + await driver.clickElement(By.css('.account-details__details-button')) await driver.findVisibleElement(By.css('.qr-wrapper')) await driver.delay(regularDelayMs) const accountModal = await driver.findElement(By.css('span .modal')) - const accountModalClose = await driver.findElement(By.css('.account-modal-close')) - await accountModalClose.click() + await driver.clickElement(By.css('.account-modal-close')) await driver.wait(until.stalenessOf(accountModal)) await driver.delay(regularDelayMs) @@ -147,11 +134,10 @@ describe('MetaMask', function () { describe('Log out an log back in', () => { it('logs out of the account', async () => { - const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) - await accountMenuButton.click() + await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const logoutButton = await driver.findElement(By.css('.account-menu__logout-button')) + const logoutButton = await driver.findClickableElement(By.css('.account-menu__logout-button')) assert.equal(await logoutButton.getText(), 'Log out') await logoutButton.click() await driver.delay(regularDelayMs) @@ -167,12 +153,10 @@ describe('MetaMask', function () { describe('Add account', () => { it('choose Create Account from the account menu', async () => { - const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) - await accountMenuButton.click() + await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const createAccount = await driver.findElement(By.xpath(`//div[contains(text(), 'Create Account')]`)) - await createAccount.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'Create Account')]`)) await driver.delay(regularDelayMs) }) @@ -181,8 +165,7 @@ describe('MetaMask', function () { await accountName.sendKeys('2nd account') await driver.delay(regularDelayMs) - const create = await driver.findElement(By.xpath(`//button[contains(text(), 'Create')]`)) - await create.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Create')]`)) await driver.delay(largeDelayMs) }) @@ -195,18 +178,17 @@ describe('MetaMask', function () { describe('Import seed phrase', () => { it('logs out of the vault', async () => { - const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) - await accountMenuButton.click() + await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const logoutButton = await driver.findElement(By.css('.account-menu__logout-button')) + const logoutButton = await driver.findClickableElement(By.css('.account-menu__logout-button')) assert.equal(await logoutButton.getText(), 'Log out') await logoutButton.click() await driver.delay(regularDelayMs) }) it('imports seed phrase', async () => { - const restoreSeedLink = await driver.findElement(By.css('.unlock-page__link--import')) + const restoreSeedLink = await driver.findClickableElement(By.css('.unlock-page__link--import')) assert.equal(await restoreSeedLink.getText(), 'Import using account seed phrase') await restoreSeedLink.click() await driver.delay(regularDelayMs) @@ -220,8 +202,7 @@ describe('MetaMask', function () { await passwordInputs[0].sendKeys('correct horse battery staple') await passwordInputs[1].sendKeys('correct horse battery staple') - const restoreButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.restore.message}')]`)) - await restoreButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.restore.message}')]`)) await driver.delay(regularDelayMs) }) @@ -234,8 +215,7 @@ describe('MetaMask', function () { describe('Send ETH from inside MetaMask using default gas', () => { it('starts a send transaction', async function () { - const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) - await sendButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) @@ -256,7 +236,7 @@ describe('MetaMask', function () { await driver.assertElementNotPresent(By.css('.send-v2__error-amount')) - const amountMax = await driver.findElement(By.css('.send-v2__amount-max')) + const amountMax = await driver.findClickableElement(By.css('.send-v2__amount-max')) await amountMax.click() assert.equal(await inputAmount.isEnabled(), false) @@ -276,14 +256,12 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) // Continue to next screen - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) await driver.delay(regularDelayMs) }) it('confirms the transaction', async function () { - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(largeDelayMs * 2) }) @@ -300,8 +278,7 @@ describe('MetaMask', function () { describe('Send ETH from inside MetaMask using fast gas option', () => { it('starts a send transaction', async function () { - const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) - await sendButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) @@ -314,19 +291,16 @@ describe('MetaMask', function () { assert.equal(inputValue, '1') // Set the gas price - const fastGas = await driver.findElement(By.xpath(`//button/div/div[contains(text(), "Fast")]`)) - await fastGas.click() + await driver.clickElement(By.xpath(`//button/div/div[contains(text(), "Fast")]`)) await driver.delay(regularDelayMs) // Continue to next screen - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) await driver.delay(regularDelayMs) }) it('confirms the transaction', async function () { - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(largeDelayMs) }) @@ -343,8 +317,7 @@ describe('MetaMask', function () { describe('Send ETH from inside MetaMask using advanced gas modal', () => { it('starts a send transaction', async function () { - const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) - await sendButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) @@ -357,19 +330,16 @@ describe('MetaMask', function () { assert.equal(inputValue, '1') // Set the gas limit - const configureGas = await driver.findElement(By.css('.advanced-gas-options-btn')) - await configureGas.click() + await driver.clickElement(By.css('.advanced-gas-options-btn')) await driver.delay(regularDelayMs) const gasModal = await driver.findElement(By.css('span .modal')) - const save = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await save.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) await driver.wait(until.stalenessOf(gasModal)) await driver.delay(regularDelayMs) // Continue to next screen - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) await driver.delay(regularDelayMs) }) @@ -378,8 +348,7 @@ describe('MetaMask', function () { const transactionAmount = transactionAmounts[0] assert.equal(await transactionAmount.getText(), '1') - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(largeDelayMs) }) @@ -401,33 +370,27 @@ describe('MetaMask', function () { let dapp it('goes to the settings screen', async () => { - const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) - await accountMenuButton.click() + await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const settingsButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Settings')]`)) - await settingsButton.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'Settings')]`)) // await driver.findElement(By.css('.tab-bar')) - const advancedTab = await driver.findElement(By.xpath(`//div[contains(text(), 'Advanced')]`)) - await advancedTab.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'Advanced')]`)) await driver.delay(regularDelayMs) - const showConversionToggle = await driver.findElement(By.css('[data-testid="advanced-setting-show-testnet-conversion"] .settings-page__content-item-col > div > div')) - await showConversionToggle.click() + await driver.clickElement(By.css('[data-testid="advanced-setting-show-testnet-conversion"] .settings-page__content-item-col > div > div')) const advancedGasTitle = await driver.findElement(By.xpath(`//span[contains(text(), 'Advanced gas controls')]`)) await driver.scrollToElement(advancedGasTitle) - const advancedGasToggle = await driver.findElement(By.css('[data-testid="advanced-setting-advanced-gas-inline"] .settings-page__content-item-col > div > div')) - await advancedGasToggle.click() + await driver.clickElement(By.css('[data-testid="advanced-setting-advanced-gas-inline"] .settings-page__content-item-col > div > div')) windowHandles = await driver.getAllWindowHandles() extension = windowHandles[0] await driver.closeAllWindowHandlesExcept([extension]) - const metamaskHomeButton = await driver.findElement(By.css('.app-header__logo-container')) - await metamaskHomeButton.click() + await driver.clickElement(By.css('.app-header__logo-container')) await driver.delay(largeDelayMs) }) @@ -436,8 +399,7 @@ describe('MetaMask', function () { await driver.openNewPage('http://127.0.0.1:8080/') await driver.delay(regularDelayMs) - const connectButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Connect')]`)) - await connectButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Connect')]`)) await driver.delay(regularDelayMs) @@ -452,11 +414,9 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) - const accountButton = await driver.findElement(By.css('.permissions-connect-choose-account__account')) - await accountButton.click() + await driver.clickElement(By.css('.permissions-connect-choose-account__account')) - const submitButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Submit')]`)) - await submitButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Submit')]`)) await driver.waitUntilXWindowHandles(2) await driver.switchToWindow(dapp) @@ -464,8 +424,7 @@ describe('MetaMask', function () { }) it('initiates a send from the dapp', async () => { - const send3eth = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`), 10000) - await send3eth.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`), 10000) await driver.delay(2000) windowHandles = await driver.getAllWindowHandles() @@ -491,8 +450,7 @@ describe('MetaMask', function () { await driver.delay(1000) - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`), 10000) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`), 10000) await driver.delay(regularDelayMs) await driver.waitUntilXWindowHandles(2) @@ -500,39 +458,24 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - let txValues - it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) return confirmedTxes.length === 4 }, 10000) - txValues = await driver.findElements(By.css('.transaction-list-item__amount--primary')) - await driver.wait(until.elementTextMatches(txValues[0], /-3\s*ETH/), 10000) + const txValue = await driver.findClickableElement(By.css('.transaction-list-item__amount--primary')) + await driver.wait(until.elementTextMatches(txValue, /-3\s*ETH/), 10000) }) it('the transaction has the expected gas price', async function () { - await driver.delay(largeDelayMs) - let txGasPriceLabels - let txGasPrices - try { - await txValues[0].click() - txGasPrices = await driver.findElements(By.css('.transaction-breakdown__value')) - txGasPriceLabels = await driver.findElements(By.css('.transaction-breakdown-row__title')) - txGasPrices = await driver.findElements(By.css('.transaction-breakdown__value')) - await driver.wait(until.elementTextMatches(txGasPrices[3], /^10$/), 10000) - } catch (e) { - console.log(e.message) - txValues = await driver.findElements(By.css('.transaction-list-item__amount--primary')) - await txValues[0].click() - txGasPriceLabels = await driver.findElements(By.css('.transaction-breakdown-row__title')) - txGasPrices = await driver.findElements(By.css('.transaction-breakdown__value')) - await driver.wait(until.elementTextMatches(txGasPrices[3], /^10$/), 10000) - } + const txValue = await driver.findClickableElement(By.css('.transaction-list-item__amount--primary')) + await txValue.click() + const txGasPrices = await driver.findElements(By.css('.transaction-breakdown__value')) + const txGasPriceLabels = await driver.findElements(By.css('.transaction-breakdown-row__title')) + await driver.wait(until.elementTextMatches(txGasPrices[3], /^10$/), 10000) assert(txGasPriceLabels[2]) - - await txValues[0].click() + await txValue.click() }) }) @@ -548,11 +491,11 @@ describe('MetaMask', function () { await driver.switchToWindow(dapp) await driver.delay(largeDelayMs) - const send3eth = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) + const send3eth = await driver.findClickableElement(By.xpath(`//button[contains(text(), 'Send')]`)) await send3eth.click() await driver.delay(largeDelayMs) - const contractDeployment = await driver.findElement(By.xpath(`//button[contains(text(), 'Deploy Contract')]`)) + const contractDeployment = await driver.findClickableElement(By.xpath(`//button[contains(text(), 'Deploy Contract')]`)) await contractDeployment.click() await driver.delay(largeDelayMs) @@ -564,16 +507,8 @@ describe('MetaMask', function () { await driver.switchToWindow(extension) await driver.delay(regularDelayMs) - let transactions = await driver.findElements(By.css('.transaction-list-item')) - await transactions[0].click() - await driver.delay(regularDelayMs) - try { - transactions = await driver.findElements(By.css('.transaction-list-item')) - await transactions[0].click() - } catch (e) { - console.log(e) - } - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.transaction-list-item')) + await driver.delay(largeDelayMs) }) it('navigates the transactions', async () => { @@ -625,8 +560,7 @@ describe('MetaMask', function () { await driver.switchToWindow(dapp) await driver.delay(regularDelayMs) - const send3eth = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) - await send3eth.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) await driver.switchToWindow(extension) @@ -639,8 +573,7 @@ describe('MetaMask', function () { it('rejects a transaction', async () => { await driver.delay(tinyDelayMs) - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Reject')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Reject')]`)) await driver.delay(largeDelayMs * 2) const navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) @@ -651,9 +584,7 @@ describe('MetaMask', function () { it('confirms a transaction', async () => { await driver.delay(tinyDelayMs / 2) - const rejectButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await driver.delay(tinyDelayMs / 2) - await rejectButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(regularDelayMs) const navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) @@ -664,12 +595,10 @@ describe('MetaMask', function () { }) it('rejects the rest of the transactions', async () => { - const rejectAllButton = await driver.findElement(By.xpath(`//a[contains(text(), 'Reject 3')]`)) - await rejectAllButton.click() + await driver.clickElement(By.xpath(`//a[contains(text(), 'Reject 3')]`)) await driver.delay(regularDelayMs) - const rejectButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Reject All')]`)) - await rejectButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Reject All')]`)) await driver.delay(largeDelayMs * 2) const confirmedTxes = await driver.findElements(By.css('.transaction-list__completed-transactions .transaction-list-item')) @@ -689,21 +618,18 @@ describe('MetaMask', function () { await driver.switchToWindow(dapp) await driver.delay(regularDelayMs) - const deployContractButton = await driver.findElement(By.css('#deployButton')) - await deployContractButton.click() + await driver.clickElement(By.css('#deployButton')) await driver.delay(regularDelayMs) await driver.switchToWindow(extension) await driver.delay(regularDelayMs) - const txListItem = await driver.findElement(By.xpath(`//div[contains(text(), 'Contract Deployment')]`)) - await txListItem.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'Contract Deployment')]`)) await driver.delay(largeDelayMs) }) it('displays the contract creation data', async () => { - const dataTab = await driver.findElement(By.xpath(`//li[contains(text(), 'Data')]`)) - await dataTab.click() + await driver.clickElement(By.xpath(`//li[contains(text(), 'Data')]`)) await driver.delay(regularDelayMs) await driver.findElement(By.xpath(`//div[contains(text(), '127.0.0.1')]`)) @@ -712,14 +638,12 @@ describe('MetaMask', function () { const confirmDataText = await confirmDataDiv.getText() assert.equal(confirmDataText.match(/0x608060405234801561001057600080fd5b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff/)) - const detailsTab = await driver.findElement(By.xpath(`//li[contains(text(), 'Details')]`)) - await detailsTab.click() + await driver.clickElement(By.xpath(`//li[contains(text(), 'Details')]`)) await driver.delay(regularDelayMs) }) it('confirms a deploy contract transaction', async () => { - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(largeDelayMs) await driver.wait(async () => { @@ -739,8 +663,7 @@ describe('MetaMask', function () { let contractStatus = await driver.findElement(By.css('#contractStatus')) await driver.wait(until.elementTextMatches(contractStatus, /Deployed/), 15000) - const depositButton = await driver.findElement(By.css('#depositButton')) - await depositButton.click() + await driver.clickElement(By.css('#depositButton')) await driver.delay(largeDelayMs) contractStatus = await driver.findElement(By.css('#contractStatus')) @@ -750,20 +673,18 @@ describe('MetaMask', function () { await driver.delay(largeDelayMs * 2) await driver.findElements(By.css('.transaction-list-item')) - const [txListValue] = await driver.findElements(By.css('.transaction-list-item__amount--primary')) + const txListValue = await driver.findClickableElement(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txListValue, /-4\s*ETH/), 10000) await txListValue.click() await driver.delay(regularDelayMs) // Set the gas limit - const configureGas = await driver.findElement(By.css('.confirm-detail-row__header-text--edit')) - await configureGas.click() + await driver.clickElement(By.css('.confirm-detail-row__header-text--edit')) await driver.delay(regularDelayMs) const gasModal = await driver.findElement(By.css('span .modal')) await driver.delay(regularDelayMs) - const modalTabs = await driver.findElements(By.css('.page-container__tab')) - await modalTabs[1].click() + await driver.clickElement(By.css('.page-container__tab:nth-of-type(2)')) await driver.delay(regularDelayMs) const [gasPriceInput, gasLimitInput] = await driver.findElements(By.css('.advanced-gas-inputs__gas-edit-row__input')) @@ -784,14 +705,12 @@ describe('MetaMask', function () { await driver.delay(1000) - const save = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await save.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) await driver.delay(regularDelayMs) await driver.wait(until.stalenessOf(gasModal)) - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(regularDelayMs) await driver.wait(async () => { @@ -807,19 +726,16 @@ describe('MetaMask', function () { await driver.switchToWindow(dapp) await driver.delay(regularDelayMs) - const withdrawButton = await driver.findElement(By.css('#withdrawButton')) - await withdrawButton.click() + await driver.clickElement(By.css('#withdrawButton')) await driver.delay(regularDelayMs) await driver.switchToWindow(extension) await driver.delay(largeDelayMs * 2) - const txListItem = await driver.findElement(By.css('.transaction-list-item')) - await txListItem.click() + await driver.clickElement(By.css('.transaction-list-item')) await driver.delay(regularDelayMs) - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(regularDelayMs) await driver.wait(async () => { @@ -854,8 +770,7 @@ describe('MetaMask', function () { await driver.switchToWindow(dapp) await driver.delay(regularDelayMs * 2) - const createToken = await driver.findElement(By.xpath(`//button[contains(text(), 'Create Token')]`)) - await createToken.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Create Token')]`)) await driver.delay(largeDelayMs) windowHandles = await driver.getAllWindowHandles() @@ -863,24 +778,20 @@ describe('MetaMask', function () { await driver.switchToWindow(popup) await driver.delay(regularDelayMs) - const configureGas = await driver.findElement(By.css('.confirm-detail-row__header-text--edit')) - await configureGas.click() + await driver.clickElement(By.css('.confirm-detail-row__header-text--edit')) await driver.delay(regularDelayMs) - const advancedTabButton = await driver.findElement(By.xpath(`//li[contains(text(), 'Advanced')]`)) - await advancedTabButton.click() + await driver.clickElement(By.xpath(`//li[contains(text(), 'Advanced')]`)) await driver.delay(tinyDelayMs) const [gasPriceInput, gasLimitInput] = await driver.findElements(By.css('.advanced-gas-inputs__gas-edit-row__input')) assert(gasPriceInput.getAttribute('value'), 20) assert(gasLimitInput.getAttribute('value'), 4700000) - const saveButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await saveButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) await driver.delay(regularDelayMs) - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(regularDelayMs) await driver.switchToWindow(dapp) @@ -898,26 +809,22 @@ describe('MetaMask', function () { }) it('clicks on the Add Token button', async () => { - const addToken = await driver.findElement(By.xpath(`//div[contains(text(), 'Add Token')]`)) - await addToken.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'Add Token')]`)) await driver.delay(regularDelayMs) }) it('picks the newly created Test token', async () => { - const addCustomToken = await driver.findElement(By.xpath("//li[contains(text(), 'Custom Token')]")) - await addCustomToken.click() + await driver.clickElement(By.xpath("//li[contains(text(), 'Custom Token')]")) await driver.delay(regularDelayMs) const newTokenAddress = await driver.findElement(By.css('#custom-address')) await newTokenAddress.sendKeys(tokenAddress) await driver.delay(regularDelayMs) - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) await driver.delay(regularDelayMs) - const addTokens = await driver.findElement(By.xpath(`//button[contains(text(), 'Add Tokens')]`)) - await addTokens.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Add Tokens')]`)) await driver.delay(regularDelayMs) }) @@ -933,8 +840,7 @@ describe('MetaMask', function () { describe('Send token from inside MetaMask', () => { let gasModal it('starts to send a transaction', async function () { - const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) - await sendButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) @@ -944,8 +850,7 @@ describe('MetaMask', function () { await inputAmount.sendKeys('1') // Set the gas limit - const configureGas = await driver.findElement(By.css('.advanced-gas-options-btn')) - await configureGas.click() + await driver.clickElement(By.css('.advanced-gas-options-btn')) await driver.delay(regularDelayMs) gasModal = await driver.findElement(By.css('span .modal')) @@ -954,8 +859,7 @@ describe('MetaMask', function () { it('opens customize gas modal', async () => { await driver.findElement(By.css('.page-container__title')) - const save = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await save.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) await driver.delay(regularDelayMs) }) @@ -963,15 +867,12 @@ describe('MetaMask', function () { await driver.wait(until.stalenessOf(gasModal)) // Continue to next screen - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await driver.wait(until.elementIsEnabled(nextScreen)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) await driver.delay(regularDelayMs) }) it('displays the token transfer data', async () => { - const dataTab = await driver.findElement(By.xpath(`//li[contains(text(), 'Data')]`)) - await dataTab.click() + await driver.clickElement(By.xpath(`//li[contains(text(), 'Data')]`)) await driver.delay(regularDelayMs) const functionType = await driver.findElement(By.css('.confirm-page-container-content__function-type')) @@ -988,14 +889,12 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) assert(confirmDataText.match(/0xa9059cbb0000000000000000000000002f318c334780961fb129d2a6c30d0763d9a5c97/)) - const detailsTab = await driver.findElement(By.xpath(`//li[contains(text(), 'Details')]`)) - await detailsTab.click() + await driver.clickElement(By.xpath(`//li[contains(text(), 'Details')]`)) await driver.delay(regularDelayMs) }) it('submits the transaction', async function () { - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(regularDelayMs) }) @@ -1025,14 +924,13 @@ describe('MetaMask', function () { await driver.switchToWindow(dapp) await driver.delay(tinyDelayMs) - const transferTokens = await driver.findElement(By.xpath(`//button[contains(text(), 'Transfer Tokens')]`)) - await transferTokens.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Transfer Tokens')]`)) await driver.switchToWindow(extension) await driver.delay(largeDelayMs) await driver.findElements(By.css('.transaction-list__pending-transactions')) - const [txListValue] = await driver.findElements(By.css('.transaction-list-item__amount--primary')) + const txListValue = await driver.findClickableElement(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/), 10000) await txListValue.click() await driver.delay(regularDelayMs) @@ -1042,16 +940,14 @@ describe('MetaMask', function () { assert(await transactionAmount.getText(), '1.5 TST') // Set the gas limit - const configureGas = await driver.findElement(By.css('.confirm-detail-row__header-text--edit')) - await configureGas.click() + await driver.clickElement(By.css('.confirm-detail-row__header-text--edit')) await driver.delay(regularDelayMs) gasModal = await driver.findElement(By.css('span .modal')) }) it('customizes gas', async () => { - const modalTabs = await driver.findElements(By.css('.page-container__tab')) - await modalTabs[1].click() + await driver.clickElement(By.css('.page-container__tab:nth-of-type(2)')) await driver.delay(regularDelayMs) const [gasPriceInput, gasLimitInput] = await driver.findElements(By.css('.advanced-gas-inputs__gas-edit-row__input')) @@ -1070,8 +966,7 @@ describe('MetaMask', function () { await driver.delay(1000) - const save = await driver.findElement(By.css('.page-container__footer-button')) - await save.click() + await driver.clickElement(By.css('.page-container__footer-button')) await driver.wait(until.stalenessOf(gasModal)) const gasFeeInputs = await driver.findElements(By.css('.confirm-detail-row__primary')) @@ -1084,8 +979,7 @@ describe('MetaMask', function () { const tokenAmountText = await tokenAmount.getText() assert.equal(tokenAmountText, '1.5 TST') - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(regularDelayMs) }) @@ -1100,11 +994,9 @@ describe('MetaMask', function () { const txStatuses = await driver.findElements(By.css('.transaction-list-item__action')) await driver.wait(until.elementTextMatches(txStatuses[0], /Sent\sToken/), 10000) - const walletBalance = await driver.findElement(By.css('.wallet-balance')) - await walletBalance.click() + await driver.clickElement(By.css('.wallet-balance')) - const tokenListItems = await driver.findElements(By.css('.token-list-item')) - await tokenListItems[0].click() + await driver.clickElement(By.css('.token-list-item')) await driver.delay(1000) const tokenBalanceAmount = await driver.findElements(By.css('.transaction-view-balance__primary-balance')) @@ -1124,8 +1016,7 @@ describe('MetaMask', function () { await driver.switchToWindow(dapp) await driver.delay(tinyDelayMs) - const approveTokens = await driver.findElement(By.xpath(`//button[contains(text(), 'Approve Tokens')]`)) - await approveTokens.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Approve Tokens')]`)) await driver.switchToWindow(extension) await driver.delay(regularDelayMs) @@ -1135,16 +1026,14 @@ describe('MetaMask', function () { return pendingTxes.length === 1 }, 10000) - const [txListItem] = await driver.findElements(By.css('.transaction-list-item')) const [txListValue] = await driver.findElements(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txListValue, /-7\s*TST/)) - await txListItem.click() + await driver.clickElement(By.css('.transaction-list-item')) await driver.delay(regularDelayMs) }) it('displays the token approval data', async () => { - const fullTxDataButton = await driver.findElement(By.css('.confirm-approve-content__view-full-tx-button')) - await fullTxDataButton.click() + await driver.clickElement(By.css('.confirm-approve-content__view-full-tx-button')) await driver.delay(regularDelayMs) const functionType = await driver.findElement(By.css('.confirm-approve-content__data .confirm-approve-content__small-text')) @@ -1157,16 +1046,14 @@ describe('MetaMask', function () { }) it('opens the gas edit modal', async () => { - const editButtons = await driver.findElements(By.css('.confirm-approve-content__small-blue-text.cursor-pointer')) - await editButtons[0].click() + await driver.clickElement(By.css('.confirm-approve-content__small-blue-text.cursor-pointer')) await driver.delay(regularDelayMs) gasModal = await driver.findElement(By.css('span .modal')) }) it('customizes gas', async () => { - const modalTabs = await driver.findElements(By.css('.page-container__tab')) - await modalTabs[1].click() + await driver.clickElement(By.css('.page-container__tab:nth-of-type(2)')) await driver.delay(regularDelayMs) const [gasPriceInput, gasLimitInput] = await driver.findElements(By.css('.advanced-gas-inputs__gas-edit-row__input')) @@ -1185,8 +1072,7 @@ describe('MetaMask', function () { await driver.delay(1000) - const save = await driver.findElement(By.css('.page-container__footer-button')) - await save.click() + await driver.clickElement(By.css('.page-container__footer-button')) await driver.wait(until.stalenessOf(gasModal)) const gasFeeInEth = await driver.findElement(By.css('.confirm-approve-content__transaction-details-content__secondary-fee')) @@ -1194,13 +1080,13 @@ describe('MetaMask', function () { }) it('edits the permission', async () => { - const editButtons = await driver.findElements(By.css('.confirm-approve-content__small-blue-text.cursor-pointer')) + const editButtons = await driver.findClickableElements(By.css('.confirm-approve-content__small-blue-text.cursor-pointer')) await editButtons[1].click() await driver.delay(regularDelayMs) const permissionModal = await driver.findElement(By.css('span .modal')) - const radioButtons = await driver.findElements(By.css('.edit-approval-permission__edit-section__radio-button')) + const radioButtons = await driver.findClickableElements(By.css('.edit-approval-permission__edit-section__radio-button')) await radioButtons[1].click() const customInput = await driver.findElement(By.css('input')) @@ -1208,8 +1094,7 @@ describe('MetaMask', function () { await customInput.sendKeys('5') await driver.delay(regularDelayMs) - const saveButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await saveButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) await driver.delay(regularDelayMs) await driver.wait(until.stalenessOf(permissionModal)) @@ -1220,8 +1105,7 @@ describe('MetaMask', function () { }) it('submits the transaction', async function () { - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(regularDelayMs) }) @@ -1248,8 +1132,7 @@ describe('MetaMask', function () { await driver.switchToWindow(dapp) - const transferTokens = await driver.findElement(By.xpath(`//button[contains(text(), 'Transfer Tokens Without Gas')]`)) - await transferTokens.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Transfer Tokens Without Gas')]`)) await driver.switchToWindow(extension) await driver.delay(regularDelayMs) @@ -1259,17 +1142,15 @@ describe('MetaMask', function () { return pendingTxes.length === 1 }, 10000) - const [txListItem] = await driver.findElements(By.css('.transaction-list-item')) const [txListValue] = await driver.findElements(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/)) - await txListItem.click() + await driver.clickElement(By.css('.transaction-list-item')) await driver.delay(regularDelayMs) }) it('submits the transaction', async function () { await driver.delay(largeDelayMs * 2) - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(largeDelayMs * 2) }) @@ -1297,8 +1178,7 @@ describe('MetaMask', function () { await driver.switchToWindow(dapp) await driver.delay(tinyDelayMs) - const transferTokens = await driver.findElement(By.xpath(`//button[contains(text(), 'Approve Tokens Without Gas')]`)) - await transferTokens.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Approve Tokens Without Gas')]`)) await driver.switchToWindow(extension) await driver.delay(regularDelayMs) @@ -1308,16 +1188,14 @@ describe('MetaMask', function () { return pendingTxes.length === 1 }, 10000) - const [txListItem] = await driver.findElements(By.css('.transaction-list-item')) const [txListValue] = await driver.findElements(By.css('.transaction-list-item__amount--primary')) await driver.wait(until.elementTextMatches(txListValue, /-7\s*TST/)) - await txListItem.click() + await driver.clickElement(By.css('.transaction-list-item')) await driver.delay(regularDelayMs) }) it('shows the correct recipient', async function () { - const fullTxDataButton = await driver.findElement(By.css('.confirm-approve-content__view-full-tx-button')) - await fullTxDataButton.click() + await driver.clickElement(By.css('.confirm-approve-content__view-full-tx-button')) await driver.delay(regularDelayMs) const permissionInfo = await driver.findElements(By.css('.confirm-approve-content__medium-text')) @@ -1327,8 +1205,7 @@ describe('MetaMask', function () { it('submits the transaction', async function () { await driver.delay(1000) - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(regularDelayMs) }) @@ -1347,19 +1224,15 @@ describe('MetaMask', function () { describe('Hide token', () => { it('hides the token when clicked', async () => { - const [hideTokenEllipsis] = await driver.findElements(By.css('.token-list-item__ellipsis')) - await hideTokenEllipsis.click() + await driver.clickElement(By.css('.token-list-item__ellipsis')) const byTokenMenuDropdownOption = By.css('.menu__item--clickable') - const tokenMenuDropdownOption = await driver.findElement(byTokenMenuDropdownOption) - - await tokenMenuDropdownOption.click() + await driver.clickElement(byTokenMenuDropdownOption) const confirmHideModal = await driver.findElement(By.css('span .modal')) const byHideTokenConfirmationButton = By.css('.hide-token-confirmation__button') - const hideTokenConfirmationButton = await driver.findElement(byHideTokenConfirmationButton) - await hideTokenConfirmationButton.click() + await driver.clickElement(byHideTokenConfirmationButton) await driver.wait(until.stalenessOf(confirmHideModal)) }) @@ -1367,8 +1240,7 @@ describe('MetaMask', function () { describe('Add existing token using search', () => { it('clicks on the Add Token button', async () => { - const addToken = await driver.findElement(By.xpath(`//div[contains(text(), 'Add Token')]`)) - await addToken.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'Add Token')]`)) await driver.delay(regularDelayMs) }) @@ -1377,16 +1249,13 @@ describe('MetaMask', function () { await tokenSearch.sendKeys('BAT') await driver.delay(regularDelayMs) - const token = await driver.findElement(By.xpath("//span[contains(text(), 'BAT')]")) - await token.click() + await driver.clickElement(By.xpath("//span[contains(text(), 'BAT')]")) await driver.delay(regularDelayMs) - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) await driver.delay(regularDelayMs) - const addTokens = await driver.findElement(By.xpath(`//button[contains(text(), 'Add Tokens')]`)) - await addTokens.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Add Tokens')]`)) await driver.delay(largeDelayMs) }) @@ -1407,12 +1276,10 @@ describe('MetaMask', function () { customRpcUrls.forEach(customRpcUrl => { it(`creates custom RPC: ${customRpcUrl}`, async () => { - const networkDropdown = await driver.findElement(By.css('.network-name')) - await networkDropdown.click() + await driver.clickElement(By.css('.network-name')) await driver.delay(regularDelayMs) - const customRpcButton = await driver.findElement(By.xpath(`//span[contains(text(), 'Custom RPC')]`)) - await customRpcButton.click() + await driver.clickElement(By.xpath(`//span[contains(text(), 'Custom RPC')]`)) await driver.delay(regularDelayMs) await driver.findElement(By.css('.settings-page__sub-header-text')) @@ -1422,25 +1289,21 @@ describe('MetaMask', function () { await customRpcInput.clear() await customRpcInput.sendKeys(customRpcUrl) - const customRpcSave = await driver.findElement(By.css('.network-form__footer .btn-secondary')) - await customRpcSave.click() + await driver.clickElement(By.css('.network-form__footer .btn-secondary')) await driver.delay(largeDelayMs * 2) }) }) it('selects another provider', async () => { - const networkDropdown = await driver.findElement(By.css('.network-name')) - await networkDropdown.click() + await driver.clickElement(By.css('.network-name')) await driver.delay(regularDelayMs) - const customRpcButton = await driver.findElement(By.xpath(`//span[contains(text(), 'Main Ethereum Network')]`)) - await customRpcButton.click() + await driver.clickElement(By.xpath(`//span[contains(text(), 'Main Ethereum Network')]`)) await driver.delay(largeDelayMs * 2) }) it('finds all recent RPCs in history', async () => { - const networkDropdown = await driver.findElement(By.css('.network-name')) - await networkDropdown.click() + await driver.clickElement(By.css('.network-name')) await driver.delay(regularDelayMs) // only recent 3 are found and in correct order (most recent at the top) @@ -1450,20 +1313,18 @@ describe('MetaMask', function () { }) it('deletes a custom RPC', async () => { - const networkListItems = await driver.findElements(By.css('.networks-tab__networks-list-name')) + const networkListItems = await driver.findClickableElements(By.css('.networks-tab__networks-list-name')) const lastNetworkListItem = networkListItems[networkListItems.length - 1] await lastNetworkListItem.click() await driver.delay(100) - const deleteButton = await driver.findElement(By.css('.btn-danger')) - await deleteButton.click() + await driver.clickElement(By.css('.btn-danger')) await driver.delay(regularDelayMs) const confirmDeleteNetworkModal = await driver.findElement(By.css('span .modal')) const byConfirmDeleteNetworkButton = By.css('.button.btn-danger.modal-container__footer-button') - const confirmDeleteNetworkButton = await driver.findElement(byConfirmDeleteNetworkButton) - await confirmDeleteNetworkButton.click() + await driver.clickElement(byConfirmDeleteNetworkButton) await driver.wait(until.stalenessOf(confirmDeleteNetworkModal)) diff --git a/test/e2e/permissions.spec.js b/test/e2e/permissions.spec.js index 780a8f5d7..3f3d323b1 100644 --- a/test/e2e/permissions.spec.js +++ b/test/e2e/permissions.spec.js @@ -54,45 +54,38 @@ describe('MetaMask', function () { describe('Going through the first time flow, but skipping the seed phrase challenge', () => { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) - const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - await welcomeScreenBtn.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) it('clicks the "Create New Wallet" option', async () => { - const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) - await customRpcButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await driver.findElement(By.css('.btn-default')) - await optOutButton.click() + await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) it('accepts a secure password', async () => { const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) - const button = await driver.findElement(By.css('.first-time-flow__form button')) await passwordBox.sendKeys('correct horse battery staple') await passwordBoxConfirm.sendKeys('correct horse battery staple') - const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) - await tosCheckBox.click() + await driver.clickElement(By.css('.first-time-flow__checkbox')) - await button.click() + await driver.clickElement(By.css('.first-time-flow__form button')) await driver.delay(largeDelayMs) }) it('skips the seed phrase challenge', async () => { - const button = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) - await button.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) await driver.delay(regularDelayMs) - const detailsButton = await driver.findElement(By.css('.account-details__details-button')) - await detailsButton.click() + await driver.clickElement(By.css('.account-details__details-button')) await driver.delay(regularDelayMs) }) @@ -101,8 +94,7 @@ describe('MetaMask', function () { publicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) - const accountModalClose = await driver.findElement(By.css('.account-modal-close')) - await accountModalClose.click() + await driver.clickElement(By.css('.account-modal-close')) await driver.wait(until.stalenessOf(accountModal)) await driver.delay(regularDelayMs) @@ -118,8 +110,7 @@ describe('MetaMask', function () { await driver.openNewPage('http://127.0.0.1:8080/') await driver.delay(regularDelayMs) - const connectButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Connect')]`)) - await connectButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Connect')]`)) await driver.waitUntilXWindowHandles(3) const windowHandles = await driver.getAllWindowHandles() @@ -132,11 +123,9 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) - const accountButton = await driver.findElement(By.css('.permissions-connect-choose-account__account')) - await accountButton.click() + await driver.clickElement(By.css('.permissions-connect-choose-account__account')) - const submitButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Submit')]`)) - await submitButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Submit')]`)) await driver.waitUntilXWindowHandles(2) await driver.switchToWindow(extension) @@ -144,12 +133,11 @@ describe('MetaMask', function () { }) it('shows connected sites', async () => { - const connectedSites = await driver.findElement(By.xpath(`//button[contains(text(), 'Connected Sites')]`)) - await connectedSites.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Connected Sites')]`)) await driver.findElement(By.css('.connected-sites__title')) - const domains = await driver.findElements(By.css('.connected-sites-list__domain')) + const domains = await driver.findClickableElements(By.css('.connected-sites-list__domain')) assert.equal(domains.length, 1) const domainName = await driver.findElement(By.css('.connected-sites-list__domain-name')) @@ -165,8 +153,7 @@ describe('MetaMask', function () { await driver.switchToWindow(dapp) await driver.delay(regularDelayMs) - const getAccountsButton = await driver.findElement(By.xpath(`//button[contains(text(), 'eth_accounts')]`)) - await getAccountsButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'eth_accounts')]`)) const getAccountsResult = await driver.findElement(By.css('#getAccountsResult')) assert.equal((await getAccountsResult.getText()).toLowerCase(), publicAddress.toLowerCase()) @@ -175,13 +162,11 @@ describe('MetaMask', function () { it('can disconnect all accounts', async () => { await driver.switchToWindow(extension) - const disconnectAllButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Disconnect All')]`)) - await disconnectAllButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Disconnect All')]`)) const disconnectModal = await driver.findElement(By.css('span .modal')) - const disconnectAllModalButton = await driver.findElement(By.css('.disconnect-all-modal .btn-danger')) - await disconnectAllModalButton.click() + await driver.clickElement(By.css('.disconnect-all-modal .btn-danger')) await driver.wait(until.stalenessOf(disconnectModal)) await driver.delay(regularDelayMs) @@ -191,8 +176,7 @@ describe('MetaMask', function () { await driver.switchToWindow(dapp) await driver.delay(regularDelayMs) - const getAccountsButton = await driver.findElement(By.xpath(`//button[contains(text(), 'eth_accounts')]`)) - await getAccountsButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'eth_accounts')]`)) const getAccountsResult = await driver.findElement(By.css('#getAccountsResult')) assert.equal(await getAccountsResult.getText(), 'Not able to get accounts') diff --git a/test/e2e/send-edit.spec.js b/test/e2e/send-edit.spec.js index 1f8ed96bb..eb4473f60 100644 --- a/test/e2e/send-edit.spec.js +++ b/test/e2e/send-edit.spec.js @@ -56,20 +56,17 @@ describe('Using MetaMask with an existing account', function () { describe('First time flow starting from an existing seed phrase', () => { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) - const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - await welcomeScreenBtn.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) it('clicks the "Import Wallet" option', async () => { - const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) - await customRpcButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await driver.findElement(By.css('.btn-default')) - await optOutButton.click() + await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) @@ -83,26 +80,22 @@ describe('Using MetaMask with an existing account', function () { const [confirmPassword] = await driver.findElements(By.id('confirm-password')) confirmPassword.sendKeys('correct horse battery staple') - const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) - await tosCheckBox.click() + await driver.clickElement(By.css('.first-time-flow__checkbox')) - const [importButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Import')]`)) - await importButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Import')]`)) await driver.delay(regularDelayMs) }) it('clicks through the success screen', async () => { await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) - await doneButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver.delay(regularDelayMs) }) }) describe('Send ETH from inside MetaMask', () => { it('starts a send transaction', async function () { - const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`)) - await sendButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]')) @@ -112,8 +105,7 @@ describe('Using MetaMask with an existing account', function () { await inputAmount.sendKeys('1') // Set the gas limit - const configureGas = await driver.findElement(By.css('.advanced-gas-options-btn')) - await configureGas.click() + await driver.clickElement(By.css('.advanced-gas-options-btn')) await driver.delay(regularDelayMs) const gasModal = await driver.findElement(By.css('span .modal')) @@ -138,14 +130,12 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(1000) - const save = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await save.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) await driver.wait(until.stalenessOf(gasModal)) await driver.delay(regularDelayMs) // Continue to next screen - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) await driver.delay(regularDelayMs) }) @@ -159,8 +149,7 @@ describe('Using MetaMask with an existing account', function () { }) it('edits the transaction', async function () { - const editButton = await driver.findElement(By.css('.confirm-page-container-header__back-button')) - await editButton.click() + await driver.clickElement(By.css('.confirm-page-container-header__back-button')) await driver.delay(regularDelayMs) @@ -171,8 +160,7 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(50) await inputAmount.sendKeys('2.2') - const configureGas = await driver.findElement(By.css('.advanced-gas-options-btn')) - await configureGas.click() + await driver.clickElement(By.css('.advanced-gas-options-btn')) await driver.delay(regularDelayMs) const gasModal = await driver.findElement(By.css('span .modal')) @@ -196,13 +184,11 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(1000) - const save = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await save.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) await driver.wait(until.stalenessOf(gasModal)) await driver.delay(regularDelayMs) - const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await nextScreen.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) await driver.delay(regularDelayMs) }) @@ -216,8 +202,7 @@ describe('Using MetaMask with an existing account', function () { }) it('confirms the transaction', async function () { - const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(regularDelayMs) }) diff --git a/test/e2e/signature-request.spec.js b/test/e2e/signature-request.spec.js index f401d8aae..35526b973 100644 --- a/test/e2e/signature-request.spec.js +++ b/test/e2e/signature-request.spec.js @@ -69,8 +69,7 @@ describe('MetaMask', function () { await driver.openNewPage('http://127.0.0.1:8080/') await driver.delay(regularDelayMs) - const connectButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Connect')]`)) - await connectButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Connect')]`)) await driver.delay(regularDelayMs) @@ -85,19 +84,16 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) - const accountButton = await driver.findElement(By.css('.permissions-connect-choose-account__account')) - await accountButton.click() + await driver.clickElement(By.css('.permissions-connect-choose-account__account')) - const submitButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Submit')]`)) - await submitButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Submit')]`)) await driver.waitUntilXWindowHandles(2) await driver.switchToWindow(dapp) }) it('creates a sign typed data signature request', async () => { - const signTypedMessage = await driver.findElement(By.xpath(`//button[contains(text(), 'Sign')]`), 10000) - await signTypedMessage.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Sign')]`), 10000) await driver.delay(largeDelayMs) await driver.delay(regularDelayMs) @@ -117,8 +113,7 @@ describe('MetaMask', function () { }) it('signs the transaction', async () => { - const signButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Sign')]`), 10000) - await signButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Sign')]`), 10000) await driver.delay(regularDelayMs) extension = windowHandles[0] @@ -126,16 +121,14 @@ describe('MetaMask', function () { }) it('gets the current accounts address', async () => { - const detailsButton = await driver.findElement(By.css('.account-details__details-button')) - await detailsButton.click() + await driver.clickElement(By.css('.account-details__details-button')) await driver.delay(regularDelayMs) const addressInput = await driver.findElement(By.css('.qr-ellip-address')) const newPublicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) - const accountModalClose = await driver.findElement(By.css('.account-modal-close')) - await accountModalClose.click() + await driver.clickElement(By.css('.account-modal-close')) await driver.wait(until.stalenessOf(accountModal)) await driver.delay(regularDelayMs) diff --git a/test/e2e/threebox.spec.js b/test/e2e/threebox.spec.js index 9167bdb5e..664ad2084 100644 --- a/test/e2e/threebox.spec.js +++ b/test/e2e/threebox.spec.js @@ -59,20 +59,17 @@ describe('MetaMask', function () { describe('First time flow starting from an existing seed phrase', () => { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) - const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - await welcomeScreenBtn.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) it('clicks the "Import Wallet" option', async () => { - const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) - await customRpcButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await driver.findElement(By.css('.btn-default')) - await optOutButton.click() + await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) @@ -86,18 +83,15 @@ describe('MetaMask', function () { const [confirmPassword] = await driver.findElements(By.id('confirm-password')) confirmPassword.sendKeys('correct horse battery staple') - const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) - await tosCheckBox.click() + await driver.clickElement(By.css('.first-time-flow__checkbox')) - const [importButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Import')]`)) - await importButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Import')]`)) await driver.delay(regularDelayMs) }) it('clicks through the success screen', async () => { await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) - await doneButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver.delay(regularDelayMs) }) @@ -110,41 +104,32 @@ describe('MetaMask', function () { describe('turns on threebox syncing', () => { it('goes to the settings screen', async () => { - const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) - await accountMenuButton.click() + await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const settingsButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Settings')]`)) - await settingsButton.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'Settings')]`)) }) it('turns on threebox syncing', async () => { - const advancedButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Advanced')]`)) - await advancedButton.click() - - const threeBoxToggleButton = await driver.findElement(By.css('[data-testid="advanced-setting-3box"] .toggle-button div')) - await threeBoxToggleButton.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'Advanced')]`)) + await driver.clickElement(By.css('[data-testid="advanced-setting-3box"] .toggle-button div')) }) }) describe('updates settings and address book', () => { it('adds an address to the contact list', async () => { - const generalButton = await driver.findElement(By.xpath(`//div[contains(text(), 'General')]`)) - await generalButton.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'General')]`)) }) it('turns on use of blockies', async () => { - const toggleButton = await driver.findElement(By.css('.toggle-button > div')) - await toggleButton.click() + await driver.clickElement(By.css('.toggle-button > div')) }) it('adds an address to the contact list', async () => { - const contactsButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Contacts')]`)) - await contactsButton.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'Contacts')]`)) - const addressBookAddButton = await driver.findElement(By.css('.address-book-add-button__button')) - await addressBookAddButton.click() + await driver.clickElement(By.css('.address-book-add-button__button')) await driver.delay(tinyDelayMs) const addAddressInputs = await driver.findElements(By.css('input')) @@ -156,8 +141,7 @@ describe('MetaMask', function () { await driver.delay(largeDelayMs * 2) - const saveButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await saveButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) await driver.findElement(By.xpath(`//div[contains(text(), 'Test User Name 11')]`)) await driver.delay(regularDelayMs) @@ -181,20 +165,17 @@ describe('MetaMask', function () { describe('First time flow starting from an existing seed phrase', () => { it('clicks the continue button on the welcome screen', async () => { await driver2.findElement(By.css('.welcome-page__header')) - const welcomeScreenBtn = await driver2.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - await welcomeScreenBtn.click() + await driver2.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver2.delay(largeDelayMs) }) it('clicks the "Import Wallet" option', async () => { - const customRpcButton = await driver2.findElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) - await customRpcButton.click() + await driver2.clickElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) await driver2.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await driver2.findElement(By.css('.btn-default')) - await optOutButton.click() + await driver2.clickElement(By.css('.btn-default')) await driver2.delay(largeDelayMs) }) @@ -208,18 +189,15 @@ describe('MetaMask', function () { const [confirmPassword] = await driver2.findElements(By.id('confirm-password')) confirmPassword.sendKeys('correct horse battery staple') - const tosCheckBox = await driver2.findElement(By.css('.first-time-flow__checkbox')) - await tosCheckBox.click() + await driver2.clickElement(By.css('.first-time-flow__checkbox')) - const [importButton] = await driver2.findElements(By.xpath(`//button[contains(text(), 'Import')]`)) - await importButton.click() + await driver2.clickElement(By.xpath(`//button[contains(text(), 'Import')]`)) await driver2.delay(regularDelayMs) }) it('clicks through the success screen', async () => { await driver2.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await driver2.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) - await doneButton.click() + await driver2.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver2.delay(regularDelayMs) }) @@ -232,18 +210,15 @@ describe('MetaMask', function () { describe('restores 3box data', () => { it('confirms the 3box restore notification', async () => { - const restoreButton = await driver2.findElement(By.css('.home-notification__accept-button')) - await restoreButton.click() + await driver2.clickElement(By.css('.home-notification__accept-button')) }) // TODO: Fix tests from here forward; they're using the wrong driver it('goes to the settings screen', async () => { - const accountMenuButton = await driver.findElement(By.css('.account-menu__icon')) - await accountMenuButton.click() + await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const settingsButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Settings')]`)) - await settingsButton.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'Settings')]`)) }) it('finds the blockies toggle turned on', async () => { @@ -254,8 +229,7 @@ describe('MetaMask', function () { }) it('finds the restored address in the contact list', async () => { - const contactsButton = await driver.findElement(By.xpath(`//div[contains(text(), 'Contacts')]`)) - await contactsButton.click() + await driver.clickElement(By.xpath(`//div[contains(text(), 'Contacts')]`)) await driver.delay(regularDelayMs) await driver.findElement(By.xpath(`//div[contains(text(), 'Test User Name 11')]`)) diff --git a/test/e2e/web3.spec.js b/test/e2e/web3.spec.js index 0f2c25262..8312101b5 100644 --- a/test/e2e/web3.spec.js +++ b/test/e2e/web3.spec.js @@ -55,20 +55,17 @@ describe('Using MetaMask with an existing account', function () { describe('First time flow starting from an existing seed phrase', () => { it('clicks the continue button on the welcome screen', async () => { await driver.findElement(By.css('.welcome-page__header')) - const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) - await welcomeScreenBtn.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) it('clicks the "Import Wallet" option', async () => { - const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) - await customRpcButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) await driver.delay(largeDelayMs) }) it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { - const optOutButton = await driver.findElement(By.css('.btn-default')) - await optOutButton.click() + await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) @@ -82,18 +79,15 @@ describe('Using MetaMask with an existing account', function () { const [confirmPassword] = await driver.findElements(By.id('confirm-password')) confirmPassword.sendKeys('correct horse battery staple') - const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox')) - await tosCheckBox.click() + await driver.clickElement(By.css('.first-time-flow__checkbox')) - const [importButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Import')]`)) - await importButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Import')]`)) await driver.delay(regularDelayMs) }) it('clicks through the success screen', async () => { await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) - const doneButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) - await doneButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver.delay(regularDelayMs) }) }) @@ -102,12 +96,10 @@ describe('Using MetaMask with an existing account', function () { describe('opens dapp', () => { it('switches to mainnet', async () => { - const networkDropdown = await driver.findElement(By.css('.network-name')) - await networkDropdown.click() + await driver.clickElement(By.css('.network-name')) await driver.delay(regularDelayMs) - const [mainnet] = await driver.findElements(By.xpath(`//span[contains(text(), 'Main Ethereum Network')]`)) - await mainnet.click() + await driver.clickElement(By.xpath(`//span[contains(text(), 'Main Ethereum Network')]`)) await driver.delay(largeDelayMs * 2) }) @@ -115,8 +107,7 @@ describe('Using MetaMask with an existing account', function () { await driver.openNewPage('http://127.0.0.1:8080/') await driver.delay(regularDelayMs) - const connectButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Connect')]`)) - await connectButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Connect')]`)) await driver.delay(regularDelayMs) @@ -128,8 +119,7 @@ describe('Using MetaMask with an existing account', function () { const dapp = windowHandles.find(handle => handle !== extension && handle !== popup) await driver.delay(regularDelayMs) - const approveButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Connect')]`)) - await approveButton.click() + await driver.clickElement(By.xpath(`//button[contains(text(), 'Connect')]`)) await driver.switchToWindow(dapp) await driver.delay(regularDelayMs) @@ -142,7 +132,7 @@ describe('Using MetaMask with an existing account', function () { it('testing hexa methods', async () => { - const List = await driver.findElements(By.className('hexaNumberMethods')) + const List = await driver.findClickableElements(By.className('hexaNumberMethods')) for (let i = 0; i < List.length; i++) { try { @@ -163,7 +153,7 @@ describe('Using MetaMask with an existing account', function () { it('testing booleanMethods', async () => { - const List = await driver.findElements(By.className('booleanMethods')) + const List = await driver.findClickableElement(By.className('booleanMethods')) for (let i = 0; i < List.length; i++) { try { @@ -186,7 +176,7 @@ describe('Using MetaMask with an existing account', function () { it('testing transactionMethods', async () => { - const List = await driver.findElements(By.className('transactionMethods')) + const List = await driver.findClickableElement(By.className('transactionMethods')) for (let i = 0; i < List.length; i++) { try { @@ -228,7 +218,7 @@ describe('Using MetaMask with an existing account', function () { it('testing blockMethods', async () => { - const List = await driver.findElements(By.className('blockMethods')) + const List = await driver.findClickableElement(By.className('blockMethods')) for (let i = 0; i < List.length; i++) { try { @@ -254,7 +244,7 @@ describe('Using MetaMask with an existing account', function () { it('testing methods', async () => { - const List = await driver.findElements(By.className('methods')) + const List = await driver.findClickableElement(By.className('methods')) let parsedData let result diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index 9ac1063b7..3774189bf 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -38,12 +38,35 @@ class Driver { return element } - findElements (locator) { - return this.driver.wait(until.elementsLocated(locator), this.timeout) + async findClickableElement (locator) { + const element = await this.findElement(locator) + await Promise.all([ + this.driver.wait(until.elementIsVisible(element), this.timeout), + this.driver.wait(until.elementIsEnabled(element), this.timeout), + ]) + return element + } + + async findElements (locator) { + return await this.driver.wait(until.elementsLocated(locator), this.timeout) + } + + async findClickableElements (locator) { + const elements = await this.findElements(locator) + await Promise.all(elements + .reduce((acc, element) => { + acc.push( + this.driver.wait(until.elementIsVisible(element), this.timeout), + this.driver.wait(until.elementIsEnabled(element), this.timeout), + ) + return acc + }, []) + ) + return elements } async clickElement (locator) { - const element = await this.findElement(locator) + const element = await this.findClickableElement(locator) await element.click() } From 948a2ce83139e74287f6237ec70067d5a45d310b Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 15 Jan 2020 17:44:47 -0330 Subject: [PATCH 134/689] Fix prop types for SendGasRow component tests (#7833) --- .../send-gas-row/tests/send-gas-row-component.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js index f9d559549..ad2056498 100644 --- a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js +++ b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js @@ -21,7 +21,7 @@ describe('SendGasRow Component', function () { Date: Wed, 15 Jan 2020 18:24:28 -0330 Subject: [PATCH 135/689] Clean up Migrator test cases (#7835) --- app/scripts/background.js | 1 + app/scripts/lib/migrator/index.js | 1 - test/unit/migrations/migrator-test.js | 40 ++++++++++++--------------- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/app/scripts/background.js b/app/scripts/background.js index 20e05039a..7f1c13686 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -167,6 +167,7 @@ async function initialize () { async function loadStateFromPersistence () { // migrations const migrator = new Migrator({ migrations }) + migrator.on('error', console.warn) // read from disk // first from preferred, async API: diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js index 8bd6f9217..73526bbf8 100644 --- a/app/scripts/lib/migrator/index.js +++ b/app/scripts/lib/migrator/index.js @@ -52,7 +52,6 @@ class Migrator extends EventEmitter { // rewrite error message to add context without clobbering stack const originalErrorMessage = err.message err.message = `MetaMask Migration Error #${migration.version}: ${originalErrorMessage}` - console.warn(err.stack) // emit error instead of throw so as to not break the run (gracefully fail) this.emit('error', err) // stop migrating and use state as is diff --git a/test/unit/migrations/migrator-test.js b/test/unit/migrations/migrator-test.js index bd80ff957..5173f8551 100644 --- a/test/unit/migrations/migrator-test.js +++ b/test/unit/migrations/migrator-test.js @@ -60,33 +60,27 @@ describe('liveMigrations require list', () => { describe('Migrator', () => { const migrator = new Migrator({ migrations: stubMigrations }) - it('migratedData version should be version 3', (done) => { - migrator.migrateData(versionedData) - .then((migratedData) => { - assert.equal(migratedData.meta.version, stubMigrations[2].version) - done() - }).catch(done) + it('migratedData version should be version 3', async () => { + const migratedData = await migrator.migrateData(versionedData) + assert.equal(migratedData.meta.version, stubMigrations[2].version) }) - it('should match the last version in live migrations', (done) => { + it('should match the last version in live migrations', async () => { const migrator = new Migrator({ migrations: liveMigrations }) - migrator.migrateData(firstTimeState) - .then((migratedData) => { - const last = liveMigrations.length - 1 - assert.equal(migratedData.meta.version, liveMigrations[last].version) - done() - }).catch(done) + const migratedData = await migrator.migrateData(firstTimeState) + const last = liveMigrations.length - 1 + assert.equal(migratedData.meta.version, liveMigrations[last].version) }) - it('should emit an error', function (done) { - this.timeout(15000) - const migrator = new Migrator({ migrations: [{ version: 1, migrate: async () => { - throw new Error('test') - } } ] }) - migrator.on('error', () => done()) - migrator.migrateData({ meta: { version: 0 } }) - .then(() => { - }).catch(done) + it('should emit an error', async () => { + const migrator = new Migrator({ + migrations: [{ + version: 1, + async migrate () { + throw new Error('test') + }, + }], + }) + await assert.rejects(migrator.migrateData({ meta: { version: 0 } })) }) - }) From e642314ae43627b70e40e4147680cb02481f17ba Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 16 Jan 2020 00:03:37 -0330 Subject: [PATCH 136/689] Fix prop types for NetworkDropdown tests (#7837) --- .../components/app/dropdowns/tests/network-dropdown.test.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/app/components/app/dropdowns/tests/network-dropdown.test.js b/ui/app/components/app/dropdowns/tests/network-dropdown.test.js index 98cba1d2e..ec47bd0de 100644 --- a/ui/app/components/app/dropdowns/tests/network-dropdown.test.js +++ b/ui/app/components/app/dropdowns/tests/network-dropdown.test.js @@ -12,12 +12,13 @@ describe('Network Dropdown', () => { describe('NetworkDropdown in appState in false', () => { const mockState = { metamask: { + network: '1', provider: { type: 'test', }, }, appState: { - networkDropdown: false, + networkDropdownOpen: false, }, } @@ -42,6 +43,7 @@ describe('Network Dropdown', () => { describe('NetworkDropdown in appState is true', () => { const mockState = { metamask: { + network: '1', provider: { 'type': 'test', }, From dcf8eb2187b98fd55e36edcdf4677f0c34ac99ae Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 16 Jan 2020 00:03:50 -0330 Subject: [PATCH 137/689] Fix prop types for GasPriceChart tests (#7836) --- .../gas-price-chart/tests/gas-price-chart.component.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js b/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js index ca9a2007f..2204262b9 100644 --- a/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js +++ b/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js @@ -51,7 +51,7 @@ const testProps = { gasPrices: [1.5, 2.5, 4, 8], estimatedTimes: [100, 80, 40, 10], gasPricesMax: 9, - estimatedTimesMax: '100', + estimatedTimesMax: 100, currentPrice: 6, updateCustomGasPrice: propsMethodSpies.updateCustomGasPrice, } From 48c9b0174f8b513ba6e050eb04ae0d3113142841 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 16 Jan 2020 00:04:32 -0330 Subject: [PATCH 138/689] Add required props for TransactionListItemDetails tests (#7834) --- .../transaction-list-item-details.component.test.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js b/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js index 67e625b0d..2111c890d 100644 --- a/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js +++ b/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js @@ -31,6 +31,9 @@ describe('TransactionListItemDetails Component', () => { const wrapper = shallow( {}} transactionGroup={transactionGroup} />, { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } @@ -69,6 +72,9 @@ describe('TransactionListItemDetails Component', () => { const wrapper = shallow( {}} transactionGroup={transactionGroup} showSpeedUp />, @@ -102,6 +108,9 @@ describe('TransactionListItemDetails Component', () => { const wrapper = shallow( {}} transactionGroup={transactionGroup} />, { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } @@ -137,6 +146,9 @@ describe('TransactionListItemDetails Component', () => { const wrapper = shallow( {}} transactionGroup={transactionGroup} />, { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } From 4257858fb5ed8cf050e06d90e78de14cbace0541 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 16 Jan 2020 13:02:02 -0330 Subject: [PATCH 139/689] Remove extraneous console output from TransactionStateManager tests (#7838) --- .../app/controllers/transactions/tx-state-manager-test.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/unit/app/controllers/transactions/tx-state-manager-test.js b/test/unit/app/controllers/transactions/tx-state-manager-test.js index ad8ae67b2..1dbeddce0 100644 --- a/test/unit/app/controllers/transactions/tx-state-manager-test.js +++ b/test/unit/app/controllers/transactions/tx-state-manager-test.js @@ -56,10 +56,7 @@ describe('TransactionStateManager', function () { it('should emit a rejected event to signal the exciton of callback', (done) => { const tx = { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} } txStateManager.addTx(tx) - const noop = function (err) { - if (err) { - console.log('Error: ', err) - } + const noop = () => { assert(true, 'event listener has been triggered and noop executed') done() } From 8225bbe1262585f44388e305ce2ead0fe7457242 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 16 Jan 2020 13:02:44 -0400 Subject: [PATCH 140/689] Remove unused current view related things (#7843) * Remove unused functions from `mapDispatchToProps` The actions import was also updated to import only the two actions used, rather than all actions. * Remove unused container component Well, technically it was the props injected by this container that were unused. The container served no purpose, so the component it surrounded is now used directly instead. * Remove both unused `getCurrentViewContext` selectors * Remove unused SHOW_CONFIG_PAGE action * Remove checks for `currentView` with name `config` Now that the SHOW_CONFIG_PAGE action has been removed, it's no longer possible for `currentView.name` to be set to that value. * Remove unused `wallet-view` container props * Delete unused SHOW_SEND_PAGE and SHOW_ADD_TOKEN_PAGE actions * Remove unused `account-menu.container` props * Remove unused SHOW_INFO_PAGE action * Remove unused SET_NEW_ACCOUNT_FORM action --- test/unit/actions/config_test.js | 7 --- test/unit/actions/view_info_test.js | 19 ------- test/unit/ui/app/reducers/app.spec.js | 53 ------------------- test/unit/ui/app/selectors.spec.js | 5 -- .../account-menu/account-menu.container.js | 12 ----- .../loading-network-screen.container.js | 3 +- .../account-details-modal.container.js | 11 ++-- .../app/wallet-view/wallet-view.container.js | 8 +-- ui/app/ducks/app/app.js | 50 ----------------- .../create-account.container.js | 20 ------- ui/app/pages/create-account/index.js | 2 +- ui/app/pages/routes/index.js | 5 +- ui/app/pages/send/send.selectors.js | 5 -- .../pages/send/tests/send-selectors.test.js | 10 ---- ui/app/selectors/selectors.js | 5 -- ui/app/store/actions.js | 39 -------------- 16 files changed, 8 insertions(+), 246 deletions(-) delete mode 100644 test/unit/actions/view_info_test.js delete mode 100644 ui/app/pages/create-account/create-account.container.js diff --git a/test/unit/actions/config_test.js b/test/unit/actions/config_test.js index 2f4ebe172..7418f0bd5 100644 --- a/test/unit/actions/config_test.js +++ b/test/unit/actions/config_test.js @@ -17,13 +17,6 @@ describe('config view actions', function () { } freeze(initialState) - describe('SHOW_CONFIG_PAGE', function () { - it('should set appState.currentView.name to config', function () { - const result = reducers(initialState, actions.showConfigPage()) - assert.equal(result.appState.currentView.name, 'config') - }) - }) - describe('SET_RPC_TARGET', function () { it('sets the state.metamask.rpcTarget property of the state to the action.value', function () { const action = { diff --git a/test/unit/actions/view_info_test.js b/test/unit/actions/view_info_test.js deleted file mode 100644 index 90f607552..000000000 --- a/test/unit/actions/view_info_test.js +++ /dev/null @@ -1,19 +0,0 @@ -import assert from 'assert' -import freeze from 'deep-freeze-strict' -import * as actions from '../../../ui/app/store/actions' -import reducers from '../../../ui/app/ducks' - -describe('SHOW_INFO_PAGE', function () { - it('sets the state.appState.currentView.name property to info', function () { - const initialState = { - appState: { - activeAddress: 'foo', - }, - } - freeze(initialState) - - const action = actions.showInfoPage() - const resultingState = reducers(initialState, action) - assert.equal(resultingState.appState.currentView.name, 'info') - }) -}) diff --git a/test/unit/ui/app/reducers/app.spec.js b/test/unit/ui/app/reducers/app.spec.js index 0ba3fa6e4..ce0eea32a 100644 --- a/test/unit/ui/app/reducers/app.spec.js +++ b/test/unit/ui/app/reducers/app.spec.js @@ -146,59 +146,6 @@ describe('App State', () => { assert.equal(state.currentView.name, 'restoreVault') }) - it('shows config page', () => { - const state = reduceApp(metamaskState, { - type: actions.SHOW_CONFIG_PAGE, - value: true, - }) - - assert.equal(state.currentView.name, 'config') - assert.equal(state.currentView.context, '0xAddress') - assert.equal(state.transForward, true) - }) - - it('shows add token page', () => { - const state = reduceApp(metamaskState, { - type: actions.SHOW_ADD_TOKEN_PAGE, - value: true, - }) - - assert.equal(state.currentView.name, 'add-token') - assert.equal(state.currentView.context, '0xAddress') - assert.equal(state.transForward, true) - }) - - it('sets new account form', () => { - const state = reduceApp(metamaskState, { - type: actions.SET_NEW_ACCOUNT_FORM, - formToSelect: 'context', - }) - - assert.equal(state.currentView.name, 'accountDetail') - assert.equal(state.currentView.context, 'context') - }) - - it('shows info page', () => { - const state = reduceApp(metamaskState, { - type: actions.SHOW_INFO_PAGE, - }) - - assert.equal(state.currentView.name, 'info') - assert.equal(state.currentView.context, '0xAddress') - assert.equal(state.transForward, true) - }) - - it('shows send page', () => { - const state = reduceApp(metamaskState, { - type: actions.SHOW_SEND_PAGE, - }) - - assert.equal(state.currentView.name, 'sendTransaction') - assert.equal(state.currentView.context, '0xAddress') - assert.equal(state.transForward, true) - assert.equal(state.warning, null) - }) - it('shows send token page', () => { const state = reduceApp(metamaskState, { type: actions.SHOW_SEND_TOKEN_PAGE, diff --git a/test/unit/ui/app/selectors.spec.js b/test/unit/ui/app/selectors.spec.js index 9a2722026..a8e1079d0 100644 --- a/test/unit/ui/app/selectors.spec.js +++ b/test/unit/ui/app/selectors.spec.js @@ -152,11 +152,6 @@ describe('Selectors', function () { assert(selectedTokenContract.abi) }) - it('#getCurrentViewContext', () => { - const currentViewContext = selectors.getCurrentViewContext(mockState) - assert.equal(currentViewContext, '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc') - }) - it('#getTotalUnapprovedCount', () => { const totalUnapprovedCount = selectors.getTotalUnapprovedCount(mockState) assert.equal(totalUnapprovedCount, 1) diff --git a/ui/app/components/app/account-menu/account-menu.container.js b/ui/app/components/app/account-menu/account-menu.container.js index 7182550a5..206afb176 100644 --- a/ui/app/components/app/account-menu/account-menu.container.js +++ b/ui/app/components/app/account-menu/account-menu.container.js @@ -7,8 +7,6 @@ import { hideSidebar, lockMetamask, hideWarning, - showConfigPage, - showInfoPage, showModal, } from '../../../store/actions' import { @@ -54,16 +52,6 @@ function mapDispatchToProps (dispatch) { dispatch(hideSidebar()) dispatch(toggleAccountMenu()) }, - showConfigPage: () => { - dispatch(showConfigPage()) - dispatch(hideSidebar()) - dispatch(toggleAccountMenu()) - }, - showInfoPage: () => { - dispatch(showInfoPage()) - dispatch(hideSidebar()) - dispatch(toggleAccountMenu()) - }, showRemoveAccountConfirmationModal: identity => { return dispatch(showModal({ name: 'CONFIRM_REMOVE_ACCOUNT', identity })) }, diff --git a/ui/app/components/app/loading-network-screen/loading-network-screen.container.js b/ui/app/components/app/loading-network-screen/loading-network-screen.container.js index 2ff819b2c..f33a12e56 100644 --- a/ui/app/components/app/loading-network-screen/loading-network-screen.container.js +++ b/ui/app/components/app/loading-network-screen/loading-network-screen.container.js @@ -6,7 +6,6 @@ import { getNetworkIdentifier } from '../../../selectors/selectors' const mapStateToProps = state => { const { loadingMessage, - currentView, } = state.appState const { provider, @@ -20,7 +19,7 @@ const mapStateToProps = state => { : [provider.type] return { - isLoadingNetwork: network === 'loading' && currentView.name !== 'config', + isLoadingNetwork: network === 'loading', loadingMessage, lastSelectedProvider, setProviderArgs, diff --git a/ui/app/components/app/modals/account-details-modal/account-details-modal.container.js b/ui/app/components/app/modals/account-details-modal/account-details-modal.container.js index b76c5d4a0..b4e9c282e 100644 --- a/ui/app/components/app/modals/account-details-modal/account-details-modal.container.js +++ b/ui/app/components/app/modals/account-details-modal/account-details-modal.container.js @@ -1,5 +1,5 @@ import { connect } from 'react-redux' -import * as actions from '../../../../store/actions' +import { showModal, setAccountLabel } from '../../../../store/actions' import { getSelectedIdentity, getRpcPrefsForCurrentProvider } from '../../../../selectors/selectors' import AccountDetailsModal from './account-details-modal.component' @@ -14,13 +14,8 @@ const mapStateToProps = (state) => { const mapDispatchToProps = (dispatch) => { return { - // Is this supposed to be used somewhere? - showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), - showExportPrivateKeyModal: () => { - dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' })) - }, - hideModal: () => dispatch(actions.hideModal()), - setAccountLabel: (address, label) => dispatch(actions.setAccountLabel(address, label)), + showExportPrivateKeyModal: () => dispatch(showModal({ name: 'EXPORT_PRIVATE_KEY' })), + setAccountLabel: (address, label) => dispatch(setAccountLabel(address, label)), } } diff --git a/ui/app/components/app/wallet-view/wallet-view.container.js b/ui/app/components/app/wallet-view/wallet-view.container.js index 29790f9a3..e9073e273 100644 --- a/ui/app/components/app/wallet-view/wallet-view.container.js +++ b/ui/app/components/app/wallet-view/wallet-view.container.js @@ -2,15 +2,13 @@ import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' import { compose } from 'recompose' import WalletView from './wallet-view.component' -import { showSendPage, hideSidebar, setSelectedToken, showAddTokenPage } from '../../../store/actions' -import { getMetaMaskAccounts, getSelectedAddress, getSelectedAccount } from '../../../selectors/selectors' +import { hideSidebar, setSelectedToken } from '../../../store/actions' +import { getSelectedAddress, getSelectedAccount } from '../../../selectors/selectors' function mapStateToProps (state) { return { - network: state.metamask.network, sidebarOpen: state.appState.sidebar.isOpen, identities: state.metamask.identities, - accounts: getMetaMaskAccounts(state), keyrings: state.metamask.keyrings, selectedAddress: getSelectedAddress(state), selectedAccount: getSelectedAccount(state), @@ -20,10 +18,8 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - showSendPage: () => dispatch(showSendPage()), hideSidebar: () => dispatch(hideSidebar()), unsetSelectedToken: () => dispatch(setSelectedToken()), - showAddTokenPage: () => dispatch(showAddTokenPage()), } } diff --git a/ui/app/ducks/app/app.js b/ui/app/ducks/app/app.js index c1bcc57ae..fb2e7ea1f 100644 --- a/ui/app/ducks/app/app.js +++ b/ui/app/ducks/app/app.js @@ -185,56 +185,6 @@ export default function reduceApp (state, action) { return newState - case actions.SHOW_CONFIG_PAGE: - return { - ...appState, - currentView: { - name: 'config', - context: appState.currentView.context, - }, - transForward: action.value, - } - - case actions.SHOW_ADD_TOKEN_PAGE: - return { - ...appState, - currentView: { - name: 'add-token', - context: appState.currentView.context, - }, - transForward: action.value, - } - - case actions.SET_NEW_ACCOUNT_FORM: - return { - ...appState, - currentView: { - name: appState.currentView.name, - context: action.formToSelect, - }, - } - - case actions.SHOW_INFO_PAGE: - return { - ...appState, - currentView: { - name: 'info', - context: appState.currentView.context, - }, - transForward: true, - } - - case actions.SHOW_SEND_PAGE: - return { - ...appState, - currentView: { - name: 'sendTransaction', - context: appState.currentView.context, - }, - transForward: true, - warning: null, - } - case actions.SHOW_SEND_TOKEN_PAGE: return { ...appState, diff --git a/ui/app/pages/create-account/create-account.container.js b/ui/app/pages/create-account/create-account.container.js deleted file mode 100644 index 0d6d79632..000000000 --- a/ui/app/pages/create-account/create-account.container.js +++ /dev/null @@ -1,20 +0,0 @@ -import { connect } from 'react-redux' -import * as actions from '../../store/actions' -import { getCurrentViewContext } from '../../selectors/selectors' -import CreateAccountPage from './create-account.component' - -const mapStateToProps = state => ({ - displayedForm: getCurrentViewContext(state), -}) - -const mapDispatchToProps = dispatch => ({ - displayForm: form => dispatch(actions.setNewAccountForm(form)), - showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), - showExportPrivateKeyModal: () => { - dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' })) - }, - hideModal: () => dispatch(actions.hideModal()), - setAccountLabel: (address, label) => dispatch(actions.setAccountLabel(address, label)), -}) - -export default connect(mapStateToProps, mapDispatchToProps)(CreateAccountPage) diff --git a/ui/app/pages/create-account/index.js b/ui/app/pages/create-account/index.js index 165c3b397..a736bfff7 100644 --- a/ui/app/pages/create-account/index.js +++ b/ui/app/pages/create-account/index.js @@ -1 +1 @@ -export { default } from './create-account.container' +export { default } from './create-account.component' diff --git a/ui/app/pages/routes/index.js b/ui/app/pages/routes/index.js index 8ccae97a3..8cb3bdbba 100644 --- a/ui/app/pages/routes/index.js +++ b/ui/app/pages/routes/index.js @@ -205,13 +205,12 @@ class Routes extends Component { network, provider, frequentRpcListDetail, - currentView, setMouseUserState, sidebar, submittedPendingTransactions, isMouseUser, } = this.props - const isLoadingNetwork = network === 'loading' && currentView.name !== 'config' + const isLoadingNetwork = network === 'loading' const loadMessage = loadingMessage || isLoadingNetwork ? this.getConnectingLabel(loadingMessage) : null log.debug('Main ui render function') @@ -366,7 +365,6 @@ Routes.propTypes = { provider: PropTypes.object, selectedAddress: PropTypes.string, frequentRpcListDetail: PropTypes.array, - currentView: PropTypes.object, sidebar: PropTypes.object, alertOpen: PropTypes.bool, hideSidebar: PropTypes.func, @@ -410,7 +408,6 @@ function mapStateToProps (state) { isLoading, loadingMessage, isUnlocked: state.metamask.isUnlocked, - currentView: state.appState.currentView, submittedPendingTransactions: submittedPendingTransactionsSelector(state), network: state.metamask.network, provider: state.metamask.provider, diff --git a/ui/app/pages/send/send.selectors.js b/ui/app/pages/send/send.selectors.js index be0a0bdac..99b941778 100644 --- a/ui/app/pages/send/send.selectors.js +++ b/ui/app/pages/send/send.selectors.js @@ -50,11 +50,6 @@ export function getCurrentNetwork (state) { return state.metamask.network } -export function getCurrentViewContext (state) { - const { currentView = {} } = state.appState - return currentView.context -} - export function getForceGasMin (state) { return state.metamask.send.forceGasMin } diff --git a/ui/app/pages/send/tests/send-selectors.test.js b/ui/app/pages/send/tests/send-selectors.test.js index 2e0b1a3d1..ca06f6524 100644 --- a/ui/app/pages/send/tests/send-selectors.test.js +++ b/ui/app/pages/send/tests/send-selectors.test.js @@ -9,7 +9,6 @@ import { getCurrentAccountWithSendEtherInfo, getCurrentCurrency, getCurrentNetwork, - getCurrentViewContext, getNativeCurrency, getForceGasMin, getGasLimit, @@ -180,15 +179,6 @@ describe('send selectors', () => { }) }) - describe('getCurrentViewContext()', () => { - it('should return the context of the current view', () => { - assert.equal( - getCurrentViewContext(mockState), - '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc' - ) - }) - }) - describe('getForceGasMin()', () => { it('should get the send.forceGasMin property', () => { assert.equal( diff --git a/ui/app/selectors/selectors.js b/ui/app/selectors/selectors.js index 4b79cdf79..410e09520 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/app/selectors/selectors.js @@ -302,11 +302,6 @@ export function getSelectedTokenContract (state) { : null } -export function getCurrentViewContext (state) { - const { currentView = {} } = state.appState - return currentView.context -} - export function getTotalUnapprovedCount ({ metamask }) { const { unapprovedTxs = {}, diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 6f1717afe..4ae342a95 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -36,8 +36,6 @@ export const actionConstants = { // remote state UPDATE_METAMASK_STATE: 'UPDATE_METAMASK_STATE', FORGOT_PASSWORD: 'FORGOT_PASSWORD', - SHOW_INFO_PAGE: 'SHOW_INFO_PAGE', - SET_NEW_ACCOUNT_FORM: 'SET_NEW_ACCOUNT_FORM', CLOSE_WELCOME_SCREEN: 'CLOSE_WELCOME_SCREEN', // unlock screen UNLOCK_IN_PROGRESS: 'UNLOCK_IN_PROGRESS', @@ -55,7 +53,6 @@ export const actionConstants = { SHOW_CONF_TX_PAGE: 'SHOW_CONF_TX_PAGE', SET_CURRENT_FIAT: 'SET_CURRENT_FIAT', // account detail screen - SHOW_SEND_PAGE: 'SHOW_SEND_PAGE', SHOW_SEND_TOKEN_PAGE: 'SHOW_SEND_TOKEN_PAGE', SHOW_PRIVATE_KEY: 'SHOW_PRIVATE_KEY', SET_ACCOUNT_LABEL: 'SET_ACCOUNT_LABEL', @@ -82,11 +79,9 @@ export const actionConstants = { UPDATE_SEND_ENS_RESOLUTION: 'UPDATE_SEND_ENS_RESOLUTION', UPDATE_SEND_ENS_RESOLUTION_ERROR: 'UPDATE_SEND_ENS_RESOLUTION_ERROR', // config screen - SHOW_CONFIG_PAGE: 'SHOW_CONFIG_PAGE', SET_RPC_TARGET: 'SET_RPC_TARGET', SET_PROVIDER_TYPE: 'SET_PROVIDER_TYPE', SET_PREVIOUS_PROVIDER: 'SET_PREVIOUS_PROVIDER', - SHOW_ADD_TOKEN_PAGE: 'SHOW_ADD_TOKEN_PAGE', UPDATE_TOKENS: 'UPDATE_TOKENS', SET_HARDWARE_WALLET_DEFAULT_HD_PATH: 'SET_HARDWARE_WALLET_DEFAULT_HD_PATH', // loading overlay @@ -548,12 +543,6 @@ export function unlockHardwareWalletAccount (index, deviceName, hdPath) { } } -export function showInfoPage () { - return { - type: actionConstants.SHOW_INFO_PAGE, - } -} - export function showQrScanner (ROUTE) { return (dispatch) => { return WebcamUtils.checkStatus() @@ -1127,14 +1116,6 @@ export function forgotPassword (forgotPasswordState = true) { } } - -export function setNewAccountForm (formToSelect) { - return { - type: actionConstants.SET_NEW_ACCOUNT_FORM, - formToSelect, - } -} - export function closeWelcomeScreen () { return { type: actionConstants.CLOSE_WELCOME_SCREEN, @@ -1272,20 +1253,6 @@ export function showConfTxPage ({ transForward = true, id }) { } } -export function showConfigPage (transitionForward = true) { - return { - type: actionConstants.SHOW_CONFIG_PAGE, - value: transitionForward, - } -} - -export function showAddTokenPage (transitionForward = true) { - return { - type: actionConstants.SHOW_ADD_TOKEN_PAGE, - value: transitionForward, - } -} - export function addToken (address, symbol, decimals, image) { return (dispatch) => { dispatch(showLoadingIndication()) @@ -1809,12 +1776,6 @@ export function setAccountLabel (account, label) { } } -export function showSendPage () { - return { - type: actionConstants.SHOW_SEND_PAGE, - } -} - export function showSendTokenPage () { return { type: actionConstants.SHOW_SEND_TOKEN_PAGE, From 20a7b8fa36a68a96f8fd9a800059abc7ce6d9204 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 16 Jan 2020 13:43:40 -0400 Subject: [PATCH 141/689] Force background state update after removing an account (#7840) The e2e tests were failing intermittently after removing an account because the account was shown as not deleted after the removal. I suspect this was because the account _had_ been removed, but that change to the background state hadn't yet propagated to the UI. The background state is now synced before the loading overlay for removing the account is removed, ensuring that the removed account cannot be seen in the UI after removal. --- test/unit/ui/app/actions.spec.js | 23 +++++++++++++++-------- ui/app/store/actions.js | 32 +++++++++++++++++++------------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js index f2e676ab5..349368701 100644 --- a/test/unit/ui/app/actions.spec.js +++ b/test/unit/ui/app/actions.spec.js @@ -239,25 +239,29 @@ describe('Actions', () => { const store = mockStore(devState) const expectedActions = [ - { type: 'SHOW_LOADING_INDICATION', value: undefined }, - { type: 'HIDE_LOADING_INDICATION' }, - { type: 'SHOW_ACCOUNTS_PAGE' }, + 'SHOW_LOADING_INDICATION', + 'UPDATE_METAMASK_STATE', + 'HIDE_LOADING_INDICATION', + 'SHOW_ACCOUNTS_PAGE', ] removeAccountSpy = sinon.spy(background, 'removeAccount') await store.dispatch(actions.removeAccount('0xe18035bf8712672935fdb4e5e431b1a0183d2dfc')) assert(removeAccountSpy.calledOnce) - assert.deepEqual(store.getActions(), expectedActions) + const actionTypes = store + .getActions() + .map(action => action.type) + assert.deepEqual(actionTypes, expectedActions) }) it('displays warning error message when removeAccount callback errors', async () => { const store = mockStore() const expectedActions = [ - { type: 'SHOW_LOADING_INDICATION', value: undefined }, - { type: 'HIDE_LOADING_INDICATION' }, - { type: 'DISPLAY_WARNING', value: 'error' }, + 'SHOW_LOADING_INDICATION', + 'DISPLAY_WARNING', + 'HIDE_LOADING_INDICATION', ] removeAccountSpy = sinon.stub(background, 'removeAccount') @@ -269,7 +273,10 @@ describe('Actions', () => { await store.dispatch(actions.removeAccount('0xe18035bf8712672935fdb4e5e431b1a0183d2dfc')) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + const actionTypes = store + .getActions() + .map(action => action.type) + assert.deepEqual(actionTypes, expectedActions) } }) diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 4ae342a95..7b1f78b29 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -380,22 +380,28 @@ export function resetAccount () { } export function removeAccount (address) { - return dispatch => { + return async dispatch => { dispatch(showLoadingIndication()) - return new Promise((resolve, reject) => { - background.removeAccount(address, (err, account) => { - dispatch(hideLoadingIndication()) - if (err) { - dispatch(displayWarning(err.message)) - return reject(err) - } - - log.info('Account removed: ' + account) - dispatch(showAccountsPage()) - resolve() + try { + await new Promise((resolve, reject) => { + background.removeAccount(address, (error, account) => { + if (error) { + return reject(error) + } + return resolve(account) + }) }) - }) + await forceUpdateMetamaskState(dispatch) + } catch (error) { + dispatch(displayWarning(error.message)) + throw error + } finally { + dispatch(hideLoadingIndication()) + } + + log.info('Account removed: ' + address) + dispatch(showAccountsPage()) } } From 70e083820bdd7a025d4e00ca92611b0d81cb395a Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 16 Jan 2020 15:02:03 -0330 Subject: [PATCH 142/689] Refactor Network dropdown component (#7817) --- ui/app/components/app/network.js | 290 +++++++++++++++---------------- 1 file changed, 138 insertions(+), 152 deletions(-) diff --git a/ui/app/components/app/network.js b/ui/app/components/app/network.js index 51543c3a2..a156f676d 100644 --- a/ui/app/components/app/network.js +++ b/ui/app/components/app/network.js @@ -1,9 +1,42 @@ import PropTypes from 'prop-types' import React, { Component } from 'react' - import classnames from 'classnames' import NetworkDropdownIcon from './dropdowns/components/network-dropdown-icon' +function NetworkIndicator ({ disabled, children, hoverText, onClick, providerName }) { + return ( +
{ + if (!disabled) { + onClick(event) + } + }} + > +
+ {children} +
+
+
+ ) +} + +NetworkIndicator.propTypes = { + children: PropTypes.node.isRequired, + disabled: PropTypes.bool, + hoverText: PropTypes.string, + onClick: PropTypes.func, + providerName: PropTypes.string, +} + export default class Network extends Component { static contextTypes = { t: PropTypes.func, @@ -21,160 +54,113 @@ export default class Network extends Component { } render () { - const context = this.context - const networkNumber = this.props.network + const { + t, + } = this.context + + const { + disabled, + network: networkNumber, + onClick, + provider, + } = this.props + let providerName, providerNick, providerUrl - try { - providerName = this.props.provider.type - providerNick = this.props.provider.nickname || '' - providerUrl = this.props.provider.rpcTarget - } catch (e) { - providerName = null + if (provider) { + providerName = provider.type + providerNick = provider.nickname || '' + providerUrl = provider.rpcTarget } - const providerId = providerNick || providerName || providerUrl || null - let iconName - let hoverText - if (providerName === 'mainnet') { - hoverText = context.t('mainnet') - iconName = 'ethereum-network' - } else if (providerName === 'ropsten') { - hoverText = context.t('ropsten') - iconName = 'ropsten-test-network' - } else if (providerName === 'kovan') { - hoverText = context.t('kovan') - iconName = 'kovan-test-network' - } else if (providerName === 'rinkeby') { - hoverText = context.t('rinkeby') - iconName = 'rinkeby-test-network' - } else if (providerName === 'goerli') { - hoverText = context.t('goerli') - iconName = 'goerli-test-network' - } else { - hoverText = providerId - iconName = 'private-network' - } + switch (providerName) { + case 'mainnet': + return ( + + +
{t('mainnet')}
+
+ ) - return ( -
{ - if (!this.props.disabled) { - this.props.onClick(event) - } - }} - > - {(function () { - switch (iconName) { - case 'ethereum-network': - return ( -
- -
- {context.t('mainnet')} -
-
-
- ) - case 'ropsten-test-network': - return ( -
- -
- {context.t('ropsten')} -
-
-
- ) - case 'kovan-test-network': - return ( -
- -
- {context.t('kovan')} -
-
-
- ) - case 'rinkeby-test-network': - return ( -
- -
- {context.t('rinkeby')} -
-
-
- ) - case 'goerli-test-network': - return ( -
- -
{context.t('goerli')}
-
-
- ) - default: - return ( -
- {networkNumber === 'loading' - ? ( - this.props.onClick(event)} - > - - - ) - : ( - - )} -
- { - providerName === 'localhost' - ? context.t('localhost') - : providerNick || context.t('privateNetwork') - } -
-
-
- ) - } - })()} -
- ) + case 'ropsten': + return ( + + +
{t('ropsten')}
+
+ ) + + case 'kovan': + return ( + + +
{t('kovan')}
+
+ ) + + case 'rinkeby': + return ( + + +
{t('rinkeby')}
+
+ ) + + case 'goerli': + return ( + + +
{t('goerli')}
+
+ ) + + default: + return ( + + { + networkNumber === 'loading' + ? ( + onClick(event)}> + + + ) + : ( + + ) + } +
+ { + providerName === 'localhost' + ? t('localhost') + : providerNick || t('privateNetwork') + } +
+
+ ) + } } } From 08dcd87d58ce69797ae1a5cba4ff1f0dbe51215e Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 16 Jan 2020 14:35:50 -0400 Subject: [PATCH 143/689] Refactor building of e2e web driver (#7841) The switch case has been moved to a separate function so that the initialization steps following the web driver instantiation could more easily be deduplicated. --- test/e2e/webdriver/index.js | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/test/e2e/webdriver/index.js b/test/e2e/webdriver/index.js index 17c3b2744..c92e74394 100644 --- a/test/e2e/webdriver/index.js +++ b/test/e2e/webdriver/index.js @@ -8,28 +8,26 @@ async function buildWebDriver ({ responsive, port } = {}) { const browser = process.env.SELENIUM_BROWSER const extensionPath = `dist/${browser}` + const { driver: seleniumDriver, extensionId, extensionUrl } = await buildBrowserWebDriver(browser, { extensionPath, responsive, port }) + setupFetchMocking(seleniumDriver) + await seleniumDriver.get(extensionUrl) + + const driver = new Driver(seleniumDriver, browser) + + return { + driver, + extensionId, + extensionUrl, + } +} + +async function buildBrowserWebDriver (browser, webDriverOptions) { switch (browser) { case Browser.CHROME: { - const { driver, extensionId, extensionUrl } = await ChromeDriver.build({ extensionPath, responsive, port }) - setupFetchMocking(driver) - await driver.get(extensionUrl) - - return { - driver: new Driver(driver, browser), - extensionId, - extensionUrl, - } + return await ChromeDriver.build(webDriverOptions) } case Browser.FIREFOX: { - const { driver, extensionId, extensionUrl } = await FirefoxDriver.build({ extensionPath, responsive, port }) - setupFetchMocking(driver) - await driver.get(extensionUrl) - - return { - driver: new Driver(driver, browser), - extensionId, - extensionUrl, - } + return await FirefoxDriver.build(webDriverOptions) } default: { throw new Error(`Unrecognized browser: ${browser}`) From 78044a5cdcda0370195421baac702e22e54cfa04 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 16 Jan 2020 15:53:14 -0330 Subject: [PATCH 144/689] Fix propTypes and test props for SignatureRequest component (#7849) --- .../signature-request-header.component.js | 2 +- .../app/signature-request/signature-request.component.js | 2 +- .../app/signature-request/tests/signature-request.test.js | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js b/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js index 661a933a0..40e1315cc 100644 --- a/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js +++ b/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js @@ -5,7 +5,7 @@ import NetworkDisplay from '../../network-display' export default class SignatureRequestHeader extends PureComponent { static propTypes = { - selectedAccount: PropTypes.object.isRequired, + selectedAccount: PropTypes.object, } render () { diff --git a/ui/app/components/app/signature-request/signature-request.component.js b/ui/app/components/app/signature-request/signature-request.component.js index 3abfbd770..645b1b2ed 100644 --- a/ui/app/components/app/signature-request/signature-request.component.js +++ b/ui/app/components/app/signature-request/signature-request.component.js @@ -14,7 +14,7 @@ export default class SignatureRequest extends PureComponent { address: PropTypes.string, balance: PropTypes.string, name: PropTypes.string, - }).isRequired, + }), clearConfirmTransaction: PropTypes.func.isRequired, cancel: PropTypes.func.isRequired, diff --git a/ui/app/components/app/signature-request/tests/signature-request.test.js b/ui/app/components/app/signature-request/tests/signature-request.test.js index 6ff07effc..acc2ac904 100644 --- a/ui/app/components/app/signature-request/tests/signature-request.test.js +++ b/ui/app/components/app/signature-request/tests/signature-request.test.js @@ -10,6 +10,9 @@ describe('Signature Request Component', function () { beforeEach(() => { wrapper = shallow(( {}} + cancel={() => {}} + sign={() => {}} txData={{ msgParams: { data: '{"message": {"from": {"name": "hello"}}}', From b4ca671b6b150c36330f042fd5d2eb56a1131b13 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 16 Jan 2020 18:18:09 -0330 Subject: [PATCH 145/689] Fix propTypes and test props for Dropdown components (#7851) --- test/unit/responsive/components/dropdown-test.js | 15 +++------------ ui/app/components/app/menu-droppo.js | 2 +- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/test/unit/responsive/components/dropdown-test.js b/test/unit/responsive/components/dropdown-test.js index 8b39a1481..3d0da520f 100644 --- a/test/unit/responsive/components/dropdown-test.js +++ b/test/unit/responsive/components/dropdown-test.js @@ -12,7 +12,6 @@ const mockState = { describe('Dropdown components', function () { let onClickOutside - let closeMenu let onClick const dropdownComponentProps = { @@ -32,7 +31,6 @@ describe('Dropdown components', function () { let component beforeEach(function () { onClickOutside = sinon.spy() - closeMenu = sinon.spy() onClick = sinon.spy() store = createMockStore(mockState) @@ -46,8 +44,8 @@ describe('Dropdown components', function () { ` } -
  • Item 1
  • -
  • Item 2
  • +
  • Item 1
  • +
  • Item 2
  • ), store) dropdownComponent = component @@ -58,17 +56,10 @@ describe('Dropdown components', function () { assert.equal(items.length, 2) }) - it('closes when item clicked', function () { - const items = dropdownComponent.find('li') - const node = items.at(0) - node.simulate('click') - assert.equal(node.props().closeMenu, closeMenu) - }) - it('invokes click handler when item clicked', function () { const items = dropdownComponent.find('li') const node = items.at(0) node.simulate('click') - assert.equal(onClick.calledOnce, true) + assert.ok(onClick.calledOnce) }) }) diff --git a/ui/app/components/app/menu-droppo.js b/ui/app/components/app/menu-droppo.js index ab149d48c..1a5d7138c 100644 --- a/ui/app/components/app/menu-droppo.js +++ b/ui/app/components/app/menu-droppo.js @@ -8,7 +8,7 @@ export default class MenuDroppoComponent extends Component { isOpen: PropTypes.bool.isRequired, innerStyle: PropTypes.object, children: PropTypes.node.isRequired, - onClickOutside: PropTypes.func.isRequired, + onClickOutside: PropTypes.func, containerClassName: PropTypes.string, zIndex: PropTypes.number, style: PropTypes.object.isRequired, From 7c7f121fe30894f05cd42168882f0339c1c1a172 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 16 Jan 2020 18:19:01 -0330 Subject: [PATCH 146/689] Fix props for BasicTabContent component tests (#7850) --- .../tests/basic-tab-content-component.test.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js index 80fbffe05..790807450 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js @@ -5,6 +5,7 @@ import BasicTabContent from '../basic-tab-content.component' import GasPriceButtonGroup from '../../../gas-price-button-group' import Loading from '../../../../../ui/loading-screen' +import { GAS_ESTIMATE_TYPES } from '../../../../../../helpers/constants/common' const mockGasPriceButtonGroupProps = { buttonDataLoading: false, @@ -15,18 +16,21 @@ const mockGasPriceButtonGroupProps = { feeInSecondaryCurrency: '0.0048 ETH', timeEstimate: '~ 1 min 0 sec', priceInHexWei: '0xa1b2c3f', + gasEstimateType: GAS_ESTIMATE_TYPES.AVERAGE, }, { feeInPrimaryCurrency: '$0.39', feeInSecondaryCurrency: '0.004 ETH', timeEstimate: '~ 1 min 30 sec', priceInHexWei: '0xa1b2c39', + gasEstimateType: GAS_ESTIMATE_TYPES.AVERAGE, }, { feeInPrimaryCurrency: '$0.30', feeInSecondaryCurrency: '0.00354 ETH', timeEstimate: '~ 2 min 1 sec', priceInHexWei: '0xa1b2c30', + gasEstimateType: GAS_ESTIMATE_TYPES.AVERAGE, }, ], handleGasPriceSelection: newPrice => console.log('NewPrice: ', newPrice), From 000fcfdfccef59e4d1492661514ca37e749d3db6 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 16 Jan 2020 18:19:38 -0330 Subject: [PATCH 147/689] Fix propTypes for TransactionBreakdown component (#7848) --- .../transaction-breakdown/transaction-breakdown.component.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js index 02cff8a59..6e610a833 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js @@ -14,7 +14,7 @@ export default class TransactionBreakdown extends PureComponent { static propTypes = { className: PropTypes.string, - nativeCurrency: PropTypes.string.isRequired, + nativeCurrency: PropTypes.string, showFiat: PropTypes.bool, gas: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), gasPrice: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), From 2bd6ba4d3523477dacad3842d688ac3dd46f8e3f Mon Sep 17 00:00:00 2001 From: Frankie Date: Fri, 17 Jan 2020 08:02:06 -0800 Subject: [PATCH 148/689] deps - update nonce-tracker (#7856) --- yarn.lock | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index fa2607a44..0ec33b66f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7584,7 +7584,12 @@ core-js@^2.2.0, core-js@^2.5.0, core-js@^2.5.3: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" integrity sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4= -core-js@^2.4.0, core-js@^2.5.7: +core-js@^2.4.0: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== + +core-js@^2.5.7: version "2.6.9" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== @@ -19694,9 +19699,9 @@ nomnom@~1.6.2: underscore "~1.4.4" nonce-tracker@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/nonce-tracker/-/nonce-tracker-1.0.0.tgz#8a23e696320a439c550f3a6d9a98340370b7e467" - integrity sha512-hxKokxgLvOZx9A5qPQKwL34G1/YwMC5xJWZHFUKfvwxypkn2nP0KVJjbcoXwY6pXsRRa11KdFEPW61N4YCGnWQ== + version "1.0.1" + resolved "https://registry.yarnpkg.com/nonce-tracker/-/nonce-tracker-1.0.1.tgz#4be90cdd9339009730c2133e86b66dbceb624ff1" + integrity sha512-pmx0gvfipbsvMh0XWOyisxq3+POTDhaXBh+7RHxfjzcBLV7c/eEfieNC1HPmMMtvvznCo0j6aqvshTg05oxfjg== dependencies: assert "^1.4.1" await-semaphore "^0.1.3" From 1728d9a5aa263ecbe48c196688345fff2f803cbd Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 17 Jan 2020 18:28:27 -0330 Subject: [PATCH 149/689] Inline networkStore to avoid having too many event listeners (#7854) --- test/unit/app/controllers/transactions/tx-controller-test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/unit/app/controllers/transactions/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js index 950e53e9c..8aab61122 100644 --- a/test/unit/app/controllers/transactions/tx-controller-test.js +++ b/test/unit/app/controllers/transactions/tx-controller-test.js @@ -19,7 +19,6 @@ import { createTestProviderTools, getTestAccounts } from '../../../../stub/provi const noop = () => true const currentNetworkId = 42 -const netStore = new ObservableStore(currentNetworkId) describe('Transaction Controller', function () { let txController, provider, providerResultStub, fromAccount @@ -41,7 +40,7 @@ describe('Transaction Controller', function () { getGasPrice: function () { return '0xee6b2800' }, - networkStore: netStore, + networkStore: new ObservableStore(currentNetworkId), txHistoryLimit: 10, blockTracker: blockTrackerStub, signTransaction: (ethTx) => new Promise((resolve) => { From 3a2c81d8bca7fdcddbc2fb6b50e3fc51e7156f31 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 17 Jan 2020 18:16:21 -0400 Subject: [PATCH 150/689] Switch signature-request e2e tests to using ganache (#7859) The signature request e2e tests were previously using ropsten. This expectation was even hard-coded into the test contract dapp. Instead the contract-dapp has been updated to use the current `chainId` when calling `signTypedData` (falling back to the `networkId` if `chainId` is not set). The fixture used by `signature-request` has been updated to use ganache. --- test/e2e/contract-test/contract.js | 5 ++++- test/e2e/fixtures/imported-account/state.json | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/e2e/contract-test/contract.js b/test/e2e/contract-test/contract.js index bd07e9dd1..4611095f3 100644 --- a/test/e2e/contract-test/contract.js +++ b/test/e2e/contract-test/contract.js @@ -269,6 +269,9 @@ const initialize = () => { } signTypedData.addEventListener('click', () => { + const networkId = parseInt(networkDiv.innerHTML) + const chainId = parseInt(chainIdDiv.innerHTML) || networkId + const typedData = { types: { EIP712Domain: [ @@ -291,7 +294,7 @@ const initialize = () => { domain: { name: 'Ether Mail', version: '1', - chainId: 3, + chainId, verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC', }, message: { diff --git a/test/e2e/fixtures/imported-account/state.json b/test/e2e/fixtures/imported-account/state.json index 97a2eddbb..4bf97d646 100644 --- a/test/e2e/fixtures/imported-account/state.json +++ b/test/e2e/fixtures/imported-account/state.json @@ -27,12 +27,12 @@ "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" }, "NetworkController": { - "network": "3", + "network": "5777", "provider": { "nickname": "", "rpcTarget": "", "ticker": "ETH", - "type": "ropsten" + "type": "localhost" }, "settings": { "ticker": "ETH" From 7b35ea640047109c4ae36d5ecef5e7dac3ad338b Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 17 Jan 2020 18:59:25 -0400 Subject: [PATCH 151/689] Allow exporting state during e2e tests (#7860) As of #7663, an in-memory store was used in place of local storage during e2e tests, to facilitate the use of state fixtures. However, this made it difficult to export state during a test run. The instructions for exporting state to create fixtures assumed that local storage was being used. A new global function has been added to the background context to allow exporting state. This method is available during testing and development, and it works with either local storage or the in-memory store. The fixture instructions have been updated to reference this new function. --- app/scripts/background.js | 4 ++++ test/e2e/fixtures/README.md | 27 +++++++-------------------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/app/scripts/background.js b/app/scripts/background.js index 7f1c13686..bee63e711 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -66,6 +66,10 @@ const localStore = inTest : new LocalStore() let versionedData +if (inTest || process.env.METAMASK_DEBUG) { + global.metamaskGetState = localStore.get.bind(localStore) +} + // initialization flow initialize().catch(log.error) diff --git a/test/e2e/fixtures/README.md b/test/e2e/fixtures/README.md index 41c04177f..e8bbe39ac 100644 --- a/test/e2e/fixtures/README.md +++ b/test/e2e/fixtures/README.md @@ -7,30 +7,17 @@ one thing: ## Generating fixture data -Fixture data can be generated by loading the unpacked extension, inspecting the background context, -dumping `chrome.storage.local`, and using [`copy`][1] to copy it to the clipboard, and manually pasting the contents into -a file on disk. +Fixture data can be generated by following these steps: -```js -// Step 1: -chrome.storage.local.get(null, (x) => console.log(x)) -// Should print something like: -// > temp1 -// > {data: {…}, meta: {…}} +1. Load the unpacked extension in development or test mode +2. Inspecting the background context of the extension +3. Call `metamaskGetState`, then call [`copy`][1] on the results -// Step 2: -// Store the value as a global via the 'Store as global variable' option in context menu (shown below) +You can then paste the contents directly in your fixture file. -// Step 3: -copy(temp1) +```js +copy(await metamaskGetState()) ``` -Store the value as a global variable: - -Store as global variable [1]:https://developers.google.com/web/tools/chrome-devtools/console/utilities From 3448f3490588c1a7c7413cdd39d86a0b53d228bf Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 17 Jan 2020 19:59:47 -0330 Subject: [PATCH 152/689] Clean up "JSON File" import strategy test output (#7855) --- app/scripts/account-import-strategies/index.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/scripts/account-import-strategies/index.js b/app/scripts/account-import-strategies/index.js index 18e564dda..7ff8c262f 100644 --- a/app/scripts/account-import-strategies/index.js +++ b/app/scripts/account-import-strategies/index.js @@ -1,3 +1,4 @@ +import log from 'loglevel' import Wallet from 'ethereumjs-wallet' import importers from 'ethereumjs-wallet/thirdparty' import ethUtil from 'ethereumjs-util' @@ -35,10 +36,7 @@ const accountImporter = { try { wallet = importers.fromEtherWallet(input, password) } catch (e) { - console.log('Attempt to import as EtherWallet format failed, trying V3...') - } - - if (!wallet) { + log.debug('Attempt to import as EtherWallet format failed, trying V3') wallet = Wallet.fromV3(input, password, true) } From 22d66b3b2df77370f96c8fd7e078b638e2283fe1 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Sun, 19 Jan 2020 21:45:49 -0330 Subject: [PATCH 153/689] Add mobile hiring note to README (#7865) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index c1db416e3..662e31438 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ # MetaMask Browser Extension + +Hey! We are hiring a Senior Mobile Engineer! Apply here: https://boards.greenhouse.io/consensys/jobs/1990589 +--- + [![Build Status](https://circleci.com/gh/MetaMask/metamask-extension.svg?style=shield&circle-token=a1ddcf3cd38e29267f254c9c59d556d513e3a1fd)](https://circleci.com/gh/MetaMask/metamask-extension) [![Coverage Status](https://coveralls.io/repos/github/MetaMask/metamask-extension/badge.svg?branch=master)](https://coveralls.io/github/MetaMask/metamask-extension?branch=master) You can find the latest version of MetaMask on [our official website](https://metamask.io/). For help using MetaMask, visit our [User Support Site](https://metamask.zendesk.com/hc/en-us). From ca38635d225244af84f4ece32e54a5458825fab1 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 20 Jan 2020 13:03:07 -0400 Subject: [PATCH 154/689] Add page navigation to e2e web driver (#7867) The driver now has a page navigation function that can navigate to any of the three primary pages used in the extension. Additional pages and support of paths can be added later as needed. --- test/e2e/webdriver/chrome.js | 2 +- test/e2e/webdriver/driver.js | 15 ++++++++++++++- test/e2e/webdriver/firefox.js | 2 +- test/e2e/webdriver/index.js | 6 ++---- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/test/e2e/webdriver/chrome.js b/test/e2e/webdriver/chrome.js index 710f2ed20..556073056 100644 --- a/test/e2e/webdriver/chrome.js +++ b/test/e2e/webdriver/chrome.js @@ -28,7 +28,7 @@ class ChromeDriver { return { driver, - extensionUrl: `chrome-extension://${extensionId}/home.html`, + extensionUrl: `chrome-extension://${extensionId}`, } } diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index 3774189bf..90a4e32a9 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -8,9 +8,10 @@ class Driver { * @param {string} browser - The type of browser this driver is controlling * @param {number} timeout */ - constructor (driver, browser, timeout = 10000) { + constructor (driver, browser, extensionUrl, timeout = 10000) { this.driver = driver this.browser = browser + this.extensionUrl = extensionUrl this.timeout = timeout } @@ -84,6 +85,12 @@ class Driver { assert.ok(!dataTab, 'Found element that should not be present') } + // Navigation + + async navigate (page = Driver.PAGES.HOME) { + return await this.driver.get(`${this.extensionUrl}/${page}.html`) + } + // Window management async openNewPage (url) { @@ -173,4 +180,10 @@ class Driver { } } +Driver.PAGES = { + HOME: 'home', + NOTIFICATION: 'notification', + POPUP: 'popup', +} + module.exports = Driver diff --git a/test/e2e/webdriver/firefox.js b/test/e2e/webdriver/firefox.js index b3ee1323b..aff7227a4 100644 --- a/test/e2e/webdriver/firefox.js +++ b/test/e2e/webdriver/firefox.js @@ -52,7 +52,7 @@ class FirefoxDriver { return { driver, extensionId, - extensionUrl: `moz-extension://${internalExtensionId}/home.html`, + extensionUrl: `moz-extension://${internalExtensionId}`, } } diff --git a/test/e2e/webdriver/index.js b/test/e2e/webdriver/index.js index c92e74394..4c172d340 100644 --- a/test/e2e/webdriver/index.js +++ b/test/e2e/webdriver/index.js @@ -10,14 +10,12 @@ async function buildWebDriver ({ responsive, port } = {}) { const { driver: seleniumDriver, extensionId, extensionUrl } = await buildBrowserWebDriver(browser, { extensionPath, responsive, port }) setupFetchMocking(seleniumDriver) - await seleniumDriver.get(extensionUrl) - - const driver = new Driver(seleniumDriver, browser) + const driver = new Driver(seleniumDriver, browser, extensionUrl) + await driver.navigate() return { driver, extensionId, - extensionUrl, } } From 523121209f629e06c88785cb3962af6c61541cf0 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 20 Jan 2020 13:03:21 -0400 Subject: [PATCH 155/689] Revert the revert of "Use common test build during CI (#7196)" (#7404) (#7870) This reverts commit 4b4c00e94fbb2f38746521864a568aab1400aac4. The original change was a possible optimization of CI, though it ended up not having a huge impact. It was thought that it may have broken source maps, because the test build overwrote the `dist` directory that the source maps were written to. However this turned out not to be the case, as the changes to `dist` are never persisted to the workspace. This is being re-introduced because the test build is needed for an additional job (the page load benchmark), and sharing the same build for all three jobs would surely be faster than building it separately three times. --- .circleci/config.yml | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ba6e90290..02441c443 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,6 +13,9 @@ workflows: - prep-build: requires: - prep-deps + - prep-build-test: + requires: + - prep-deps # - prep-docs: # requires: # - prep-deps @@ -28,10 +31,10 @@ workflows: - prep-deps - test-e2e-chrome: requires: - - prep-deps + - prep-build-test - test-e2e-firefox: requires: - - prep-deps + - prep-build-test - test-unit: requires: - prep-deps @@ -131,6 +134,24 @@ jobs: - dist - builds + prep-build-test: + docker: + - image: circleci/node:10.16-browsers + steps: + - checkout + - attach_workspace: + at: . + - run: + name: Build extension for testing + command: yarn build:test + - run: + name: Move test build to 'dist-test' to avoid conflict with production build + command: mv ./dist ./dist-test + - persist_to_workspace: + root: . + paths: + - dist-test + prep-docs: docker: - image: circleci/node:10.17-browsers @@ -218,9 +239,12 @@ jobs: - checkout - attach_workspace: at: . + - run: + name: Move test build to dist + command: mv ./dist-test ./dist - run: name: test:e2e:chrome - command: yarn build:test && yarn test:e2e:chrome + command: yarn test:e2e:chrome no_output_timeout: 20m - store_artifacts: path: test-artifacts @@ -236,9 +260,12 @@ jobs: command: ./.circleci/scripts/firefox-install - attach_workspace: at: . + - run: + name: Move test build to dist + command: mv ./dist-test ./dist - run: name: test:e2e:firefox - command: yarn build:test && yarn test:e2e:firefox + command: yarn test:e2e:firefox no_output_timeout: 20m - store_artifacts: path: test-artifacts From cc928aaed986cfbfd2212ba5f18cf7f7788b7bf7 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 20 Jan 2020 14:50:25 -0400 Subject: [PATCH 156/689] Add `withFixtures` helper and simple-send test (#7862) The `withFixtures` helper will instantiate ganache, a web driver, and a fixture server initialized with the given set of fixtures. It is meant to facilitating writing small, isolated e2e tests. The first example test has been added: simple-send. It ensures that the user can send 1 ETH to another account. These new e2e tests will run during the normal e2e test run. Closes #6548 --- test/e2e/helpers.js | 31 +++++++++++++++++++ test/e2e/run-all.sh | 2 ++ test/e2e/tests/simple-send.spec.js | 28 +++++++++++++++++ .../transaction-view-balance.component.js | 1 + .../page-container-footer.component.js | 2 ++ .../add-recipient/ens-input.component.js | 1 + 6 files changed, 65 insertions(+) create mode 100644 test/e2e/tests/simple-send.spec.js diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 08dc1c97b..2d4e030ca 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -1,9 +1,40 @@ +const path = require('path') +const Ganache = require('./ganache') +const FixtureServer = require('./fixture-server') +const { buildWebDriver } = require('./webdriver') + const tinyDelayMs = 200 const regularDelayMs = tinyDelayMs * 2 const largeDelayMs = regularDelayMs * 2 +async function withFixtures (options, callback) { + const { fixtures, ganacheOptions, driverOptions } = options + const fixtureServer = new FixtureServer() + const ganacheServer = new Ganache() + + let webDriver + try { + await ganacheServer.start(ganacheOptions) + await fixtureServer.start() + await fixtureServer.loadState(path.join(__dirname, 'fixtures', fixtures)) + const { driver } = await buildWebDriver(driverOptions) + webDriver = driver + + await callback({ + driver, + }) + } finally { + await fixtureServer.stop() + await ganacheServer.quit() + if (webDriver) { + await webDriver.quit() + } + } +} + module.exports = { tinyDelayMs, regularDelayMs, largeDelayMs, + withFixtures, } diff --git a/test/e2e/run-all.sh b/test/e2e/run-all.sh index f5ed527e2..c89f3f232 100755 --- a/test/e2e/run-all.sh +++ b/test/e2e/run-all.sh @@ -7,6 +7,8 @@ set -o pipefail export PATH="$PATH:./node_modules/.bin" +mocha --no-timeouts test/e2e/tests/*.spec.js + concurrently --kill-others \ --names 'dapp,e2e' \ --prefix '[{time}][{name}]' \ diff --git a/test/e2e/tests/simple-send.spec.js b/test/e2e/tests/simple-send.spec.js new file mode 100644 index 000000000..bf4eed442 --- /dev/null +++ b/test/e2e/tests/simple-send.spec.js @@ -0,0 +1,28 @@ +const { By, Key } = require('selenium-webdriver') +const { withFixtures } = require('../helpers') + +describe('MetaMask Browser Extension', function () { + it('can send a simple transaction from one account to another', async () => { + const ganacheOptions = { + accounts: [ + { + secretKey: '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + balance: 25000000000000000000, + }, + ], + } + await withFixtures({ fixtures: 'imported-account', ganacheOptions }, async ({ driver }) => { + const passwordField = await driver.findElement(By.css('#password')) + await passwordField.sendKeys('correct horse battery staple') + await passwordField.sendKeys(Key.ENTER) + await driver.clickElement(By.css('[data-testid="transaction-view-send"]')) + const recipientAddressField = await driver.findElement(By.css('[data-testid="ens-input"]')) + await recipientAddressField.sendKeys('0x985c30949c92df7a0bd42e0f3e3d539ece98db24') + const amountField = await driver.findElement(By.css('.unit-input__input')) + await amountField.sendKeys('1') + await driver.clickElement(By.css('[data-testid="page-container-footer-next"]')) + await driver.clickElement(By.css('[data-testid="page-container-footer-next"]')) + await driver.findElement(By.css('.transaction-list-item')) + }) + }) +}) diff --git a/ui/app/components/app/transaction-view-balance/transaction-view-balance.component.js b/ui/app/components/app/transaction-view-balance/transaction-view-balance.component.js index 73905574e..91032b49c 100644 --- a/ui/app/components/app/transaction-view-balance/transaction-view-balance.component.js +++ b/ui/app/components/app/transaction-view-balance/transaction-view-balance.component.js @@ -117,6 +117,7 @@ export default class TransactionViewBalance extends PureComponent { }) history.push(SEND_ROUTE) }} + data-testid="transaction-view-send" > { t('send') } diff --git a/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js b/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js index 338df83d8..7927c20d8 100644 --- a/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js +++ b/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js @@ -45,6 +45,7 @@ export default class PageContainerFooter extends Component { large={buttonSizeLarge} className="page-container__footer-button" onClick={e => onCancel(e)} + data-testid="page-container-footer-cancel" > { cancelText || this.context.t('cancel') } @@ -56,6 +57,7 @@ export default class PageContainerFooter extends Component { className="page-container__footer-button" disabled={disabled} onClick={e => onSubmit(e)} + data-testid="page-container-footer-next" > { submitText || this.context.t('next') } diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js index 15aa3db24..bac9ab3e6 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js +++ b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js @@ -163,6 +163,7 @@ export default class EnsInput extends Component { onPaste={this.onPaste} value={selectedAddress || input} autoFocus + data-testid="ens-input" />
    Date: Mon, 20 Jan 2020 18:40:01 -0400 Subject: [PATCH 157/689] Add 1 second pause at the beginning of each e2e test run (#7872) There have been intermittent test failures at the beginning of various e2e test runs. Most tests start with waiting for the 'Welcome' button to be visible and enabled, which means waiting for the loading screen to go away. It looks like the reason the test intermittently fails is that sometimes the loading screen doesn't appear until a few moments _after_ the page loads (or that it vanishes and comes back). It was rather difficult to track down each possible cause for the loading screens, so in the meantime a pause has been added at the start of each run. This should hopefully suffice to ensure the momentary gap in loading has been passed by the time the first test starts up. --- test/e2e/webdriver/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/e2e/webdriver/index.js b/test/e2e/webdriver/index.js index 4c172d340..fa8b3837e 100644 --- a/test/e2e/webdriver/index.js +++ b/test/e2e/webdriver/index.js @@ -13,6 +13,8 @@ async function buildWebDriver ({ responsive, port } = {}) { const driver = new Driver(seleniumDriver, browser, extensionUrl) await driver.navigate() + await driver.delay(1000) + return { driver, extensionId, From 6e49d0b5b5b7e29d4200067d9ad4d5bdf7229086 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 21 Jan 2020 11:19:35 -0400 Subject: [PATCH 158/689] Remove unnecessary `shouldComponentUpdate` (#7875) The `confirm-seed-phrase` component extends PureComponent, so it doesn't need a `shouldComponentUpdate` function. The state is effectively immutable, as all state is either a primitive type or is updated with new instances rather than mutation. Removing this function will silence a warning message printed to the console during e2e tests (React doesn't want you to set this function on `PureComponent`s). Removing this function also exposed an unused piece of state, which has also been removed. --- .../confirm-seed-phrase.component.js | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js index 9de7d61c4..309ece594 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js @@ -38,27 +38,6 @@ export default class ConfirmSeedPhrase extends PureComponent { pendingSeedIndices: [], draggingSeedIndex: -1, hoveringIndex: -1, - isDragging: false, - } - - shouldComponentUpdate (nextProps, nextState) { - const { seedPhrase } = this.props - const { - selectedSeedIndices, - shuffledSeedWords, - pendingSeedIndices, - draggingSeedIndex, - hoveringIndex, - isDragging, - } = this.state - - return seedPhrase !== nextProps.seedPhrase || - draggingSeedIndex !== nextState.draggingSeedIndex || - isDragging !== nextState.isDragging || - hoveringIndex !== nextState.hoveringIndex || - selectedSeedIndices.join(' ') !== nextState.selectedSeedIndices.join(' ') || - shuffledSeedWords.join(' ') !== nextState.shuffledSeedWords.join(' ') || - pendingSeedIndices.join(' ') !== nextState.pendingSeedIndices.join(' ') } componentDidMount () { From d27f2ee7d6406bdd5b850f537627b72f0dc89ef7 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 21 Jan 2020 11:31:56 -0400 Subject: [PATCH 159/689] Fix intermittent e2e test failure (#7873) The 'can retype the seed phrase' test would fail sometimes when one of the words in the seed phrase was a subset of another word (e.g. 'issue' and 'tissue'). This is because the selector used to find the word looked for the first element that contained the text, rather than an exact match. To simplify the selector and make it more reliable, test ids were added to each seed phrase word. The selector now uses CSS instead of XPath, and it only finds exact matches. A test id was also added to the div containing the shuffled seed words to select from, so that the chosen seed words wouldn't be selected in place of the real target when the same word appears twice. --- test/e2e/address-book.spec.js | 3 +-- test/e2e/incremental-security.spec.js | 3 +-- test/e2e/metamask-responsive-ui.spec.js | 3 +-- test/e2e/metamask-ui.spec.js | 3 +-- .../confirm-seed-phrase/confirm-seed-phrase.component.js | 2 +- .../confirm-seed-phrase/draggable-seed.component.js | 1 + 6 files changed, 6 insertions(+), 9 deletions(-) diff --git a/test/e2e/address-book.spec.js b/test/e2e/address-book.spec.js index 8b6ef3310..6d41596db 100644 --- a/test/e2e/address-book.spec.js +++ b/test/e2e/address-book.spec.js @@ -98,8 +98,7 @@ describe('MetaMask', function () { }) async function clickWordAndWait (word) { - const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]` - await driver.clickElement(By.xpath(xpath)) + await driver.clickElement(By.css(`[data-testid="seed-phrase-shuffled"] [data-testid="draggable-seed-${word}"]`)) await driver.delay(tinyDelayMs) } diff --git a/test/e2e/incremental-security.spec.js b/test/e2e/incremental-security.spec.js index 197c94152..3287ca0ae 100644 --- a/test/e2e/incremental-security.spec.js +++ b/test/e2e/incremental-security.spec.js @@ -171,8 +171,7 @@ describe('MetaMask', function () { }) async function clickWordAndWait (word) { - const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]` - await driver.clickElement(By.xpath(xpath)) + await driver.clickElement(By.css(`[data-testid="seed-phrase-shuffled"] [data-testid="draggable-seed-${word}"]`)) await driver.delay(tinyDelayMs) } diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index b06c11f8e..b57f9bb61 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -93,8 +93,7 @@ describe('MetaMask', function () { }) async function clickWordAndWait (word) { - const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]` - await driver.clickElement(By.xpath(xpath)) + await driver.clickElement(By.css(`[data-testid="seed-phrase-shuffled"] [data-testid="draggable-seed-${word}"]`)) await driver.delay(tinyDelayMs) } diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index 3433d68ed..09ce14da9 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -95,8 +95,7 @@ describe('MetaMask', function () { }) async function clickWordAndWait (word) { - const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]` - await driver.clickElement(By.xpath(xpath)) + await driver.clickElement(By.css(`[data-testid="seed-phrase-shuffled"] [data-testid="draggable-seed-${word}"]`)) await driver.delay(tinyDelayMs) } diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js index 309ece594..8f51e89a3 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js @@ -163,7 +163,7 @@ export default class ConfirmSeedPhrase extends PureComponent { { this.renderPendingSeeds() } { this.renderSelectedSeeds() }
    -
    +
    { shuffledSeedWords.map((word, index) => { const isSelected = selectedSeedIndices.includes(index) diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js index 7a23738ff..7293e6098 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js @@ -58,6 +58,7 @@ class DraggableSeed extends Component { 'confirm-seed-phrase__seed-word--drop-hover': isOver && canDrop, })} onClick={onClick} + data-testid={`draggable-seed-${selected ? 'selected-' : ''}${word}`} > { word }
    From 5734f7210c70eb4bcd184ece4c0d6c3e3f7b5ff7 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 21 Jan 2020 12:02:45 -0400 Subject: [PATCH 160/689] Add benchmark script (#7869) The script `benchmark.js` will collect page load metrics from the extension, and print them to a file or the console. A method for collecting metrics was added to the web driver to help with this. This script will calculate the min, max, average, and standard deviation for four metrics: 'firstPaint', 'domContentLoaded', 'load', and 'domInteractive'. The variation between samples is sometimes high, with the results varying between samples if only 3 were taken. However, all tests I've done locally with 5 samples have produced results within one standard deviation of each other. The default number of samples has been set to 10, which should be more than enough to produce consistent results. The benchmark can be run with the npm script `benchmark:chrome` or `benchmark:firefox`, e.g. `yarn benchmark:chrome`. --- package.json | 2 + test/e2e/benchmark.js | 166 +++++++++++++++++++++++++++++++++++ test/e2e/webdriver/driver.js | 29 ++++++ 3 files changed, 197 insertions(+) create mode 100644 test/e2e/benchmark.js diff --git a/package.json b/package.json index 5d2c3a90c..f6175be36 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,8 @@ "doc": "jsdoc -c development/.jsdoc.json", "publish-docs": "gh-pages -d docs/jsdocs", "start:test": "gulp dev:test", + "benchmark:chrome": "SELENIUM_BROWSER=chrome node test/e2e/benchmark.js", + "benchmark:firefox": "SELENIUM_BROWSER=firefox node test/e2e/benchmark.js", "build:test": "gulp build:test", "test": "yarn test:unit && yarn lint", "dapp": "node development/static-server.js test/e2e/contract-test --port 8080", diff --git a/test/e2e/benchmark.js b/test/e2e/benchmark.js new file mode 100644 index 000000000..caaba39b3 --- /dev/null +++ b/test/e2e/benchmark.js @@ -0,0 +1,166 @@ +#!/usr/bin/env node + +const path = require('path') +const { promises: fs, constants: fsConstants } = require('fs') +const { By, Key } = require('selenium-webdriver') +const { withFixtures } = require('./helpers') +const { PAGES } = require('./webdriver/driver') + +const DEFAULT_NUM_SAMPLES = 10 +const ALL_PAGES = Object.values(PAGES) + +async function measurePage (pageName) { + let metrics + await withFixtures({ fixtures: 'imported-account' }, async ({ driver }) => { + const passwordField = await driver.findElement(By.css('#password')) + await passwordField.sendKeys('correct horse battery staple') + await passwordField.sendKeys(Key.ENTER) + await driver.navigate(pageName) + await driver.delay(1000) + metrics = await driver.collectMetrics() + }) + return metrics +} + +function calculateResult (calc) { + return (result) => { + const calculatedResult = {} + for (const key of Object.keys(result)) { + calculatedResult[key] = calc(result[key]) + } + return calculatedResult + } +} +const calculateSum = (array) => array.reduce((sum, val) => sum + val) +const calculateAverage = (array) => calculateSum(array) / array.length +const minResult = calculateResult((array) => Math.min(...array)) +const maxResult = calculateResult((array) => Math.max(...array)) +const averageResult = calculateResult(array => calculateAverage(array)) +const standardDeviationResult = calculateResult((array) => { + const average = calculateAverage(array) + const squareDiffs = array.map(value => Math.pow(value - average, 2)) + return Math.sqrt(calculateAverage(squareDiffs)) +}) + +async function profilePageLoad (pages, numSamples) { + const results = {} + for (const pageName of pages) { + const runResults = [] + for (let i = 0; i < numSamples; i += 1) { + runResults.push(await measurePage(pageName)) + } + + if (runResults.some(result => result.navigation.lenth > 1)) { + throw new Error(`Multiple navigations not supported`) + } else if (runResults.some(result => result.navigation[0].type !== 'navigate')) { + throw new Error(`Navigation type ${runResults.find(result => result.navigation[0].type !== 'navigate').navigation[0].type} not supported`) + } + + const result = { + firstPaint: runResults.map(result => result.paint['first-paint']), + domContentLoaded: runResults.map(result => result.navigation[0] && result.navigation[0].domContentLoaded), + load: runResults.map(result => result.navigation[0] && result.navigation[0].load), + domInteractive: runResults.map(result => result.navigation[0] && result.navigation[0].domInteractive), + } + + results[pageName] = { + min: minResult(result), + max: maxResult(result), + average: averageResult(result), + standardDeviation: standardDeviationResult(result), + } + } + return results +} + +async function isWritable (directory) { + try { + await fs.access(directory, fsConstants.W_OK) + return true + } catch (error) { + if (error.code !== 'EACCES') { + throw error + } + return false + } +} + +async function getFirstParentDirectoryThatExists (directory) { + while (true) { + try { + await fs.access(directory, fsConstants.F_OK) + return directory + } catch (error) { + if (error.code !== 'ENOENT') { + throw error + } else if (directory === path.dirname(directory)) { + throw new Error('Failed to find parent directory that exists') + } + directory = path.dirname(directory) + } + } +} + +async function main () { + const args = process.argv.slice(2) + + let pages = ['notification'] + let numSamples = DEFAULT_NUM_SAMPLES + let outputPath + let outputDirectory + let existingParentDirectory + + while (args.length) { + if (/^(--pages|-p)$/i.test(args[0])) { + if (args[1] === undefined) { + throw new Error('Missing pages argument') + } + pages = args[1].split(',') + for (const page of pages) { + if (!ALL_PAGES.includes(page)) { + throw new Error(`Invalid page: '${page}`) + } + } + args.splice(0, 2) + } else if (/^(--samples|-s)$/i.test(args[0])) { + if (args[1] === undefined) { + throw new Error('Missing number of samples') + } + numSamples = parseInt(args[1], 10) + if (isNaN(numSamples)) { + throw new Error(`Invalid 'samples' argument given: '${args[1]}'`) + } + args.splice(0, 2) + } else if (/^(--out|-o)$/i.test(args[0])) { + if (args[1] === undefined) { + throw new Error('Missing output filename') + } + outputPath = path.resolve(args[1]) + outputDirectory = path.dirname(outputPath) + existingParentDirectory = await getFirstParentDirectoryThatExists(outputDirectory) + if (!await isWritable(existingParentDirectory)) { + throw new Error(`Specified directory is not writable: '${args[1]}'`) + } + args.splice(0, 2) + } else { + throw new Error(`Unrecognized argument: '${args[0]}'`) + } + } + + const results = await profilePageLoad(pages, numSamples) + + if (outputPath) { + if (outputDirectory !== existingParentDirectory) { + await fs.mkdir(outputDirectory, { recursive: true }) + } + await fs.writeFile(outputPath, JSON.stringify(results, null, 2)) + } else { + console.log(JSON.stringify(results, null, 2)) + } +} + +main() + .catch(e => { + console.error(e) + process.exit(1) + }) diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index 90a4e32a9..4369f88cd 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -91,6 +91,12 @@ class Driver { return await this.driver.get(`${this.extensionUrl}/${page}.html`) } + // Metrics + + async collectMetrics () { + return await this.driver.executeScript(collectMetrics) + } + // Window management async openNewPage (url) { @@ -180,6 +186,29 @@ class Driver { } } +function collectMetrics () { + const results = { + paint: {}, + navigation: [], + } + + performance.getEntriesByType('paint').forEach((paintEntry) => { + results.paint[paintEntry.name] = paintEntry.startTime + }) + + performance.getEntriesByType('navigation').forEach((navigationEntry) => { + results.navigation.push({ + domContentLoaded: navigationEntry.domContentLoadedEventEnd, + load: navigationEntry.loadEventEnd, + domInteractive: navigationEntry.domInteractive, + redirectCount: navigationEntry.redirectCount, + type: navigationEntry.type, + }) + }) + + return results +} + Driver.PAGES = { HOME: 'home', NOTIFICATION: 'notification', From e35d4edac5e2ae329a01ef5de71484ea7d0dfed1 Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Tue, 21 Jan 2020 10:12:38 -0800 Subject: [PATCH 161/689] Update inpage provider (#7878) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index f6175be36..8ce2d5a26 100644 --- a/package.json +++ b/package.json @@ -131,7 +131,7 @@ "lodash.shuffle": "^4.2.0", "loglevel": "^1.4.1", "luxon": "^1.8.2", - "metamask-inpage-provider": "^4.0.2", + "metamask-inpage-provider": "^4.0.3", "metamask-logo": "^2.1.4", "mkdirp": "^0.5.1", "multihashes": "^0.4.12", diff --git a/yarn.lock b/yarn.lock index 0ec33b66f..95a81b540 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18639,10 +18639,10 @@ mersenne-twister@^1.0.1: resolved "https://registry.yarnpkg.com/mersenne-twister/-/mersenne-twister-1.1.0.tgz#f916618ee43d7179efcf641bec4531eb9670978a" integrity sha1-+RZhjuQ9cXnvz2Qb7EUx65Zwl4o= -metamask-inpage-provider@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/metamask-inpage-provider/-/metamask-inpage-provider-4.0.2.tgz#50d9e46b5fdd6610ce185a165004e3c6b762dbb3" - integrity sha512-GXoMa7rP+fx9CriCA+RPHjvJJpfy9531eRdMvbDKv0q95/1pvtzYkj6BdzjxtbM91n4zYl6tmeKDILu+le9Qog== +metamask-inpage-provider@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/metamask-inpage-provider/-/metamask-inpage-provider-4.0.3.tgz#856698255c2153b82203402c6b5337ca6363d9b0" + integrity sha512-JKbGkkR7qg+Z5Dayg6rpfXXzSVcXcp3BENbk2zgWwp/Aa70Sf9MHC7m364FeyIIio9A2r9OuJKV0Bcwmz0h+xg== dependencies: eth-json-rpc-errors "^2.0.0" fast-deep-equal "^2.0.1" From 3f1971bb10f716b94b3bb90b567be415e8536c72 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 21 Jan 2020 17:14:51 -0330 Subject: [PATCH 162/689] Remove unused browser-passworder dependency from package.json (#7879) --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 8ce2d5a26..0cbeef17b 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,6 @@ "bip39": "^2.2.0", "bluebird": "^3.5.0", "bn.js": "^4.11.7", - "browser-passworder": "^2.0.3", "browserify-derequire": "^0.9.4", "c3": "^0.6.7", "classnames": "^2.2.5", From e02b229df6661248f17dfac692f2ec4f12523dc0 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 21 Jan 2020 17:12:40 -0400 Subject: [PATCH 163/689] Add margin of error metric (#7877) A margin of error metric has been added, which is calculated from a 95% confidence interval. This confidence interval is calculated using Student's t-distribution, which is generally preferred for smaller sample sizes (< ~30) of populations following a normal distribution. --- package.json | 1 + test/e2e/benchmark.js | 5 +++++ yarn.lock | 25 +++++++++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/package.json b/package.json index 0cbeef17b..eb7f465d2 100644 --- a/package.json +++ b/package.json @@ -302,6 +302,7 @@ "stylelint-config-standard": "^18.2.0", "testem": "^2.16.0", "through2": "^2.0.3", + "ttest": "^2.1.1", "vinyl-buffer": "^1.0.1", "vinyl-source-stream": "^2.0.0", "watchify": "^3.11.1" diff --git a/test/e2e/benchmark.js b/test/e2e/benchmark.js index caaba39b3..d89cd5666 100644 --- a/test/e2e/benchmark.js +++ b/test/e2e/benchmark.js @@ -2,6 +2,7 @@ const path = require('path') const { promises: fs, constants: fsConstants } = require('fs') +const ttest = require('ttest') const { By, Key } = require('selenium-webdriver') const { withFixtures } = require('./helpers') const { PAGES } = require('./webdriver/driver') @@ -41,6 +42,9 @@ const standardDeviationResult = calculateResult((array) => { const squareDiffs = array.map(value => Math.pow(value - average, 2)) return Math.sqrt(calculateAverage(squareDiffs)) }) +// 95% margin of error calculated using Student's t-distrbution +const calculateMarginOfError = (array) => ttest(array).confidence()[1] - calculateAverage(array) +const marginOfErrorResult = calculateResult((array) => calculateMarginOfError(array)) async function profilePageLoad (pages, numSamples) { const results = {} @@ -68,6 +72,7 @@ async function profilePageLoad (pages, numSamples) { max: maxResult(result), average: averageResult(result), standardDeviation: standardDeviationResult(result), + marginOfError: marginOfErrorResult(result), } } return results diff --git a/yarn.lock b/yarn.lock index 95a81b540..5679b8b42 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6606,6 +6606,11 @@ ccount@^1.0.0, ccount@^1.0.3: resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.4.tgz#9cf2de494ca84060a2a8d2854edd6dfb0445f386" integrity sha512-fpZ81yYfzentuieinmGnphk0pLkOTMm6MZdVqwd77ROvhko6iujLNGrHH5E7utq3ygWklwfmwuG+A7P+NpqT6w== +cephes@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/cephes/-/cephes-1.2.0.tgz#4d246b622bc488ab8c982a1f702f0c9f49705d96" + integrity sha512-twuUuJRrIrsELHz6foJtZlqrz6FC36zoHZJvvThsrM1UWPKxyoilw1Rka6Hk0AmPFKHKUoGwGfAtvNZNtNZu0g== + chai-checkmark@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/chai-checkmark/-/chai-checkmark-1.0.1.tgz#9fbb3c9ad9101f097ef288328d30f4227d74fffb" @@ -8970,6 +8975,13 @@ disposables@^1.0.1: resolved "https://registry.yarnpkg.com/disposables/-/disposables-1.0.2.tgz#36c6a674475f55a2d6913567a601444e487b4b6e" integrity sha1-NsamdEdfVaLWkTVnpgFETkh7S24= +distributions@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/distributions/-/distributions-2.1.0.tgz#7005f01898937fbe6404abda20fa7f4aaaa058e0" + integrity sha512-4eov7WXRip5Tu0K7Y51W1oVt+DcvkoE0EzsvbLzgedC/n4PUpYXHqk6vo/OH1HteBHp5Vm6cmfnInf9NAXM4qQ== + dependencies: + cephes "^1.1.2" + dlv@^1.1.2, dlv@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" @@ -26071,6 +26083,11 @@ sumchecker@^2.0.2: dependencies: debug "^2.2.0" +summary@0.3.x: + version "0.3.2" + resolved "https://registry.yarnpkg.com/summary/-/summary-0.3.2.tgz#3d7439b30dab3449dfd66840a822838d4a4a8561" + integrity sha1-PXQ5sw2rNEnf1mhAqCKDjUpKhWE= + superagent-proxy@^1.0.3, superagent-proxy@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/superagent-proxy/-/superagent-proxy-2.0.0.tgz#9f57515cd660e2e9ce55c0e6bd70f92eb07c3ee0" @@ -27056,6 +27073,14 @@ tsscmp@1.0.6: resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA== +ttest@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ttest/-/ttest-2.1.1.tgz#ee0c9118fff6580a5c8d6cfe69845219e075277f" + integrity sha512-YlRYswipptMVPLil4bsblnp2HXmcAR0McnfnuCM26EYrBZTCdUc/BVPuqZoaMb9h06smAPhe+s+wFMtYOULVGQ== + dependencies: + distributions "^2.1.0" + summary "0.3.x" + tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" From b095dc0347ca9f2f07b85095ef714372557fe31e Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Tue, 21 Jan 2020 14:09:53 -0800 Subject: [PATCH 164/689] Change "Log In/Out" terminology to "Unlock/Lock" (#7853) * log out/in -> lock/unlock --- app/_locales/am/messages.json | 9 ++-- app/_locales/ar/messages.json | 9 ++-- app/_locales/bg/messages.json | 9 ++-- app/_locales/bn/messages.json | 9 ++-- app/_locales/ca/messages.json | 9 ++-- app/_locales/cs/messages.json | 4 +- app/_locales/da/messages.json | 9 ++-- app/_locales/de/messages.json | 9 ++-- app/_locales/el/messages.json | 9 ++-- app/_locales/en/messages.json | 21 ++++---- app/_locales/es/messages.json | 9 ++-- app/_locales/es_419/messages.json | 9 ++-- app/_locales/et/messages.json | 9 ++-- app/_locales/fa/messages.json | 9 ++-- app/_locales/fi/messages.json | 9 ++-- app/_locales/fil/messages.json | 9 ++-- app/_locales/fr/messages.json | 9 ++-- app/_locales/he/messages.json | 9 ++-- app/_locales/hi/messages.json | 9 ++-- app/_locales/hn/messages.json | 4 +- app/_locales/hr/messages.json | 9 ++-- app/_locales/ht/messages.json | 5 +- app/_locales/hu/messages.json | 9 ++-- app/_locales/id/messages.json | 9 ++-- app/_locales/it/messages.json | 9 ++-- app/_locales/ja/messages.json | 8 +-- app/_locales/kn/messages.json | 9 ++-- app/_locales/ko/messages.json | 9 ++-- app/_locales/lt/messages.json | 9 ++-- app/_locales/lv/messages.json | 9 ++-- app/_locales/ms/messages.json | 9 ++-- app/_locales/nl/messages.json | 4 +- app/_locales/no/messages.json | 9 ++-- app/_locales/pl/messages.json | 9 ++-- app/_locales/pt/messages.json | 4 +- app/_locales/pt_BR/messages.json | 9 ++-- app/_locales/ro/messages.json | 9 ++-- app/_locales/ru/messages.json | 9 ++-- app/_locales/sk/messages.json | 9 ++-- app/_locales/sl/messages.json | 9 ++-- app/_locales/sr/messages.json | 9 ++-- app/_locales/sv/messages.json | 9 ++-- app/_locales/sw/messages.json | 9 ++-- app/_locales/ta/messages.json | 5 +- app/_locales/th/messages.json | 5 +- app/_locales/tr/messages.json | 4 +- app/_locales/uk/messages.json | 9 ++-- app/_locales/vi/messages.json | 2 +- app/_locales/zh_CN/messages.json | 11 ++-- app/_locales/zh_TW/messages.json | 14 +++--- app/scripts/controllers/app-state.js | 4 +- app/scripts/migrations/041.js | 24 +++++++++ app/scripts/migrations/index.js | 1 + test/e2e/address-book.spec.js | 6 +-- test/e2e/from-import-ui.spec.js | 8 +-- test/e2e/metamask-responsive-ui.spec.js | 6 +-- test/e2e/metamask-ui.spec.js | 14 +++--- .../account-menu/account-menu.component.js | 4 +- ui/app/components/app/account-menu/index.scss | 2 +- ui/app/pages/routes/index.js | 10 ++-- .../advanced-tab/advanced-tab.component.js | 50 +++++++++---------- .../advanced-tab/advanced-tab.container.js | 10 ++-- .../tests/advanced-tab-component.test.js | 12 ++--- .../unlock-page/unlock-page.component.js | 2 +- ui/app/store/actions.js | 4 +- 65 files changed, 240 insertions(+), 341 deletions(-) create mode 100644 app/scripts/migrations/041.js diff --git a/app/_locales/am/messages.json b/app/_locales/am/messages.json index ad584f304..5c1a04718 100644 --- a/app/_locales/am/messages.json +++ b/app/_locales/am/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "አይነታ" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "በራስ ሰር ዘግቶ መውጫ ሰዓት ቆጣሪ (ደቂቃ)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "MetaMask በራስ ሰር መንገድ ዘግቶ ከመውጣቱ በፊት የቦዘነ ጊዜን በደቂቃዎች ሙላ" }, "average": { @@ -648,10 +648,7 @@ "loadMore": { "message": "ተጨማሪ ጫን" }, - "login": { - "message": "በመለያ ግባ" - }, - "logout": { + "lock": { "message": "ዘግተህ ውጣ" }, "mainnet": { diff --git a/app/_locales/ar/messages.json b/app/_locales/ar/messages.json index 464dbf22f..0ba042127 100644 --- a/app/_locales/ar/messages.json +++ b/app/_locales/ar/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "الصفات" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "مؤقت تسجيل الخروج التلقائي (بالدقائق)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "اضبط مهلة السكون بالدقائق التي يقوم MetaMask بتسجيل الخروج بعدها تلقائيًا" }, "average": { @@ -644,10 +644,7 @@ "localhost": { "message": "المضيف المحلي 8545" }, - "login": { - "message": "تسجيل الدخول" - }, - "logout": { + "lock": { "message": "تسجيل الخروج" }, "mainnet": { diff --git a/app/_locales/bg/messages.json b/app/_locales/bg/messages.json index 620660809..872111178 100644 --- a/app/_locales/bg/messages.json +++ b/app/_locales/bg/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Функции" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Таймер за автоматично излизане (минути)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Задайте времето на неактивност в минути, преди MetaMask автоматично да Ви отпише от акаунта" }, "average": { @@ -647,10 +647,7 @@ "localhost": { "message": "Локален хост 8545" }, - "login": { - "message": "Вход" - }, - "logout": { + "lock": { "message": "Излизане" }, "mainnet": { diff --git a/app/_locales/bn/messages.json b/app/_locales/bn/messages.json index a5aa8f366..869281beb 100644 --- a/app/_locales/bn/messages.json +++ b/app/_locales/bn/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "গুণাবলী" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "স্বয়ংক্রিয়-লগ আউট টাইমার (মিনিট)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "MetaMask স্বয়ংক্রিয়ভাবে লগ আউট করার আগে নিষ্ক্রিয় থাকার সময় মিনিটে সেট করুন" }, "average": { @@ -651,10 +651,7 @@ "localhost": { "message": "লোকালহোস্ট 8545" }, - "login": { - "message": "লগইন করুন" - }, - "logout": { + "lock": { "message": "লগ আউট করুন" }, "mainnet": { diff --git a/app/_locales/ca/messages.json b/app/_locales/ca/messages.json index 042e4b258..201d321e0 100644 --- a/app/_locales/ca/messages.json +++ b/app/_locales/ca/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Atribucions" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Temporitzador de tancament de sessió automàtic (minuts)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Configura el temps de repòs com minuts abans que MetaMask tanqui la sessió automàticament" }, "average": { @@ -635,10 +635,7 @@ "localhost": { "message": "Host local 8545" }, - "login": { - "message": "Inicia sessió" - }, - "logout": { + "lock": { "message": "Tanca la sessió" }, "mainnet": { diff --git a/app/_locales/cs/messages.json b/app/_locales/cs/messages.json index 3df744de1..1ffc1d2f6 100644 --- a/app/_locales/cs/messages.json +++ b/app/_locales/cs/messages.json @@ -268,10 +268,10 @@ "loadingTokens": { "message": "Načítám tokeny..." }, - "login": { + "unlock": { "message": "Přihlásit" }, - "logout": { + "lock": { "message": "Odhlásit" }, "message": { diff --git a/app/_locales/da/messages.json b/app/_locales/da/messages.json index c4e5105ff..88b457aec 100644 --- a/app/_locales/da/messages.json +++ b/app/_locales/da/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Tilskrivninger" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Timer for automatisk udlogning (minutter)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Indstil den passive tid i minutter, før MetaMask automatisk logger dig ud" }, "average": { @@ -638,10 +638,7 @@ "loadMore": { "message": "Indlæs Mere" }, - "login": { - "message": "Log Ind" - }, - "logout": { + "lock": { "message": "Log ud" }, "mainnet": { diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index 6e0ce19e0..1c2a4be35 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -106,10 +106,10 @@ "attributions": { "message": "Was wir verwenden" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Auto-Logout-Timer (Minuten)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Stellen Sie die Ruhezeit in Minuten ein, nach der sich MetaMask automatisch ausloggen soll" }, "average": { @@ -627,10 +627,7 @@ "loadMore": { "message": "Mehr laden" }, - "login": { - "message": "Login" - }, - "logout": { + "lock": { "message": "Ausloggen" }, "mainnet": { diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index 3f152fc6a..84efaf273 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Αποδόσεις" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Χρονόμετρο Αυτόματης Αποσύνδεσης (λεπτά)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Ρυθμίστε τον χρόνο αδράνειας σε λεπτά πριν αποσυνδεθεί αυτόματα το MetaMask" }, "average": { @@ -648,10 +648,7 @@ "localhost": { "message": "Τοπικός Υπολογιστής 8545" }, - "login": { - "message": "Σύνδεση" - }, - "logout": { + "lock": { "message": "Αποσύνδεση" }, "mainnet": { diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 2c98ed485..665affeee 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -155,11 +155,11 @@ "attributions": { "message": "Attributions" }, - "autoLogoutTimeLimit": { - "message": "Auto-Logout Timer (minutes)" + "autoLockTimeLimit": { + "message": "Auto-Lock Timer (minutes)" }, - "autoLogoutTimeLimitDescription": { - "message": "Set the idle time in minutes before MetaMask will automatically log out" + "autoLockTimeLimitDescription": { + "message": "Set the idle time in minutes before MetaMask will become locked." }, "average": { "message": "Average" @@ -788,14 +788,11 @@ "localhost": { "message": "Localhost 8545" }, - "login": { - "message": "Log In" + "lock": { + "message": "Lock" }, - "logout": { - "message": "Log out" - }, - "logoutTimeTooGreat": { - "message": "Logout time is too great" + "lockTimeTooGreat": { + "message": "Lock time is too great" }, "mainnet": { "message": "Main Ethereum Network" @@ -1312,7 +1309,7 @@ "message": "3. Start using dApps and more!" }, "step3HardwareWalletMsg": { - "message": "Use your hardware account like you would with any Ethereum account. Log in to dApps, send Eth, buy and store ERC20 tokens and Non-Fungible tokens like CryptoKitties." + "message": "Use your hardware account like you would with any Ethereum account. Connect to dApps, send ETH, buy and store ERC20 tokens and non-fungible tokens like CryptoKitties." }, "storePhrase": { "message": "Store this phrase in a password manager like 1Password." diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index 9e83d05d9..32c6bb15f 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -106,10 +106,10 @@ "attributions": { "message": "Atribuciones" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Temporizador Auto-Cierre (minutos)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Establece el tiempo de inactividad en minutos antes de que MetaMask cierre la sesión automáticamente." }, "average": { @@ -533,10 +533,7 @@ "loadMore": { "message": "Cargar Más" }, - "login": { - "message": "Ingresar" - }, - "logout": { + "lock": { "message": "Cerrar sesión" }, "mainnet": { diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index b6ab61496..e2d386e0a 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Atribuciones" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Temporizador de cierre de sesión automático (minutos)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Configura tu tiempo de inactividad en minutos para controlar cuándo MetaMask cerrará tu sesión de forma automática" }, "average": { @@ -639,10 +639,7 @@ "loadMore": { "message": "Cargar más" }, - "login": { - "message": "Iniciar sesión" - }, - "logout": { + "lock": { "message": "Cerrar sesión" }, "mainnet": { diff --git a/app/_locales/et/messages.json b/app/_locales/et/messages.json index e11a90b16..3946d4fad 100644 --- a/app/_locales/et/messages.json +++ b/app/_locales/et/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Omistamised" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Automaatse väljalogimise taimer (minutites)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Seadistage jõudeolek minutites, enne kui MetaMask automaatselt välja logib" }, "average": { @@ -641,10 +641,7 @@ "loadMore": { "message": "Laadi rohkem" }, - "login": { - "message": "Logi sisse" - }, - "logout": { + "lock": { "message": "Logi välja" }, "mainnet": { diff --git a/app/_locales/fa/messages.json b/app/_locales/fa/messages.json index d12b19fb8..94c041ff9 100644 --- a/app/_locales/fa/messages.json +++ b/app/_locales/fa/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "مواصفات" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "زمان سنج خروج-خودکار (دقایق)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "زمان های بیکار را به شکل دقیقه قبل از خروج MetaMask تنظیم کنید" }, "average": { @@ -651,10 +651,7 @@ "localhost": { "message": "Localhost 8545 " }, - "login": { - "message": "ورود" - }, - "logout": { + "lock": { "message": "خروج" }, "mainnet": { diff --git a/app/_locales/fi/messages.json b/app/_locales/fi/messages.json index 5b0a5f8ed..61df7c813 100644 --- a/app/_locales/fi/messages.json +++ b/app/_locales/fi/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Attribuutiot" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Automaattisen uloskirjautumisen ajastin (minuuttia)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Määritä, montako minuuttia MetaMask on ollut joutilaana ennen kuin sinut kirjataan automaattisesti ulos" }, "average": { @@ -648,10 +648,7 @@ "localhost": { "message": "Paikallisjoukko 8545" }, - "login": { - "message": "Kirjaudu sisään" - }, - "logout": { + "lock": { "message": "Kirjaudu ulos" }, "mainnet": { diff --git a/app/_locales/fil/messages.json b/app/_locales/fil/messages.json index 51cb76533..ff44ba30a 100644 --- a/app/_locales/fil/messages.json +++ b/app/_locales/fil/messages.json @@ -100,10 +100,10 @@ "attributions": { "message": "Mga Attribution" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Auto-Logout Timer (minuto)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "I-set ang idle time na minuto bago awtomatikong mag-log out ang MetaMask" }, "back": { @@ -595,10 +595,7 @@ "loadMore": { "message": "Mag-load Pa" }, - "login": { - "message": "Mag-log In" - }, - "logout": { + "lock": { "message": "Mag-log out" }, "memorizePhrase": { diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index 2f02eb8bb..5eb4dc066 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -106,10 +106,10 @@ "attemptToCancelDescription": { "message": "Faire une demande d'annulation ne garantit pas que votre transaction originale sera bien annulée. Dans le cas où l'annulation réussit, vous payerez les frais de transaction indiqués ci-dessus." }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Minuterie de déconnexion automatique (minutes)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Réglez le temps d'inactivité en minutes avant que MetaMask ne se déconnecte automatiquement." }, "average": { @@ -636,10 +636,7 @@ "loadMore": { "message": "Charger plus" }, - "login": { - "message": "Connexion" - }, - "logout": { + "lock": { "message": "Déconnexion" }, "mainnet": { diff --git a/app/_locales/he/messages.json b/app/_locales/he/messages.json index 3ee07502b..c7e14dc77 100644 --- a/app/_locales/he/messages.json +++ b/app/_locales/he/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "תכונות" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "טיימר התנתקות אוטומטית (דקות)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "הגדר/י את זמן היעדר הפעילות בדקות לפני ש-MetaMask יתנתק אוטומטית." }, "average": { @@ -648,10 +648,7 @@ "loadMore": { "message": "טען עוד" }, - "login": { - "message": "כניסה" - }, - "logout": { + "lock": { "message": "התנתקות" }, "mainnet": { diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index 46e3ef87a..9a2f69614 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "विशेषताएं" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "ऑटो-लॉगआउट टाइमर (मिनट)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "मेटामास्क से स्वचालित रूप से लॉग आउट होने से पहले निष्क्रिय समय को मिनटों में सेट करें" }, "average": { @@ -648,10 +648,7 @@ "localhost": { "message": "लोकलहोस्ट 8545" }, - "login": { - "message": "लॉग इन करें" - }, - "logout": { + "lock": { "message": "लॉग आउट" }, "mainnet": { diff --git a/app/_locales/hn/messages.json b/app/_locales/hn/messages.json index a9658e3a1..3ce391719 100644 --- a/app/_locales/hn/messages.json +++ b/app/_locales/hn/messages.json @@ -248,10 +248,10 @@ "localhost": { "message": "स्थानीयहोस्ट 8545" }, - "login": { + "unlock": { "message": "लॉग इन करें" }, - "logout": { + "lock": { "message": "लॉग आउट करें" }, "mainnet": { diff --git a/app/_locales/hr/messages.json b/app/_locales/hr/messages.json index 535d824ab..e3ce9f2b7 100644 --- a/app/_locales/hr/messages.json +++ b/app/_locales/hr/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Svojstva" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Brojač za automatsko odjavljivanje (minute)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Postavite stanje u mirovanju u minutama prije nego što se MetaMask automatski odjavi" }, "average": { @@ -644,10 +644,7 @@ "loadMore": { "message": "Učitaj više" }, - "login": { - "message": "Prijava" - }, - "logout": { + "lock": { "message": "Odjava" }, "mainnet": { diff --git a/app/_locales/ht/messages.json b/app/_locales/ht/messages.json index a5ff121ad..6ca9b5c44 100644 --- a/app/_locales/ht/messages.json +++ b/app/_locales/ht/messages.json @@ -386,10 +386,7 @@ "loadingTokens": { "message": "Telechaje Tokens..." }, - "login": { - "message": "Ouvri" - }, - "logout": { + "lock": { "message": "Dekonekte" }, "mainnet": { diff --git a/app/_locales/hu/messages.json b/app/_locales/hu/messages.json index 41e065e8b..1794413e1 100644 --- a/app/_locales/hu/messages.json +++ b/app/_locales/hu/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Attribúciók" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Automatikus kijelentkezés időzítő (perc)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Adja meg a MetaMask automatikus kijelentkezéséig tartó tétlen állapot idejét percekben " }, "average": { @@ -644,10 +644,7 @@ "loadMore": { "message": "Továbbiak betöltése" }, - "login": { - "message": "Belépés" - }, - "logout": { + "lock": { "message": "Kilépés" }, "mainnet": { diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index dd36a4141..5ca31e394 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Atribusi" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Jangka Waktu Keluar-Otomatis (menit)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Atur waktu diam dalam menit sebelum MetaMask mengeluarkan Anda secara otomatis" }, "average": { @@ -635,10 +635,7 @@ "loadMore": { "message": "Muat Lainnya" }, - "login": { - "message": "Masuk" - }, - "logout": { + "lock": { "message": "Keluar" }, "mainnet": { diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index 5cb30244d..3b7a4870c 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -103,10 +103,10 @@ "attributions": { "message": "Attribuzioni" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Timer di Logout Automatico (minuti)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Imposta il tempo di inattività dopo il quale MetaMask fa il log out automaticamente" }, "average": { @@ -624,10 +624,7 @@ "loadMore": { "message": "Carica di più" }, - "login": { - "message": "Accedi" - }, - "logout": { + "lock": { "message": "Disconnetti" }, "mainnet": { diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index 91a417449..2cb64059c 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -106,10 +106,10 @@ "attributions": { "message": "属性" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "自動ログアウト(分)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "MetaMaskが自動的にログアウトするまでのアイドル時間を分単位で設定します。" }, "average": { @@ -314,10 +314,10 @@ "loadingTokens": { "message": "トークンをロード中..." }, - "login": { + "unlock": { "message": "ログイン" }, - "logout": { + "lock": { "message": "ログアウト" }, "mainnet": { diff --git a/app/_locales/kn/messages.json b/app/_locales/kn/messages.json index 8f79e7966..61d7fe74b 100644 --- a/app/_locales/kn/messages.json +++ b/app/_locales/kn/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "ಗುಣಲಕ್ಷಣಗಳು" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "ಸ್ವಯಂ-ಲಾಗ್ಔಟ್‌ ಟೈಮರ್ (ನಿಮಿಷಗಳು)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "MetaMask ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಲಾಗ್ ಔಟ್‌ ಆಗುವ ಮೊದಲು ನಿಮಿಷಗಳಲ್ಲಿ ನಿಷ್ಕ್ರಿಯ ಸಮಯವನ್ನು ಹೊಂದಿಸಿ" }, "average": { @@ -651,10 +651,7 @@ "localhost": { "message": "ಲೋಕಲ್‌ಹೋಸ್ಟ್ 8545" }, - "login": { - "message": "ಲಾಗ್ ಇನ್" - }, - "logout": { + "lock": { "message": "ಲಾಗ್ ಔಟ್" }, "mainnet": { diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index 3c99005b8..346b7f4e3 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "속성" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "자동 로그아웃 타이머 (분)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "MetaMask가 자동으로 로그아웃되기 전 유휴 시간을 분 단위로 설정하세요" }, "average": { @@ -645,10 +645,7 @@ "localhost": { "message": "로컬호스트 8545" }, - "login": { - "message": "로그인" - }, - "logout": { + "lock": { "message": "로그아웃" }, "mainnet": { diff --git a/app/_locales/lt/messages.json b/app/_locales/lt/messages.json index 7c800d81a..a89974bcc 100644 --- a/app/_locales/lt/messages.json +++ b/app/_locales/lt/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Požymiai" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Automatinio atjungimo laikmatis (minutės)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Nustatykite laukimo trukmę minutėmis iki „MetaMask“ automatinio atsijungimo" }, "average": { @@ -651,10 +651,7 @@ "localhost": { "message": "Vietinis serveris 8545" }, - "login": { - "message": "Prisijungti" - }, - "logout": { + "lock": { "message": "Atsijungti" }, "mainnet": { diff --git a/app/_locales/lv/messages.json b/app/_locales/lv/messages.json index 303774c35..98a61ee46 100644 --- a/app/_locales/lv/messages.json +++ b/app/_locales/lv/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Atribūti" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Automātiskās izrakstīšanās taimeris (minūtes)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Iestatiet bezdarbības laiku minūtēs, pēc kura MetaMask veiks automātisku izrakstīšanu" }, "average": { @@ -647,10 +647,7 @@ "localhost": { "message": "Resursdators 8545" }, - "login": { - "message": "Pierakstīties" - }, - "logout": { + "lock": { "message": "Izrakstīties" }, "mainnet": { diff --git a/app/_locales/ms/messages.json b/app/_locales/ms/messages.json index 172009ec0..aaf4cca59 100644 --- a/app/_locales/ms/messages.json +++ b/app/_locales/ms/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Atribusi" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Pemasa Logout Automatik (minit)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Tetapkan masa melahu dalam minit sebelum MetaMask log keluar secara automatik" }, "average": { @@ -628,10 +628,7 @@ "loadMore": { "message": "Muat Lagi" }, - "login": { - "message": "Log Masuk" - }, - "logout": { + "lock": { "message": "Log keluar" }, "mainnet": { diff --git a/app/_locales/nl/messages.json b/app/_locales/nl/messages.json index 8c5032ad3..6da9261cf 100644 --- a/app/_locales/nl/messages.json +++ b/app/_locales/nl/messages.json @@ -239,10 +239,10 @@ "loadingTokens": { "message": "Tokens laden ..." }, - "login": { + "unlock": { "message": "Log in" }, - "logout": { + "lock": { "message": "Uitloggen" }, "mainnet": { diff --git a/app/_locales/no/messages.json b/app/_locales/no/messages.json index a1ec7e119..5102c3c97 100644 --- a/app/_locales/no/messages.json +++ b/app/_locales/no/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Henvisninger" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Timer for automatisk utlogging (minutter) " }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Innstill hviletiden i minutter før MetaMask automatisk logger ut" }, "average": { @@ -641,10 +641,7 @@ "localhost": { "message": "Lokalvert 8545" }, - "login": { - "message": "Logg inn" - }, - "logout": { + "lock": { "message": "Logg ut " }, "mainnet": { diff --git a/app/_locales/pl/messages.json b/app/_locales/pl/messages.json index b53b4ebb0..6e08f31aa 100644 --- a/app/_locales/pl/messages.json +++ b/app/_locales/pl/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Atrybuty" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Czas automatycznego wylogowania (w minutach)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Ustaw czas bezczynności w minutach, po którym MetaMask wyloguje Cię automatycznie" }, "average": { @@ -648,10 +648,7 @@ "localhost": { "message": "Serwer lokalny 8545" }, - "login": { - "message": "Zaloguj się" - }, - "logout": { + "lock": { "message": "Wyloguj się" }, "mainnet": { diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index 47439021b..189225fc4 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -245,10 +245,10 @@ "loadingTokens": { "message": "A carregar Tokens..." }, - "login": { + "unlock": { "message": "Entrar" }, - "logout": { + "lock": { "message": "Sair" }, "mainnet": { diff --git a/app/_locales/pt_BR/messages.json b/app/_locales/pt_BR/messages.json index 1f32af89c..52a711bd3 100644 --- a/app/_locales/pt_BR/messages.json +++ b/app/_locales/pt_BR/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Atribuições" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Temporizador de Logout Automático (minutos)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Defina o tempo de inatividade em minutos antes de o MetaMask fazer logout automaticamente" }, "average": { @@ -639,10 +639,7 @@ "loadMore": { "message": "Carregar Mais" }, - "login": { - "message": "Entrar" - }, - "logout": { + "lock": { "message": "Sair" }, "mainnet": { diff --git a/app/_locales/ro/messages.json b/app/_locales/ro/messages.json index bad3f6293..aeb986ecb 100644 --- a/app/_locales/ro/messages.json +++ b/app/_locales/ro/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Atribuții" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Temporizator deconectare automată (minute)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Setați perioada de inactivitate în minute înainte ca MetaMask să se deconecteze automat" }, "average": { @@ -638,10 +638,7 @@ "loadMore": { "message": "Încărcați mai multe" }, - "login": { - "message": "Autentificare" - }, - "logout": { + "lock": { "message": "Deconectați-vă" }, "mainnet": { diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index 2f1302d43..9d819c29b 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -281,10 +281,7 @@ "loadingTokens": { "message": "Загрузка токенов..." }, - "login": { - "message": "Вход" - }, - "logout": { + "lock": { "message": "Выход" }, "mainnet": { @@ -593,10 +590,10 @@ "attemptToCancelDescription": { "message": "Отправка этой попытки не гарантирует отмену вашей первоначальной транзакции. Если попытка отмены окажется успешной комиссия за исходную транзакцию будет возвращена." }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Таймер автоматического выхода из кошелька (минуты)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Установите время простоя в минутах, прежде чем MetaMask автоматически заблокирует кошелек" }, "average": { diff --git a/app/_locales/sk/messages.json b/app/_locales/sk/messages.json index 43b235e9a..c1a5ef877 100644 --- a/app/_locales/sk/messages.json +++ b/app/_locales/sk/messages.json @@ -106,10 +106,10 @@ "attributions": { "message": "Zásluhy" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Časovač automatického odhlásenia (minúty)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Nastavte čas nečinnosti v minútach skôr, než sa MetaMask automaticky odhlási" }, "average": { @@ -626,10 +626,7 @@ "loadMore": { "message": "Načítať viac" }, - "login": { - "message": "Přihlásit" - }, - "logout": { + "lock": { "message": "Odhlásit" }, "memorizePhrase": { diff --git a/app/_locales/sl/messages.json b/app/_locales/sl/messages.json index b1e9e4dd8..2dbeb1046 100644 --- a/app/_locales/sl/messages.json +++ b/app/_locales/sl/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Dodelitve" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Časovnik za samodejno odjavo (minute)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Nastavite, po koliko minutah mirovanja naj se MetaMask samodejno odjavi" }, "average": { @@ -636,10 +636,7 @@ "loadMore": { "message": "Naloži več" }, - "login": { - "message": "Prijava" - }, - "logout": { + "lock": { "message": "Odjava" }, "mainnet": { diff --git a/app/_locales/sr/messages.json b/app/_locales/sr/messages.json index 4d72762d0..3b359584c 100644 --- a/app/_locales/sr/messages.json +++ b/app/_locales/sr/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Atribucije" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Tajmer za automatsko odjavljivanje (u minutama)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Podesite vreme mirovanja u minutima pre nego što se MetaMask automatski odjavi. " }, "average": { @@ -645,10 +645,7 @@ "loadMore": { "message": "Učitati više" }, - "login": { - "message": "Ulogujte se" - }, - "logout": { + "lock": { "message": "Odjavi se" }, "mainnet": { diff --git a/app/_locales/sv/messages.json b/app/_locales/sv/messages.json index e0ec851ee..22cd0ffe6 100644 --- a/app/_locales/sv/messages.json +++ b/app/_locales/sv/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Tillskrivningar" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Timer för automatisk utloggning (minuter)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Ställ in efter hur lång tids inaktivitet som MetaMask automatiskt loggar ut" }, "average": { @@ -638,10 +638,7 @@ "loadMore": { "message": "Ladda mer" }, - "login": { - "message": "Logga in" - }, - "logout": { + "lock": { "message": "Logga ut" }, "mainnet": { diff --git a/app/_locales/sw/messages.json b/app/_locales/sw/messages.json index 2ab4f52a5..3326b7c7a 100644 --- a/app/_locales/sw/messages.json +++ b/app/_locales/sw/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Sifa" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Kihesabu Muda wa Kuondoka Kwenye Akaunti Kiotomatiki (dakika)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Weka muda katika dakika kabla MetaMask haijaondoa kwenye akaunti kiotomatiki." }, "average": { @@ -632,10 +632,7 @@ "loadMore": { "message": "Pak zAIDI" }, - "login": { - "message": "Ingia kwenye akanuti" - }, - "logout": { + "lock": { "message": "Toka kwenye akaunti" }, "mainnet": { diff --git a/app/_locales/ta/messages.json b/app/_locales/ta/messages.json index ab4a2d996..75ef08a57 100644 --- a/app/_locales/ta/messages.json +++ b/app/_locales/ta/messages.json @@ -278,10 +278,7 @@ "localhost": { "message": "லோக்கல் ஹோஸ்ட் 8545" }, - "login": { - "message": "உள் நுழை" - }, - "logout": { + "lock": { "message": "வெளியேறு" }, "mainnet": { diff --git a/app/_locales/th/messages.json b/app/_locales/th/messages.json index 01cc020f0..61bc3e5f7 100644 --- a/app/_locales/th/messages.json +++ b/app/_locales/th/messages.json @@ -329,10 +329,7 @@ "loadingTokens": { "message": "กำลังโหลดโทเค็น..." }, - "login": { - "message": "เข้าสู่ระบบ" - }, - "logout": { + "lock": { "message": "ออกจากระบบ" }, "mainnet": { diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index f21f35be8..6aac95387 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -281,10 +281,10 @@ "loadingTokens": { "message": "Jetonlar yükleniyor..." }, - "login": { + "unlock": { "message": "Giriş yap" }, - "logout": { + "lock": { "message": "Çıkış" }, "mainnet": { diff --git a/app/_locales/uk/messages.json b/app/_locales/uk/messages.json index c735a98b0..fa62d58f5 100644 --- a/app/_locales/uk/messages.json +++ b/app/_locales/uk/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "Авторство" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "Таймер автоматичного виходу (хвилин)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "Встановіть час відсутності активності у хвилинах після якого MetaMask буде здійснювати автоматичний вихід" }, "average": { @@ -651,10 +651,7 @@ "localhost": { "message": "Локальний хост 8545" }, - "login": { - "message": "Увійти" - }, - "logout": { + "lock": { "message": "Вийти" }, "mainnet": { diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index cf668f161..a2e9d7c60 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -200,7 +200,7 @@ "loadingTokens": { "message": "Đang tải mã token..." }, - "logout": { + "lock": { "message": "Thoát" }, "mainnet": { diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index 3d2ff6f69..f970b5606 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "来源" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "自动注销计时器(分钟)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "请设置 MetaMask 自动注销前的空闲时间(以分钟为单位)" }, "average": { @@ -639,11 +639,8 @@ "loadMore": { "message": "加载更多" }, - "login": { - "message": "登录" - }, - "logout": { - "message": "登出" + "lock": { + "message": "锁定" }, "mainnet": { "message": "以太坊主网络" diff --git a/app/_locales/zh_TW/messages.json b/app/_locales/zh_TW/messages.json index c44bfaf37..6513a4b0e 100644 --- a/app/_locales/zh_TW/messages.json +++ b/app/_locales/zh_TW/messages.json @@ -109,10 +109,10 @@ "attributions": { "message": "來源" }, - "autoLogoutTimeLimit": { + "autoLockTimeLimit": { "message": "自動登出計時器(分)" }, - "autoLogoutTimeLimitDescription": { + "autoLockTimeLimitDescription": { "message": "設定閒置分鐘上限,時間到時 MetaMask 將自動登出" }, "average": { @@ -645,11 +645,8 @@ "loadMore": { "message": "載入更多" }, - "login": { - "message": "登入" - }, - "logout": { - "message": "登出" + "lock": { + "message": "鎖定" }, "mainnet": { "message": "乙太坊 主網路" @@ -1263,6 +1260,9 @@ "unknownCameraError": { "message": "無法存取攝影鏡頭。請再試一次..." }, + "unlock": { + "message": "解鎖" + }, "unlockMessage": { "message": "去中心化網路世界等待著您" }, diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index 55fbe2e76..f80fb1198 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -17,10 +17,10 @@ class AppStateController { this.timer = null preferencesStore.subscribe(state => { - this._setInactiveTimeout(state.preferences.autoLogoutTimeLimit) + this._setInactiveTimeout(state.preferences.autoLockTimeLimit) }) - this._setInactiveTimeout(preferences.autoLogoutTimeLimit) + this._setInactiveTimeout(preferences.autoLockTimeLimit) } setMkrMigrationReminderTimestamp (timestamp) { diff --git a/app/scripts/migrations/041.js b/app/scripts/migrations/041.js new file mode 100644 index 000000000..b5ffed38e --- /dev/null +++ b/app/scripts/migrations/041.js @@ -0,0 +1,24 @@ +const version = 41 +import clone from 'clone' + +/** + * PreferencesController.autoLogoutTimeLimit -> autoLockTimeLimit + */ +export default { + version, + migrate: async function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + const state = versionedData.data + versionedData.data = transformState(state) + return versionedData + }, +} + +function transformState (state) { + if (state.PreferencesController && state.PreferencesController.preferences) { + state.PreferencesController.preferences.autoLockTimeLimit = state.PreferencesController.preferences.autoLogoutTimeLimit + delete state.PreferencesController.preferences.autoLogoutTimeLimit + } + return state +} diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 959af961a..4a6c56cc7 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -51,6 +51,7 @@ const migrations = [ require('./038').default, require('./039').default, require('./040').default, + require('./041').default, ] export default migrations diff --git a/test/e2e/address-book.spec.js b/test/e2e/address-book.spec.js index 6d41596db..8d0d7ac8c 100644 --- a/test/e2e/address-book.spec.js +++ b/test/e2e/address-book.spec.js @@ -125,9 +125,9 @@ describe('MetaMask', function () { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const logoutButton = await driver.findClickableElement(By.css('.account-menu__logout-button')) - assert.equal(await logoutButton.getText(), 'Log out') - await logoutButton.click() + const lockButton = await driver.findClickableElement(By.css('.account-menu__lock-button')) + assert.equal(await lockButton.getText(), 'Lock') + await lockButton.click() await driver.delay(regularDelayMs) }) diff --git a/test/e2e/from-import-ui.spec.js b/test/e2e/from-import-ui.spec.js index fa8e117a2..9911ec8d1 100644 --- a/test/e2e/from-import-ui.spec.js +++ b/test/e2e/from-import-ui.spec.js @@ -121,14 +121,14 @@ describe('Using MetaMask with an existing account', function () { }) }) - describe('Log out and log back in', () => { + describe('Lock and unlock', () => { it('logs out of the account', async () => { await driver.clickElement(By.css('.account-menu__icon .identicon')) await driver.delay(regularDelayMs) - const logoutButton = await driver.findClickableElement(By.css('.account-menu__logout-button')) - assert.equal(await logoutButton.getText(), 'Log out') - await logoutButton.click() + const lockButton = await driver.findClickableElement(By.css('.account-menu__lock-button')) + assert.equal(await lockButton.getText(), 'Lock') + await lockButton.click() await driver.delay(regularDelayMs) }) diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index b57f9bb61..f0d66746d 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -129,9 +129,9 @@ describe('MetaMask', function () { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const logoutButton = await driver.findClickableElement(By.css('.account-menu__logout-button')) - assert.equal(await logoutButton.getText(), 'Log out') - await logoutButton.click() + const lockButton = await driver.findClickableElement(By.css('.account-menu__lock-button')) + assert.equal(await lockButton.getText(), 'Lock') + await lockButton.click() await driver.delay(regularDelayMs) }) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index 09ce14da9..bc6b94c56 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -131,14 +131,14 @@ describe('MetaMask', function () { }) }) - describe('Log out an log back in', () => { + describe('Lock an unlock', () => { it('logs out of the account', async () => { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const logoutButton = await driver.findClickableElement(By.css('.account-menu__logout-button')) - assert.equal(await logoutButton.getText(), 'Log out') - await logoutButton.click() + const lockButton = await driver.findClickableElement(By.css('.account-menu__lock-button')) + assert.equal(await lockButton.getText(), 'Lock') + await lockButton.click() await driver.delay(regularDelayMs) }) @@ -180,9 +180,9 @@ describe('MetaMask', function () { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) - const logoutButton = await driver.findClickableElement(By.css('.account-menu__logout-button')) - assert.equal(await logoutButton.getText(), 'Log out') - await logoutButton.click() + const lockButton = await driver.findClickableElement(By.css('.account-menu__lock-button')) + assert.equal(await lockButton.getText(), 'Lock') + await lockButton.click() await driver.delay(regularDelayMs) }) diff --git a/ui/app/components/app/account-menu/account-menu.component.js b/ui/app/components/app/account-menu/account-menu.component.js index 17f4614dc..8d6b6417f 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/app/components/app/account-menu/account-menu.component.js @@ -315,13 +315,13 @@ export default class AccountMenu extends Component { { t('myAccounts') } diff --git a/ui/app/components/app/account-menu/index.scss b/ui/app/components/app/account-menu/index.scss index c8385b5e7..f81ce278e 100644 --- a/ui/app/components/app/account-menu/index.scss +++ b/ui/app/components/app/account-menu/index.scss @@ -36,7 +36,7 @@ align-items: center; } - &__logout-button { + &__lock-button { border: 1px solid $dusty-gray; background-color: transparent; color: $white; diff --git a/ui/app/pages/routes/index.js b/ui/app/pages/routes/index.js index 8cb3bdbba..97886b734 100644 --- a/ui/app/pages/routes/index.js +++ b/ui/app/pages/routes/index.js @@ -124,7 +124,7 @@ class Routes extends Component { } renderRoutes () { - const { autoLogoutTimeLimit, setLastActiveTime } = this.props + const { autoLockTimeLimit, setLastActiveTime } = this.props const routes = ( @@ -147,7 +147,7 @@ class Routes extends Component { ) - if (autoLogoutTimeLimit > 0) { + if (autoLockTimeLimit > 0) { return ( {routes} @@ -378,7 +378,7 @@ Routes.propTypes = { setMouseUserState: PropTypes.func, providerId: PropTypes.string, hasPermissionsRequests: PropTypes.bool, - autoLogoutTimeLimit: PropTypes.number, + autoLockTimeLimit: PropTypes.number, addressConnectedToCurrentTab: PropTypes.string, showAccountDetail: PropTypes.func, } @@ -397,7 +397,7 @@ function mapStateToProps (state) { loadingMessage, } = appState - const { autoLogoutTimeLimit = 0 } = preferencesSelector(state) + const { autoLockTimeLimit = 0 } = preferencesSelector(state) return { // state from plugin @@ -416,7 +416,7 @@ function mapStateToProps (state) { currentCurrency: state.metamask.currentCurrency, isMouseUser: state.appState.isMouseUser, providerId: getNetworkIdentifier(state), - autoLogoutTimeLimit, + autoLockTimeLimit, hasPermissionsRequests: hasPermissionRequests(state), addressConnectedToCurrentTab: getAddressConnectedToCurrentTab(state), } diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js index 260b32b69..78b5a36d0 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js +++ b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js @@ -25,8 +25,8 @@ export default class AdvancedTab extends PureComponent { setAdvancedInlineGasFeatureFlag: PropTypes.func, advancedInlineGas: PropTypes.bool, showFiatInTestnets: PropTypes.bool, - autoLogoutTimeLimit: PropTypes.number, - setAutoLogoutTimeLimit: PropTypes.func.isRequired, + autoLockTimeLimit: PropTypes.number, + setAutoLockTimeLimit: PropTypes.func.isRequired, setShowFiatConversionOnTestnetsPreference: PropTypes.func.isRequired, threeBoxSyncingAllowed: PropTypes.bool.isRequired, setThreeBoxSyncingPermission: PropTypes.func.isRequired, @@ -36,8 +36,8 @@ export default class AdvancedTab extends PureComponent { } state = { - autoLogoutTimeLimit: this.props.autoLogoutTimeLimit, - logoutTimeError: '', + autoLockTimeLimit: this.props.autoLockTimeLimit, + lockTimeError: '', ipfsGateway: this.props.ipfsGateway, ipfsGatewayError: '', } @@ -249,38 +249,38 @@ export default class AdvancedTab extends PureComponent { ) } - handleLogoutChange (time) { + handleLockChange (time) { const { t } = this.context - const autoLogoutTimeLimit = Math.max(Number(time), 0) + const autoLockTimeLimit = Math.max(Number(time), 0) this.setState(() => { - let logoutTimeError = '' + let lockTimeError = '' - if (autoLogoutTimeLimit > 10080) { - logoutTimeError = t('logoutTimeTooGreat') + if (autoLockTimeLimit > 10080) { + lockTimeError = t('lockTimeTooGreat') } return { - autoLogoutTimeLimit, - logoutTimeError, + autoLockTimeLimit, + lockTimeError, } }) } - renderAutoLogoutTimeLimit () { + renderAutoLockTimeLimit () { const { t } = this.context - const { logoutTimeError } = this.state + const { lockTimeError } = this.state const { - autoLogoutTimeLimit, - setAutoLogoutTimeLimit, + autoLockTimeLimit, + setAutoLockTimeLimit, } = this.props return ( -
    +
    - { t('autoLogoutTimeLimit') } + { t('autoLockTimeLimit') }
    - { t('autoLogoutTimeLimitDescription') } + { t('autoLockTimeLimitDescription') }
    @@ -289,10 +289,10 @@ export default class AdvancedTab extends PureComponent { type="number" id="autoTimeout" placeholder="5" - value={this.state.autoLogoutTimeLimit} - defaultValue={autoLogoutTimeLimit} - onChange={e => this.handleLogoutChange(e.target.value)} - error={logoutTimeError} + value={this.state.autoLockTimeLimit} + defaultValue={autoLockTimeLimit} + onChange={e => this.handleLockChange(e.target.value)} + error={lockTimeError} fullWidth margin="dense" min={0} @@ -300,9 +300,9 @@ export default class AdvancedTab extends PureComponent {
    diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.container.js b/ui/app/pages/settings/advanced-tab/advanced-tab.container.js index 90a4861c7..0e93a68fe 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.container.js +++ b/ui/app/pages/settings/advanced-tab/advanced-tab.container.js @@ -7,7 +7,7 @@ import { setFeatureFlag, showModal, setShowFiatConversionOnTestnetsPreference, - setAutoLogoutTimeLimit, + setAutoLockTimeLimit, setThreeBoxSyncingPermission, turnThreeBoxSyncingOnAndInitialize, setUseNonceField, @@ -27,14 +27,14 @@ export const mapStateToProps = state => { useNonceField, ipfsGateway, } = metamask - const { showFiatInTestnets, autoLogoutTimeLimit } = preferencesSelector(state) + const { showFiatInTestnets, autoLockTimeLimit } = preferencesSelector(state) return { warning, sendHexData, advancedInlineGas, showFiatInTestnets, - autoLogoutTimeLimit, + autoLockTimeLimit, threeBoxSyncingAllowed, threeBoxDisabled, useNonceField, @@ -52,8 +52,8 @@ export const mapDispatchToProps = dispatch => { setShowFiatConversionOnTestnetsPreference: value => { return dispatch(setShowFiatConversionOnTestnetsPreference(value)) }, - setAutoLogoutTimeLimit: value => { - return dispatch(setAutoLogoutTimeLimit(value)) + setAutoLockTimeLimit: value => { + return dispatch(setAutoLockTimeLimit(value)) }, setThreeBoxSyncingPermission: newThreeBoxSyncingState => { if (newThreeBoxSyncingState) { diff --git a/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js b/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js index 408657523..70e8f4ca6 100644 --- a/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js +++ b/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js @@ -10,7 +10,7 @@ describe('AdvancedTab Component', () => { const root = shallow( {}} + setAutoLockTimeLimit={() => {}} setIpfsGateway={() => {}} setShowFiatConversionOnTestnetsPreference={() => {}} setThreeBoxSyncingPermission={() => {}} @@ -27,12 +27,12 @@ describe('AdvancedTab Component', () => { assert.equal(root.find('.settings-page__content-row').length, 10) }) - it('should update autoLogoutTimeLimit', () => { - const setAutoLogoutTimeLimitSpy = sinon.spy() + it('should update autoLockTimeLimit', () => { + const setAutoLockTimeLimitSpy = sinon.spy() const root = shallow( {}} setShowFiatConversionOnTestnetsPreference={() => {}} setThreeBoxSyncingPermission={() => {}} @@ -50,9 +50,9 @@ describe('AdvancedTab Component', () => { const textField = autoTimeout.find(TextField) textField.props().onChange({ target: { value: 1440 } }) - assert.equal(root.state().autoLogoutTimeLimit, 1440) + assert.equal(root.state().autoLockTimeLimit, 1440) autoTimeout.find('.settings-tab__rpc-save-button').simulate('click') - assert.equal(setAutoLogoutTimeLimitSpy.args[0][0], 1440) + assert.equal(setAutoLockTimeLimitSpy.args[0][0], 1440) }) }) diff --git a/ui/app/pages/unlock-page/unlock-page.component.js b/ui/app/pages/unlock-page/unlock-page.component.js index ae10efbfd..346257a3a 100644 --- a/ui/app/pages/unlock-page/unlock-page.component.js +++ b/ui/app/pages/unlock-page/unlock-page.component.js @@ -125,7 +125,7 @@ export default class UnlockPage extends Component { onClick={this.handleSubmit} disableRipple > - { this.context.t('login') } + { this.context.t('unlock') } ) } diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 7b1f78b29..6123bfecb 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -1937,8 +1937,8 @@ export function setShowFiatConversionOnTestnetsPreference (value) { return setPreference('showFiatInTestnets', value) } -export function setAutoLogoutTimeLimit (value) { - return setPreference('autoLogoutTimeLimit', value) +export function setAutoLockTimeLimit (value) { + return setPreference('autoLockTimeLimit', value) } export function setCompletedOnboarding () { From d8c685ba2e590bc00478387bba0e42b9237d61dd Mon Sep 17 00:00:00 2001 From: ryanml Date: Tue, 21 Jan 2020 17:22:55 -0800 Subject: [PATCH 165/689] Add mechanism to randomize seed phrase filename (#7863) The filename is seeded by a simple use of Math.random() pulling from an alphanumeric character bank, as opposed to a more cryptographically random solution. This provides a simple layer of difficulty for bad actors to seek out the recovery phrase file. --- app/_locales/am/messages.json | 3 --- app/_locales/ar/messages.json | 3 --- app/_locales/bg/messages.json | 3 --- app/_locales/bn/messages.json | 3 --- app/_locales/ca/messages.json | 3 --- app/_locales/da/messages.json | 3 --- app/_locales/de/messages.json | 3 --- app/_locales/el/messages.json | 3 --- app/_locales/en/messages.json | 3 --- app/_locales/es/messages.json | 3 --- app/_locales/es_419/messages.json | 3 --- app/_locales/et/messages.json | 3 --- app/_locales/fa/messages.json | 3 --- app/_locales/fi/messages.json | 3 --- app/_locales/fil/messages.json | 3 --- app/_locales/fr/messages.json | 3 --- app/_locales/he/messages.json | 3 --- app/_locales/hi/messages.json | 3 --- app/_locales/hr/messages.json | 3 --- app/_locales/ht/messages.json | 3 --- app/_locales/hu/messages.json | 3 --- app/_locales/id/messages.json | 3 --- app/_locales/it/messages.json | 3 --- app/_locales/kn/messages.json | 3 --- app/_locales/ko/messages.json | 3 --- app/_locales/lt/messages.json | 3 --- app/_locales/lv/messages.json | 3 --- app/_locales/ms/messages.json | 3 --- app/_locales/no/messages.json | 3 --- app/_locales/pl/messages.json | 3 --- app/_locales/pt_BR/messages.json | 3 --- app/_locales/ro/messages.json | 3 --- app/_locales/ru/messages.json | 3 --- app/_locales/sk/messages.json | 3 --- app/_locales/sl/messages.json | 3 --- app/_locales/sr/messages.json | 3 --- app/_locales/sv/messages.json | 3 --- app/_locales/sw/messages.json | 3 --- app/_locales/uk/messages.json | 3 --- app/_locales/zh_CN/messages.json | 3 --- .../export-text-container.component.js | 5 ++--- ui/app/helpers/utils/util.js | 15 +++++++++++++++ ui/app/helpers/utils/util.test.js | 15 +++++++++++++++ .../confirm-seed-phrase.component.js | 2 +- .../reveal-seed-phrase.component.js | 2 +- ui/app/pages/keychains/reveal-seed.js | 2 +- 46 files changed, 35 insertions(+), 126 deletions(-) diff --git a/app/_locales/am/messages.json b/app/_locales/am/messages.json index 5c1a04718..8de236b7c 100644 --- a/app/_locales/am/messages.json +++ b/app/_locales/am/messages.json @@ -669,9 +669,6 @@ "metamaskDescription": { "message": "ከ Ethereum እና ያልተማከለ መረብ ጋር እርስዎን ማገናኘት።" }, - "metamaskSeedWords": { - "message": "MetaMask የዘር ቃላት" - }, "metamaskVersion": { "message": "የ MetaMask ስሪት" }, diff --git a/app/_locales/ar/messages.json b/app/_locales/ar/messages.json index 0ba042127..fa6eb638a 100644 --- a/app/_locales/ar/messages.json +++ b/app/_locales/ar/messages.json @@ -665,9 +665,6 @@ "metamaskDescription": { "message": "إيصالك بالإيثيريوم وبالشبكة اللامركزية." }, - "metamaskSeedWords": { - "message": "كلمات MetaMask البذرية" - }, "metamaskVersion": { "message": "إصدار MetaMask " }, diff --git a/app/_locales/bg/messages.json b/app/_locales/bg/messages.json index 872111178..9b58cce3d 100644 --- a/app/_locales/bg/messages.json +++ b/app/_locales/bg/messages.json @@ -668,9 +668,6 @@ "metamaskDescription": { "message": "Свързва ви с Ethereum и децентрализираната мрежа." }, - "metamaskSeedWords": { - "message": "Думи зародиш на MetaMask" - }, "metamaskVersion": { "message": "Версия на MetaMask" }, diff --git a/app/_locales/bn/messages.json b/app/_locales/bn/messages.json index 869281beb..ebb3a7943 100644 --- a/app/_locales/bn/messages.json +++ b/app/_locales/bn/messages.json @@ -672,9 +672,6 @@ "metamaskDescription": { "message": "আপনার Ethereum এবং ছড়িয়ে ছিটিয়ে থাকা ওয়েবের সাথে সংযোগ করছে। " }, - "metamaskSeedWords": { - "message": "MetaMask সীড শব্দসমূহ" - }, "metamaskVersion": { "message": "MetaMask সংস্করণ" }, diff --git a/app/_locales/ca/messages.json b/app/_locales/ca/messages.json index 201d321e0..38a1b7eb1 100644 --- a/app/_locales/ca/messages.json +++ b/app/_locales/ca/messages.json @@ -656,9 +656,6 @@ "metamaskDescription": { "message": "Conectant-te a Ethereum i la web descentralitzada." }, - "metamaskSeedWords": { - "message": "Frase de recuperació de MetaMask" - }, "metamaskVersion": { "message": "Versió MetaMask" }, diff --git a/app/_locales/da/messages.json b/app/_locales/da/messages.json index 88b457aec..9adeedbf6 100644 --- a/app/_locales/da/messages.json +++ b/app/_locales/da/messages.json @@ -656,9 +656,6 @@ "metamaskDescription": { "message": "Som forbinder dig til Ethereum og de decentraliserede internet." }, - "metamaskSeedWords": { - "message": "MetaMask Seedord" - }, "missingYourTokens": { "message": "Kan du ikke se dine tokens?" }, diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index 1c2a4be35..b618df138 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -648,9 +648,6 @@ "metamaskDescription": { "message": "MetaMask ist ein sicherer Identitätssafe für Ethereum." }, - "metamaskSeedWords": { - "message": "MetaMask-Seed-Wörter" - }, "metamaskVersion": { "message": "MetaMask-Version" }, diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index 84efaf273..cb9299c0a 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -669,9 +669,6 @@ "metamaskDescription": { "message": "Σύνδεση με το Ethereum και τον Αποκεντρωμένο Ιστό." }, - "metamaskSeedWords": { - "message": "Λέξεις Φύτρου MetaMask" - }, "metamaskVersion": { "message": "Έκδοση MetaMask " }, diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 665affeee..f904ffa50 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -812,9 +812,6 @@ "metamaskDescription": { "message": "Connecting you to Ethereum and the Decentralized Web." }, - "metamaskSeedWords": { - "message": "MetaMask Seed Words" - }, "metamaskVersion": { "message": "MetaMask Version" }, diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index 32c6bb15f..4fed0b1fb 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -548,9 +548,6 @@ "metamaskDescription": { "message": "MetaMask es una identidad segura en Ethereum" }, - "metamaskSeedWords": { - "message": "Palabras semilla de MetaMask" - }, "metamaskVersion": { "message": "Versión de MetaMask" }, diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index e2d386e0a..ac8d8569f 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -657,9 +657,6 @@ "metamaskDescription": { "message": "Te estamos conectando a Ethereum y a la web descentralizada." }, - "metamaskSeedWords": { - "message": "Palabras de inicialización de MetaMask" - }, "metamaskVersion": { "message": "Versión de MetaMask" }, diff --git a/app/_locales/et/messages.json b/app/_locales/et/messages.json index 3946d4fad..191563c2f 100644 --- a/app/_locales/et/messages.json +++ b/app/_locales/et/messages.json @@ -662,9 +662,6 @@ "metamaskDescription": { "message": "Teid ühendatakse Ethereumi ja detsentraliseeritud võrguga." }, - "metamaskSeedWords": { - "message": "MetaMaski seemnesõnad" - }, "metamaskVersion": { "message": "MetaMaski versioon" }, diff --git a/app/_locales/fa/messages.json b/app/_locales/fa/messages.json index 94c041ff9..f95adee30 100644 --- a/app/_locales/fa/messages.json +++ b/app/_locales/fa/messages.json @@ -672,9 +672,6 @@ "metamaskDescription": { "message": "در حال اتصال شما با ایترم و وب غیر متمرکز شده." }, - "metamaskSeedWords": { - "message": "کلمات بازیاب MetaMask" - }, "metamaskVersion": { "message": "نسخه MetaMask" }, diff --git a/app/_locales/fi/messages.json b/app/_locales/fi/messages.json index 61df7c813..31f1ff147 100644 --- a/app/_locales/fi/messages.json +++ b/app/_locales/fi/messages.json @@ -669,9 +669,6 @@ "metamaskDescription": { "message": "Sinua yhdistetään Ethereumiin ja hajautettuun verkkoon." }, - "metamaskSeedWords": { - "message": "MetaMaskin siemensanat" - }, "metamaskVersion": { "message": "MetaMask-versio" }, diff --git a/app/_locales/fil/messages.json b/app/_locales/fil/messages.json index ff44ba30a..9311cdbdb 100644 --- a/app/_locales/fil/messages.json +++ b/app/_locales/fil/messages.json @@ -607,9 +607,6 @@ "metamaskDescription": { "message": "Kinokonekta ka sa Ethereum at sa Decentralized Web." }, - "metamaskSeedWords": { - "message": "Seed Words ng MetaMask" - }, "metamaskVersion": { "message": "Bersyon ng MetaMask" }, diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index 5eb4dc066..937d0e520 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -651,9 +651,6 @@ "metamaskDescription": { "message": "MetaMask est un coffre sécurisé pour votre identité sur Ethereum." }, - "metamaskSeedWords": { - "message": "Mots Seed pour MetaMask" - }, "metamaskVersion": { "message": "Version de MetaMask" }, diff --git a/app/_locales/he/messages.json b/app/_locales/he/messages.json index c7e14dc77..bc906bafd 100644 --- a/app/_locales/he/messages.json +++ b/app/_locales/he/messages.json @@ -669,9 +669,6 @@ "metamaskDescription": { "message": "מחבר אותך לאתריום ולרשת המבוזרת." }, - "metamaskSeedWords": { - "message": "מילות גרעין (Seed) של MetaMask " - }, "metamaskVersion": { "message": "גרסת MetaMask" }, diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index 9a2f69614..d3a955013 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -669,9 +669,6 @@ "metamaskDescription": { "message": "आपको Ethereum और विकेंद्रीकृत वेब से कनेक्ट कर रहे हैं।" }, - "metamaskSeedWords": { - "message": "मेटामास्क बीज शब्द" - }, "metamaskVersion": { "message": "MetaMask का संस्करण" }, diff --git a/app/_locales/hr/messages.json b/app/_locales/hr/messages.json index e3ce9f2b7..aa22658e4 100644 --- a/app/_locales/hr/messages.json +++ b/app/_locales/hr/messages.json @@ -665,9 +665,6 @@ "metamaskDescription": { "message": "Povezujete se na Ethereum i decentralizirani internet." }, - "metamaskSeedWords": { - "message": "Početne riječi za MetaMask" - }, "metamaskVersion": { "message": "Inačica usluge MetaMask" }, diff --git a/app/_locales/ht/messages.json b/app/_locales/ht/messages.json index 6ca9b5c44..8ae90a17d 100644 --- a/app/_locales/ht/messages.json +++ b/app/_locales/ht/messages.json @@ -401,9 +401,6 @@ "metamaskDescription": { "message": "MetaMask sekirize idantite pou Ethereum." }, - "metamaskSeedWords": { - "message": "MetaMask Seed Mo" - }, "metamaskVersion": { "message": "MetaMask Vèsyon" }, diff --git a/app/_locales/hu/messages.json b/app/_locales/hu/messages.json index 1794413e1..8d0c94228 100644 --- a/app/_locales/hu/messages.json +++ b/app/_locales/hu/messages.json @@ -665,9 +665,6 @@ "metamaskDescription": { "message": "Csatlakozás az Ethereumhoz és a decentralizált hálózathoz." }, - "metamaskSeedWords": { - "message": "MetaMask seed szavak" - }, "metamaskVersion": { "message": "MetaMask verzió" }, diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index 5ca31e394..d7281ab62 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -650,9 +650,6 @@ "metamaskDescription": { "message": "Menghubungkan Anda ke Ethereum dan Web Terdesentralisasi." }, - "metamaskSeedWords": { - "message": "Kata Benih MetaMask" - }, "metamaskVersion": { "message": "Versi MetaMask" }, diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index 3b7a4870c..e03c58d05 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -642,9 +642,6 @@ "metamaskDescription": { "message": "MetaMask è una cassaforte sicura per identità su Ethereum." }, - "metamaskSeedWords": { - "message": "Parole Seed di MetaMask" - }, "metamaskVersion": { "message": "versione di MetaMask" }, diff --git a/app/_locales/kn/messages.json b/app/_locales/kn/messages.json index 61d7fe74b..81c134c0e 100644 --- a/app/_locales/kn/messages.json +++ b/app/_locales/kn/messages.json @@ -672,9 +672,6 @@ "metamaskDescription": { "message": "ನಿಮ್ಮನ್ನು ಎಥೆರಿಯಮ್ ಮತ್ತು ವಿಕೇಂದ್ರೀಕೃತ ವೆಬ್‌ಗೆ ಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ." }, - "metamaskSeedWords": { - "message": "MetaMask ಸೀಡ್ ಪದಗಳು" - }, "metamaskVersion": { "message": "MetaMask ಆವೃತ್ತಿ" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index 346b7f4e3..f2166ab36 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -666,9 +666,6 @@ "metamaskDescription": { "message": "메타마스크는 이더리움을 위한 안전한 저장소입니다." }, - "metamaskSeedWords": { - "message": "메타마스크 시드 단어" - }, "metamaskVersion": { "message": "메타마스크 버전" }, diff --git a/app/_locales/lt/messages.json b/app/_locales/lt/messages.json index a89974bcc..d19b40b95 100644 --- a/app/_locales/lt/messages.json +++ b/app/_locales/lt/messages.json @@ -672,9 +672,6 @@ "metamaskDescription": { "message": "Prijungiame jus prie „Ethereum“ ir decentralizuotojo žiniatinklio." }, - "metamaskSeedWords": { - "message": "„MetaMask“ atkūrimo žodžiai" - }, "metamaskVersion": { "message": "„MetaMask“ versija" }, diff --git a/app/_locales/lv/messages.json b/app/_locales/lv/messages.json index 98a61ee46..71d06529b 100644 --- a/app/_locales/lv/messages.json +++ b/app/_locales/lv/messages.json @@ -668,9 +668,6 @@ "metamaskDescription": { "message": "Veido savienojumu ar Ethereum un decentralizēto tīmekli." }, - "metamaskSeedWords": { - "message": "MetaMask atkopšanas vārdi" - }, "metamaskVersion": { "message": "MetaMask versija" }, diff --git a/app/_locales/ms/messages.json b/app/_locales/ms/messages.json index aaf4cca59..f16184011 100644 --- a/app/_locales/ms/messages.json +++ b/app/_locales/ms/messages.json @@ -643,9 +643,6 @@ "metamaskDescription": { "message": "Menyambungkan anda kepada Ethereum dan Web Ternyahpusat." }, - "metamaskSeedWords": { - "message": "Perkataan Benih MetaMask" - }, "metamaskVersion": { "message": "Versi MetaMask" }, diff --git a/app/_locales/no/messages.json b/app/_locales/no/messages.json index 5102c3c97..84a4c2f18 100644 --- a/app/_locales/no/messages.json +++ b/app/_locales/no/messages.json @@ -662,9 +662,6 @@ "metamaskDescription": { "message": "Kobler deg til Ethereum og det desentraliserte nettet." }, - "metamaskSeedWords": { - "message": "Mnemoniske gjenopprettingsfraser for MetaMask " - }, "metamaskVersion": { "message": "MetaMask-versjon " }, diff --git a/app/_locales/pl/messages.json b/app/_locales/pl/messages.json index 6e08f31aa..9c037eddb 100644 --- a/app/_locales/pl/messages.json +++ b/app/_locales/pl/messages.json @@ -663,9 +663,6 @@ "metamaskDescription": { "message": "MetaMask to bezpieczny portfel dla Ethereum." }, - "metamaskSeedWords": { - "message": "Słowa Seed MetaMask" - }, "metamaskVersion": { "message": "Wersja MetaMask" }, diff --git a/app/_locales/pt_BR/messages.json b/app/_locales/pt_BR/messages.json index 52a711bd3..367d52564 100644 --- a/app/_locales/pt_BR/messages.json +++ b/app/_locales/pt_BR/messages.json @@ -657,9 +657,6 @@ "metamaskDescription": { "message": "Conectando você ao Ethereum e à Web Descentralizada." }, - "metamaskSeedWords": { - "message": "Palavras-semente do MetaMask" - }, "metamaskVersion": { "message": "Versão do MetaMask" }, diff --git a/app/_locales/ro/messages.json b/app/_locales/ro/messages.json index aeb986ecb..308ad5c74 100644 --- a/app/_locales/ro/messages.json +++ b/app/_locales/ro/messages.json @@ -659,9 +659,6 @@ "metamaskDescription": { "message": "Vă conectăm la Ethereum și la Internetul descentralizat." }, - "metamaskSeedWords": { - "message": "Cuvinte Seed MetaMask" - }, "metamaskVersion": { "message": "Versiune MetaMask" }, diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index 9d819c29b..addc3178e 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -896,9 +896,6 @@ "menu": { "message": "Меню" }, - "metamaskSeedWords": { - "message": "MetaMask ключевая фраза (сид)" - }, "metamaskVersion": { "message": "Версия MetaMask" }, diff --git a/app/_locales/sk/messages.json b/app/_locales/sk/messages.json index c1a5ef877..0460edb0b 100644 --- a/app/_locales/sk/messages.json +++ b/app/_locales/sk/messages.json @@ -638,9 +638,6 @@ "metamaskDescription": { "message": "MetaMask je bezpečný osobní trezor pro Ethereum." }, - "metamaskSeedWords": { - "message": "Seed slová MetaMask" - }, "metamaskVersion": { "message": "Verzia MetaMask" }, diff --git a/app/_locales/sl/messages.json b/app/_locales/sl/messages.json index 2dbeb1046..ed1c3f71c 100644 --- a/app/_locales/sl/messages.json +++ b/app/_locales/sl/messages.json @@ -657,9 +657,6 @@ "metamaskDescription": { "message": "MetaMask je varen identitetni sklad za Ethereum." }, - "metamaskSeedWords": { - "message": "Seed Words" - }, "metamaskVersion": { "message": "Različica" }, diff --git a/app/_locales/sr/messages.json b/app/_locales/sr/messages.json index 3b359584c..afc28ec93 100644 --- a/app/_locales/sr/messages.json +++ b/app/_locales/sr/messages.json @@ -663,9 +663,6 @@ "metamaskDescription": { "message": "Povezivanje na Ethereum i decentralizovani veb." }, - "metamaskSeedWords": { - "message": "MetaMask reči početne vrednosti" - }, "metamaskVersion": { "message": "MetaMask verzija" }, diff --git a/app/_locales/sv/messages.json b/app/_locales/sv/messages.json index 22cd0ffe6..098170886 100644 --- a/app/_locales/sv/messages.json +++ b/app/_locales/sv/messages.json @@ -656,9 +656,6 @@ "metamaskDescription": { "message": "Ansluter dig mot Ethereum och den decentraliserade webben." }, - "metamaskSeedWords": { - "message": "MetaMask" - }, "metamaskVersion": { "message": "MetaMask-version" }, diff --git a/app/_locales/sw/messages.json b/app/_locales/sw/messages.json index 3326b7c7a..38cf9883f 100644 --- a/app/_locales/sw/messages.json +++ b/app/_locales/sw/messages.json @@ -650,9 +650,6 @@ "metamaskDescription": { "message": "Kukuunganisha kwenye Ethereum na Wavutiu Uliotawanywa." }, - "metamaskSeedWords": { - "message": "Maeno ya Kianzio ya MetaMask" - }, "metamaskVersion": { "message": "Toleo la MetaMask" }, diff --git a/app/_locales/uk/messages.json b/app/_locales/uk/messages.json index fa62d58f5..1e9218df9 100644 --- a/app/_locales/uk/messages.json +++ b/app/_locales/uk/messages.json @@ -672,9 +672,6 @@ "metamaskDescription": { "message": "Під'єднуємо вас до Ethereum та децентралізованої мережі." }, - "metamaskSeedWords": { - "message": "Початкові слова MetaMask" - }, "metamaskVersion": { "message": "Версія MetaMask" }, diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index f970b5606..b6cc66806 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -660,9 +660,6 @@ "metamaskDescription": { "message": "MetaMask is a secure identity vault for Ethereum." }, - "metamaskSeedWords": { - "message": "MetaMask 助记词" - }, "metamaskVersion": { "message": "MetaMask 版本" }, diff --git a/ui/app/components/ui/export-text-container/export-text-container.component.js b/ui/app/components/ui/export-text-container/export-text-container.component.js index ee809a553..61d15a99d 100644 --- a/ui/app/components/ui/export-text-container/export-text-container.component.js +++ b/ui/app/components/ui/export-text-container/export-text-container.component.js @@ -5,7 +5,7 @@ import { exportAsFile } from '../../../helpers/utils/util' class ExportTextContainer extends Component { render () { - const { text = '', filename = '' } = this.props + const { text = '' } = this.props const { t } = this.context return ( @@ -27,7 +27,7 @@ class ExportTextContainer extends Component {
    exportAsFile(filename, text)} + onClick={() => exportAsFile('', text)} >
    @@ -42,7 +42,6 @@ class ExportTextContainer extends Component { ExportTextContainer.propTypes = { text: PropTypes.string, - filename: PropTypes.string, } ExportTextContainer.contextTypes = { diff --git a/ui/app/helpers/utils/util.js b/ui/app/helpers/utils/util.js index c9ede21d8..04e5072d5 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/app/helpers/utils/util.js @@ -213,7 +213,22 @@ export function getContractAtAddress (tokenAddress) { return global.eth.contract(abi).at(tokenAddress) } +export function getRandomFileName () { + let fileName = '' + const charBank = [ + ...'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', + ] + const fileNameLength = Math.floor((Math.random() * 7) + 6) + + for (let i = 0; i < fileNameLength; i++) { + fileName += charBank[Math.floor(Math.random() * charBank.length)] + } + + return fileName +} + export function exportAsFile (filename, data, type = 'text/csv') { + filename = filename || getRandomFileName() // source: https://stackoverflow.com/a/33542499 by Ludovic Feltz const blob = new Blob([data], { type }) if (window.navigator.msSaveOrOpenBlob) { diff --git a/ui/app/helpers/utils/util.test.js b/ui/app/helpers/utils/util.test.js index 6e623ae3a..51ec92ee3 100644 --- a/ui/app/helpers/utils/util.test.js +++ b/ui/app/helpers/utils/util.test.js @@ -254,5 +254,20 @@ describe('util', function () { assert(result) }) }) + + describe('#getRandomFileName', function () { + it('should only return a string containing alphanumeric characters', function () { + const result = util.getRandomFileName() + assert(result.match(/^[a-zA-Z0-9]*$/g)) + }) + + // 50 samples + it('should return a string that is between 6 and 12 characters in length', function () { + for (let i = 0; i < 50; i++) { + const result = util.getRandomFileName() + assert(result.length >= 6 && result.length <= 12) + } + }) + }) }) }) diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js index 8f51e89a3..6642e1e7d 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js @@ -67,7 +67,7 @@ export default class ConfirmSeedPhrase extends PureComponent { } handleExport = () => { - exportAsFile('MetaMask Secret Backup Phrase', this.props.seedPhrase, 'text/plain') + exportAsFile('', this.props.seedPhrase, 'text/plain') } handleSubmit = async () => { diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js index 922685059..afcd771c4 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js @@ -30,7 +30,7 @@ export default class RevealSeedPhrase extends PureComponent { } handleExport = () => { - exportAsFile('MetaMask Secret Backup Phrase', this.props.seedPhrase, 'text/plain') + exportAsFile('', this.props.seedPhrase, 'text/plain') } handleNext = () => { diff --git a/ui/app/pages/keychains/reveal-seed.js b/ui/app/pages/keychains/reveal-seed.js index b8afd1bcd..fa527a363 100644 --- a/ui/app/pages/keychains/reveal-seed.js +++ b/ui/app/pages/keychains/reveal-seed.js @@ -88,7 +88,7 @@ class RevealSeedPage extends Component { return (
    - +
    ) } From ecd4b8221c7a0bbed40137648932eb504ae0a3af Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 22 Jan 2020 11:07:19 -0330 Subject: [PATCH 166/689] Use shared MetaMask ESLint config (#7882) --- .eslintignore | 2 + .eslintrc | 220 -------------------------------------------------- .eslintrc.js | 95 ++++++++++++++++++++++ package.json | 1 + yarn.lock | 5 ++ 5 files changed, 103 insertions(+), 220 deletions(-) delete mode 100644 .eslintrc create mode 100644 .eslintrc.js diff --git a/.eslintignore b/.eslintignore index 8fb306d16..d791f6a12 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,5 @@ +!.eslintrc.js + node_modules/** dist/** builds/** diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 354a77663..000000000 --- a/.eslintrc +++ /dev/null @@ -1,220 +0,0 @@ -{ - "parser": "babel-eslint", - "parserOptions": { - "sourceType": "module", - "ecmaVersion": 2017, - "ecmaFeatures": { - "experimentalObjectRestSpread": true, - "impliedStrict": true, - "modules": true, - "blockBindings": true, - "arrowFunctions": true, - "objectLiteralShorthandMethods": true, - "objectLiteralShorthandProperties": true, - "templateStrings": true, - "classes": true, - "jsx": true - } - }, - - "extends": ["plugin:react/recommended"], - - "env": { - "es6": true, - "node": true, - "browser": true, - "mocha" : true - }, - - "plugins": [ - "babel", - "mocha", - "chai", - "react", - "json", - "import" - ], - - "globals": { - "document": false, - "navigator": false, - "web3": true, - "window": false, - "$": false, - "QUnit": false - }, - - "rules": { - "default-case": 2, - "import/default": 2, - "import/export": 2, - "import/named": 2, - "import/namespace": 2, - "import/newline-after-import": 2, - "import/no-absolute-path": 2, - "import/no-amd": 2, - "import/no-anonymous-default-export": [2, { "allowObject": true }], - "import/no-duplicates": 2, - "import/no-dynamic-require": 2, - "import/no-mutable-exports": 2, - "import/no-named-as-default": 2, - "import/no-named-as-default-member": 2, - "import/no-named-default": 2, - "import/no-self-import": 2, - "import/no-unresolved": [2, { "commonjs": true }], - "import/no-unused-modules": 2, - "import/no-useless-path-segments": [2, { "commonjs": true }], - "import/no-webpack-loader-syntax": 2, - "no-restricted-globals": ["error", "event"], - "accessor-pairs": 2, - "arrow-spacing": [2, { "before": true, "after": true }], - "block-spacing": [2, "always"], - "brace-style": 2, - "camelcase": [2, { "properties": "never", "allow": ["^UNSAFE_"] }], - "comma-dangle": [2, "always-multiline"], - "comma-spacing": [2, { "before": false, "after": true }], - "comma-style": [2, "last"], - "constructor-super": 2, - "curly": 2, - "dot-location": [2, "property"], - "eol-last": 2, - "eqeqeq": [2, "allow-null"], - "generator-star-spacing": [2, { "before": true, "after": true }], - "handle-callback-err": [2, "^(err|error)$" ], - "indent": [2, 2,{ "SwitchCase": 1 }], - "jsx-quotes": [2, "prefer-double"], - "key-spacing": 2, - "keyword-spacing": [2, { "before": true, "after": true }], - "new-cap": [2, { "newIsCap": true, "capIsNew": false }], - "new-parens": 2, - "no-array-constructor": 2, - "no-async-promise-executor": "error", - "no-caller": 2, - "no-class-assign": 2, - "no-cond-assign": 2, - "no-confusing-arrow": 2, - "no-const-assign": 2, - "no-control-regex": 2, - "no-debugger": 2, - "no-delete-var": 2, - "no-dupe-args": 2, - "no-dupe-class-members": 2, - "no-dupe-keys": 2, - "no-duplicate-case": 2, - "no-duplicate-imports": 2, - "no-empty-character-class": 2, - "no-empty-pattern": 2, - "no-eval": 2, - "no-ex-assign": 2, - "no-extend-native": 2, - "no-extra-bind": 2, - "no-extra-boolean-cast": 2, - "no-extra-parens": [2, "functions"], - "no-fallthrough": 2, - "no-floating-decimal": 2, - "no-func-assign": 2, - "no-implied-eval": 2, - "no-inner-declarations": [2, "functions"], - "no-invalid-regexp": 2, - "no-irregular-whitespace": 2, - "no-iterator": 2, - "no-label-var": 2, - "no-labels": [2, { "allowLoop": false, "allowSwitch": false }], - "no-lone-blocks": 2, - "no-mixed-spaces-and-tabs": 2, - "no-multi-spaces": 2, - "no-multi-str": 2, - "no-multiple-empty-lines": [2, { "max": 2 }], - "no-native-reassign": 2, - "no-negated-in-lhs": 2, - "no-new": 2, - "no-new-func": 2, - "no-new-object": 2, - "no-new-require": 2, - "no-new-symbol": 2, - "no-new-wrappers": 2, - "no-obj-calls": 2, - "no-octal": 2, - "no-octal-escape": 2, - "no-path-concat": 2, - "no-proto": 2, - "no-redeclare": 2, - "no-regex-spaces": 2, - "no-return-assign": [2, "except-parens"], - "no-self-assign": 2, - "no-self-compare": 2, - "no-sequences": 2, - "no-shadow-restricted-names": 2, - "no-spaced-func": 2, - "no-sparse-arrays": 2, - "no-this-before-super": 2, - "no-throw-literal": 2, - "no-trailing-spaces": 2, - "no-undef": 2, - "no-undef-init": 2, - "no-unexpected-multiline": 2, - "no-unmodified-loop-condition": 2, - "no-unneeded-ternary": [2, { "defaultAssignment": false }], - "no-unreachable": 2, - "no-unsafe-finally": 2, - "no-unused-expressions": ["error", { "allowShortCircuit" : true, "allowTernary": true }], - "no-unused-vars": [2, { "vars": "all", "args": "all", "argsIgnorePattern": "[_]+" }], - "no-use-before-define": [2, { "functions": false }], - "no-useless-call": 2, - "no-useless-computed-key": 2, - "no-useless-constructor": 2, - "no-useless-escape": 2, - "no-var": 2, - "no-whitespace-before-property": 2, - "no-with": 2, - "object-curly-spacing": [2, "always"], - "one-var": [2, { "initialized": "never" }], - "operator-linebreak": [2, "after", { "overrides": { "?": "ignore", ":": "ignore" } }], - "padded-blocks": "off", - "quotes": [2, "single", {"avoidEscape": true, "allowTemplateLiterals": true}], - "react/no-unused-prop-types": "error", - "react/no-unused-state": 2, - "react/jsx-boolean-value": 2, - "react/jsx-curly-brace-presence": [2, { "props": "never", "children": "never" }], - "react/jsx-equals-spacing": 2, - "react/no-deprecated": 2, - "react/default-props-match-prop-types": 2, - "react/jsx-closing-tag-location": 2, - "react/jsx-no-duplicate-props": 2, - "react/jsx-closing-bracket-location": 2, - "react/jsx-first-prop-new-line": 2, - "react/jsx-max-props-per-line": [2, { "maximum": 1, "when": "multiline"} ], - "react/jsx-tag-spacing": [2, { - "closingSlash": "never", - "beforeSelfClosing": "always", - "afterOpening": "never" - }], - "react/jsx-wrap-multilines": [2, { - "declaration": "parens-new-line", - "assignment": "parens-new-line", - "return": "parens-new-line", - "arrow": "parens-new-line", - "condition": "parens-new-line", - "logical": "parens-new-line", - "prop": "parens-new-line" - }], - "semi": [2, "never"], - "babel/semi": [2, "never"], - "semi-spacing": [2, { "before": false, "after": true }], - "space-before-blocks": [2, "always"], - "space-before-function-paren": [2, "always"], - "space-in-parens": [2, "never"], - "space-infix-ops": 2, - "space-unary-ops": [2, { "words": true, "nonwords": false }], - "spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","], "exceptions": ["=", "-"] } ], - "strict": 0, - "template-curly-spacing": [2, "never"], - "use-isnan": 2, - "valid-typeof": 2, - "wrap-iife": [2, "any"], - "yield-star-spacing": [2, "both"], - "yoda": [2, "never"], - "prefer-const": 2, - "mocha/no-exclusive-tests": "error" - } -} diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..558e66bc2 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,95 @@ +module.exports = { + parser: 'babel-eslint', + parserOptions: { + 'sourceType': 'module', + 'ecmaVersion': 2017, + 'ecmaFeatures': { + 'experimentalObjectRestSpread': true, + 'impliedStrict': true, + 'modules': true, + 'blockBindings': true, + 'arrowFunctions': true, + 'objectLiteralShorthandMethods': true, + 'objectLiteralShorthandProperties': true, + 'templateStrings': true, + 'classes': true, + 'jsx': true, + }, + }, + + extends: [ + '@metamask/eslint-config', + '@metamask/eslint-config/config/nodejs', + 'plugin:react/recommended', + ], + + env: { + 'browser': true, + 'mocha': true, + }, + + plugins: [ + 'babel', + 'mocha', + 'chai', + 'react', + 'json', + 'import', + ], + + globals: { + 'web3': true, + '$': false, + 'QUnit': false, + }, + + rules: { + 'import/default': 'error', + 'import/export': 'error', + 'import/named': 'error', + 'import/namespace': 'error', + 'import/newline-after-import': 'error', + 'import/no-absolute-path': 'error', + 'import/no-amd': 'error', + 'import/no-anonymous-default-export': ['error', { 'allowObject': true }], + 'import/no-duplicates': 'error', + 'import/no-dynamic-require': 'error', + 'import/no-mutable-exports': 'error', + 'import/no-named-as-default': 'error', + 'import/no-named-as-default-member': 'error', + 'import/no-named-default': 'error', + 'import/no-self-import': 'error', + 'import/no-unresolved': ['error', { 'commonjs': true }], + 'import/no-unused-modules': 'error', + 'import/no-useless-path-segments': ['error', { 'commonjs': true }], + 'import/no-webpack-loader-syntax': 'error', + 'react/no-unused-prop-types': 'error', + 'react/no-unused-state': 'error', + 'react/jsx-boolean-value': 'error', + 'react/jsx-curly-brace-presence': ['error', { 'props': 'never', 'children': 'never' }], + 'react/jsx-equals-spacing': 'error', + 'react/no-deprecated': 'error', + 'react/default-props-match-prop-types': 'error', + 'react/jsx-closing-tag-location': 'error', + 'react/jsx-no-duplicate-props': 'error', + 'react/jsx-closing-bracket-location': 'error', + 'react/jsx-first-prop-new-line': 'error', + 'react/jsx-max-props-per-line': ['error', { 'maximum': 1, 'when': 'multiline' } ], + 'react/jsx-tag-spacing': ['error', { + 'closingSlash': 'never', + 'beforeSelfClosing': 'always', + 'afterOpening': 'never', + }], + 'react/jsx-wrap-multilines': ['error', { + 'declaration': 'parens-new-line', + 'assignment': 'parens-new-line', + 'return': 'parens-new-line', + 'arrow': 'parens-new-line', + 'condition': 'parens-new-line', + 'logical': 'parens-new-line', + 'prop': 'parens-new-line', + }], + 'babel/semi': ['error', 'never'], + 'mocha/no-exclusive-tests': 'error', + }, +} diff --git a/package.json b/package.json index eb7f465d2..7c55a399b 100644 --- a/package.json +++ b/package.json @@ -195,6 +195,7 @@ "@babel/preset-env": "^7.5.5", "@babel/preset-react": "^7.0.0", "@babel/register": "^7.5.5", + "@metamask/eslint-config": "^1.0.0", "@metamask/forwarder": "^1.1.0", "@metamask/onboarding": "^0.2.0", "@sentry/cli": "^1.49.0", diff --git a/yarn.lock b/yarn.lock index 5679b8b42..f9344614e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1997,6 +1997,11 @@ scroll "^2.0.3" warning "^3.0.0" +"@metamask/eslint-config@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-1.0.0.tgz#046012398bb27f56395355c96ef07152925043b7" + integrity sha512-MmxM2sknVhIHyXCjR6LcK57OPJ30gTEX5v/jwC+qXuw4GIgUAPbxFp3AFmFRAJwty3RMjJSbRJ7YlamMq67U8w== + "@metamask/forwarder@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@metamask/forwarder/-/forwarder-1.1.0.tgz#13829d8244bbf19ea658c0b20d21a77b67de0bdd" From 7471e2df02ce74b0b8e5a68dbb533fbc0fb611d8 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 23 Jan 2020 14:04:05 -0400 Subject: [PATCH 167/689] Remove unnecessary WebRTC shim (#7886) The WebRTC spec is fairly stable these days, particularly among the browsers we support. We don't need this shim for anything. I'm guessing it may have been added primarily with IE in mind. --- package.json | 1 - .../modals/qr-scanner/qr-scanner.component.js | 1 - yarn.lock | 20 ------------------- 3 files changed, 22 deletions(-) diff --git a/package.json b/package.json index 7c55a399b..74a44db5b 100644 --- a/package.json +++ b/package.json @@ -184,7 +184,6 @@ "valid-url": "^1.0.9", "web3": "^0.20.7", "web3-stream-provider": "^4.0.0", - "webrtc-adapter": "^6.3.0", "xtend": "^4.0.1" }, "devDependencies": { diff --git a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js b/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js index 3fd08d906..1537c0f52 100644 --- a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js +++ b/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js @@ -1,7 +1,6 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import { BrowserQRCodeReader } from '@zxing/library' -import 'webrtc-adapter' import Spinner from '../../../ui/spinner' import WebcamUtils from '../../../../../lib/webcam-utils' import PageContainerFooter from '../../../ui/page-container/page-container-footer/page-container-footer.component' diff --git a/yarn.lock b/yarn.lock index f9344614e..7c596fe1a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24161,13 +24161,6 @@ rst-selector-parser@^2.2.3: lodash.flattendeep "^4.4.0" nearley "^2.7.10" -rtcpeerconnection-shim@^1.2.10: - version "1.2.13" - resolved "https://registry.yarnpkg.com/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.13.tgz#326e316b06e8b96b40f7558c8f582b86dd2c1b46" - integrity sha512-Xz4zQLZNs9lFBvqbaHGIjLWtyZ1V82ec5r+WNEo7NlIx3zF5M3ytn9mkkfYeZmpE032cNg3Vvf0rP8kNXUNd9w== - dependencies: - sdp "^2.6.0" - rtlcss@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-2.4.0.tgz#482ea28f2b9fe06dd0ab3057997be9af13da84c1" @@ -24500,11 +24493,6 @@ scss-tokenizer@^0.2.3: js-base64 "^2.1.8" source-map "^0.4.2" -sdp@^2.6.0, sdp@^2.7.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/sdp/-/sdp-2.8.0.tgz#8d914a733b1c19b6d8fd36ba6cd2dfbfbd668b8a" - integrity sha512-wRSES07rAwKWAR7aev9UuClT7kdf9ZTdeUK5gTgHue9vlhs19Fbm3ccNEGJO4y2IitH4/JzS4sdzyPl6H2KQLw== - secp256k1@^3.0.1, secp256k1@^3.6.1, secp256k1@^3.6.2: version "3.7.1" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.7.1.tgz#12e473e0e9a7c2f2d4d4818e722ad0e14cc1e2f1" @@ -28449,14 +28437,6 @@ webpack@^4.28.0, webpack@^4.32.0: watchpack "^1.5.0" webpack-sources "^1.3.0" -webrtc-adapter@^6.3.0: - version "6.3.2" - resolved "https://registry.yarnpkg.com/webrtc-adapter/-/webrtc-adapter-6.3.2.tgz#7e616e27defe31968b22b01b902db0d0e68ae786" - integrity sha512-7pFMXpZCka7ScIQyk8Wo+fOr3OlKLtGd6YHqkHVT74zerpY2Siyds8sxsmkE0bNqsi/J1b0vDzN7WpB34dQzAA== - dependencies: - rtcpeerconnection-shim "^1.2.10" - sdp "^2.7.0" - "webrtcsupport@github:ipfs/webrtcsupport": version "2.2.0" resolved "https://codeload.github.com/ipfs/webrtcsupport/tar.gz/0669f576582c53a3a42aa5ac014fcc5966809615" From e79d18de2a082e8fd9f779072ba3a076400b5237 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 23 Jan 2020 14:04:16 -0400 Subject: [PATCH 168/689] Replace DetectRTC package with standard web APIs (#7887) The only web API that our usage of DetectRTC relied upon was 'enumerateDevices', which is supported and stable among all of our supported browsers. Note that the error handling here is a little... non-standard, and the logic around how Firefox and Brave are handled should be justified, but I've left the logic as-is for now to keep this PR small. --- package.json | 1 - ui/lib/webcam-utils.js | 47 +++++++++++++++++++++--------------------- yarn.lock | 5 ----- 3 files changed, 24 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index 74a44db5b..8929fee7a 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,6 @@ "deep-extend": "^0.5.1", "deep-freeze-strict": "1.1.1", "detect-node": "^2.0.3", - "detectrtc": "^1.3.6", "dnode": "^1.2.2", "end-of-stream": "^1.1.0", "eth-block-tracker": "^4.4.2", diff --git a/ui/lib/webcam-utils.js b/ui/lib/webcam-utils.js index 3825efd9d..83897e779 100644 --- a/ui/lib/webcam-utils.js +++ b/ui/lib/webcam-utils.js @@ -1,34 +1,35 @@ 'use strict' -import DetectRTC from 'detectrtc' import { ENVIRONMENT_TYPE_POPUP, PLATFORM_BRAVE, PLATFORM_FIREFOX } from '../../app/scripts/lib/enums' import { getEnvironmentType, getPlatform } from '../../app/scripts/lib/util' class WebcamUtils { - static checkStatus () { - return new Promise((resolve, reject) => { - const isPopup = getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP - const isFirefoxOrBrave = getPlatform() === (PLATFORM_FIREFOX || PLATFORM_BRAVE) - try { - DetectRTC.load(_ => { - if (DetectRTC.hasWebcam) { - let environmentReady = true - if ((isFirefoxOrBrave && isPopup) || (isPopup && !DetectRTC.isWebsiteHasWebcamPermissions)) { - environmentReady = false - } - resolve({ - permissions: DetectRTC.isWebsiteHasWebcamPermissions, - environmentReady, - }) - } else { - reject({ type: 'NO_WEBCAM_FOUND' }) - } - }) - } catch (e) { - reject({ type: 'UNKNOWN_ERROR' }) + static async checkStatus () { + const isPopup = getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP + const isFirefoxOrBrave = getPlatform() === (PLATFORM_FIREFOX || PLATFORM_BRAVE) + + const devices = await window.navigator.mediaDevices.enumerateDevices() + const webcams = devices.filter(device => device.kind === 'videoinput') + const hasWebcam = webcams.length > 0 + // A non-empty-string label implies that the webcam has been granted permission, as + // otherwise the label is kept blank to prevent fingerprinting + const hasWebcamPermissions = webcams.some(webcam => webcam.label && webcam.label.length > 0) + + if (hasWebcam) { + let environmentReady = true + if ((isFirefoxOrBrave && isPopup) || (isPopup && !hasWebcamPermissions)) { + environmentReady = false + } + return { + permissions: hasWebcamPermissions, + environmentReady, } - }) + } else { + const error = new Error('No webcam found') + error.type = 'NO_WEBCAM_FOUND' + throw error + } } } diff --git a/yarn.lock b/yarn.lock index 7c596fe1a..4b89515cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8861,11 +8861,6 @@ detective@^5.0.2: defined "^1.0.0" minimist "^1.1.1" -detectrtc@^1.3.6: - version "1.3.6" - resolved "https://registry.yarnpkg.com/detectrtc/-/detectrtc-1.3.6.tgz#dabc0353981a3da7732de969071c08b6dddd5b59" - integrity sha1-2rwDU5gaPadzLelpBxwItt3dW1k= - dezalgo@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" From 550fba246662594527f758419d1f03398e5a211a Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 23 Jan 2020 16:55:17 -0400 Subject: [PATCH 169/689] Add benchmark to CI (#7871) * Add benchmark to CI The page load benchmark for Chrome is now run during CI, and the results are collected and summarized in the `metamaskbot` comment. Closes #6881 * Double default number of samples The number of default samples was changed from 10 to 20. The results from 10 samples would show statistically significant changes in page load times between builds, so weren't a sufficiently useful metric. --- .circleci/config.yml | 25 ++++++ development/metamaskbot-build-announce.js | 93 ++++++++++++++++++++++- test/e2e/benchmark.js | 3 +- 3 files changed, 119 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 02441c443..16293ef20 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -65,10 +65,14 @@ workflows: - test-e2e-firefox - test-integration-flat-chrome - test-integration-flat-firefox + - benchmark: + requires: + - prep-build-test - job-publish-prerelease: requires: - prep-deps - prep-build + - benchmark - all-tests-pass - job-publish-release: filters: @@ -271,6 +275,27 @@ jobs: path: test-artifacts destination: test-artifacts + benchmark: + docker: + - image: circleci/node:10.17-browsers + steps: + - checkout + - attach_workspace: + at: . + - run: + name: Move test build to dist + command: mv ./dist-test ./dist + - run: + name: Run page load benchmark + command: yarn benchmark:chrome --out test-artifacts/chrome/benchmark/pageload.json + - store_artifacts: + path: test-artifacts + destination: test-artifacts + - persist_to_workspace: + root: . + paths: + - test-artifacts + job-publish-prerelease: docker: - image: circleci/node:10.17-browsers diff --git a/development/metamaskbot-build-announce.js b/development/metamaskbot-build-announce.js index caff15427..d9d887b2f 100755 --- a/development/metamaskbot-build-announce.js +++ b/development/metamaskbot-build-announce.js @@ -1,9 +1,15 @@ #!/usr/bin/env node +const { promises: fs } = require('fs') +const path = require('path') const request = require('request-promise') const VERSION = require('../dist/chrome/manifest.json').version // eslint-disable-line import/no-unresolved start().catch(console.error) +function capitalizeFirstLetter (string) { + return string.charAt(0).toUpperCase() + string.slice(1) +} + async function start () { const GITHUB_COMMENT_TOKEN = process.env.GITHUB_COMMENT_TOKEN @@ -54,7 +60,92 @@ async function start () { ] const hiddenContent = `
      ` + contentRows.map(row => `
    • ${row}
    • `).join('\n') + `
    ` const exposedContent = `Builds ready [${SHORT_SHA1}]` - const commentBody = `
    ${exposedContent}${hiddenContent}
    ` + const artifactsBody = `
    ${exposedContent}${hiddenContent}
    ` + + const benchmarkResults = {} + for (const platform of platforms) { + const benchmarkPath = path.resolve(__dirname, '..', path.join('test-artifacts', platform, 'benchmark', 'pageload.json')) + try { + const data = await fs.readFile(benchmarkPath, 'utf8') + const benchmark = JSON.parse(data) + benchmarkResults[platform] = benchmark + } catch (error) { + if (error.code === 'ENOENT') { + console.log(`No benchmark data found for ${platform}; skipping`) + } else { + console.error(`Error encountered processing benchmark data for '${platform}': '${error}'`) + } + } + } + + let commentBody + if (!benchmarkResults.chrome) { + console.log(`No results for Chrome found; skipping benchmark`) + commentBody = artifactsBody + } else { + try { + const chromePageLoad = Math.round(parseFloat(benchmarkResults.chrome.notification.average.load)) + const chromePageLoadMarginOfError = Math.round(parseFloat(benchmarkResults.chrome.notification.marginOfError.load)) + const benchmarkSummary = `Page Load Metrics (${chromePageLoad} ± ${chromePageLoadMarginOfError} ms)` + + const allPlatforms = new Set() + const allPages = new Set() + const allMetrics = new Set() + const allMeasures = new Set() + for (const platform of Object.keys(benchmarkResults)) { + allPlatforms.add(platform) + const platformBenchmark = benchmarkResults[platform] + const pages = Object.keys(platformBenchmark) + for (const page of pages) { + allPages.add(page) + const pageBenchmark = platformBenchmark[page] + const measures = Object.keys(pageBenchmark) + for (const measure of measures) { + allMeasures.add(measure) + const measureBenchmark = pageBenchmark[measure] + const metrics = Object.keys(measureBenchmark) + for (const metric of metrics) { + allMetrics.add(metric) + } + } + } + } + + const tableRows = [] + for (const platform of allPlatforms) { + const pageRows = [] + for (const page of allPages) { + const metricRows = [] + for (const metric of allMetrics) { + let metricData = `${metric}` + for (const measure of allMeasures) { + metricData += `${Math.round(parseFloat(benchmarkResults[platform][page][measure][metric]))}` + } + metricRows.push(metricData) + } + metricRows[0] = `${capitalizeFirstLetter(page)}${metricRows[0]}` + pageRows.push(...metricRows) + } + pageRows[0] = `${capitalizeFirstLetter(platform)}${pageRows[0]}` + for (const row of pageRows) { + tableRows.push(`${row}`) + } + } + + const benchmarkTableHeaders = ['Platform', 'Page', 'Metric'] + for (const measure of allMeasures) { + benchmarkTableHeaders.push(`${capitalizeFirstLetter(measure)} (ms)`) + } + const benchmarkTableHeader = `${benchmarkTableHeaders.map(header => `${header}`).join('')}` + const benchmarkTableBody = `${tableRows.join('')}` + const benchmarkTable = `${benchmarkTableHeader}${benchmarkTableBody}
    ` + const benchmarkBody = `
    ${benchmarkSummary}${benchmarkTable}
    ` + commentBody = `${artifactsBody}${benchmarkBody}` + } catch (error) { + console.error(`Error constructing benchmark results: '${error}'`) + commentBody = artifactsBody + } + } const JSON_PAYLOAD = JSON.stringify({ body: commentBody }) const POST_COMMENT_URI = `https://api.github.com/repos/metamask/metamask-extension/issues/${CIRCLE_PR_NUMBER}/comments` diff --git a/test/e2e/benchmark.js b/test/e2e/benchmark.js index d89cd5666..825382559 100644 --- a/test/e2e/benchmark.js +++ b/test/e2e/benchmark.js @@ -7,7 +7,7 @@ const { By, Key } = require('selenium-webdriver') const { withFixtures } = require('./helpers') const { PAGES } = require('./webdriver/driver') -const DEFAULT_NUM_SAMPLES = 10 +const DEFAULT_NUM_SAMPLES = 20 const ALL_PAGES = Object.values(PAGES) async function measurePage (pageName) { @@ -16,6 +16,7 @@ async function measurePage (pageName) { const passwordField = await driver.findElement(By.css('#password')) await passwordField.sendKeys('correct horse battery staple') await passwordField.sendKeys(Key.ENTER) + await driver.findElement(By.css('.account-details__account-name')) await driver.navigate(pageName) await driver.delay(1000) metrics = await driver.collectMetrics() From 70a689410a7ee7eb6f3fba942f96e477150baafc Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 24 Jan 2020 14:15:34 -0400 Subject: [PATCH 170/689] Use ref in Mascot component rather than reaching into DOM directly (#7893) Accessing the dom via `document` is strongly discouraged in React. Instead the DOM element is now referenced by ref instead. --- ui/app/components/ui/mascot.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/app/components/ui/mascot.js b/ui/app/components/ui/mascot.js index 4b6aac27d..835290487 100644 --- a/ui/app/components/ui/mascot.js +++ b/ui/app/components/ui/mascot.js @@ -1,5 +1,5 @@ import PropTypes from 'prop-types' -import React, { Component } from 'react' +import React, { createRef, Component } from 'react' import metamaskLogo from 'metamask-logo' import debounce from 'debounce' @@ -22,6 +22,8 @@ export default class Mascot extends Component { height, }) + this.mascotContainer = createRef() + this.refollowMouse = debounce(this.logo.setFollowMouse.bind(this.logo, true), 1000) this.unfollowMouse = this.logo.setFollowMouse.bind(this.logo, false) } @@ -43,9 +45,7 @@ export default class Mascot extends Component { } componentDidMount () { - const targetDivId = 'metamask-mascot-container' - const container = document.getElementById(targetDivId) - container.appendChild(this.logo.container) + this.mascotContainer.current.appendChild(this.logo.container) } componentWillUnmount () { @@ -62,7 +62,7 @@ export default class Mascot extends Component { this.handleAnimationEvents() return (
    ) From b90b30f706f9be9c730e516a362baf5647bf20a5 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 24 Jan 2020 15:12:49 -0400 Subject: [PATCH 171/689] Remove unnecessary `withRouter` and `compose` calls (#7890) `withRouter` has been removed from any components that were not using any of the three props injected by `withRouter`: `history`, `location`, and `match`. `compose` is a no-op when called upon a single component, so it has been removed in all such cases. --- .../app/account-details/account-details.container.js | 5 +---- .../connected-sites-list.container.js | 5 +---- .../permission-page-container.container.js | 7 +------ .../app/signature-request/signature-request.container.js | 7 +------ .../app/transaction-list/transaction-list.container.js | 7 +------ .../transaction-time-remaining.container.js | 7 +------ ui/app/helpers/higher-order-components/i18n-provider.js | 8 +------- .../permissions-connect/permissions-connect.container.js | 5 +---- .../pages/settings/settings-tab/settings-tab.container.js | 5 +---- ui/app/pages/settings/settings.component.js | 4 ++-- 10 files changed, 11 insertions(+), 49 deletions(-) diff --git a/ui/app/components/app/account-details/account-details.container.js b/ui/app/components/app/account-details/account-details.container.js index 11b143653..eb1a1a1e1 100644 --- a/ui/app/components/app/account-details/account-details.container.js +++ b/ui/app/components/app/account-details/account-details.container.js @@ -1,5 +1,4 @@ import { connect } from 'react-redux' -import { compose } from 'recompose' import PropTypes from 'prop-types' import { hideSidebar, showModal } from '../../../store/actions' import AccountDetails from './account-details.component' @@ -13,9 +12,7 @@ function mapDispatchToProps (dispatch) { } } -const AccountDetailsContainer = compose( - connect(null, mapDispatchToProps) -)(AccountDetails) +const AccountDetailsContainer = connect(null, mapDispatchToProps)(AccountDetails) AccountDetailsContainer.propTypes = { label: PropTypes.string.isRequired, diff --git a/ui/app/components/app/connected-sites-list/connected-sites-list.container.js b/ui/app/components/app/connected-sites-list/connected-sites-list.container.js index de45831a9..1058152e1 100644 --- a/ui/app/components/app/connected-sites-list/connected-sites-list.container.js +++ b/ui/app/components/app/connected-sites-list/connected-sites-list.container.js @@ -1,5 +1,4 @@ import { connect } from 'react-redux' -import { compose } from 'recompose' import ConnectedSitesList from './connected-sites-list.component' import { @@ -52,6 +51,4 @@ const mapDispatchToProps = dispatch => { } } -export default compose( - connect(mapStateToProps, mapDispatchToProps) -)(ConnectedSitesList) +export default connect(mapStateToProps, mapDispatchToProps)(ConnectedSitesList) diff --git a/ui/app/components/app/permission-page-container/permission-page-container.container.js b/ui/app/components/app/permission-page-container/permission-page-container.container.js index f83393c70..e8c97cd04 100644 --- a/ui/app/components/app/permission-page-container/permission-page-container.container.js +++ b/ui/app/components/app/permission-page-container/permission-page-container.container.js @@ -1,6 +1,4 @@ import { connect } from 'react-redux' -import { compose } from 'recompose' -import { withRouter } from 'react-router-dom' import PermissionPageContainer from './permission-page-container.component' import { getPermissionsDescriptions, @@ -22,7 +20,4 @@ const mapStateToProps = (state, ownProps) => { } } -export default compose( - withRouter, - connect(mapStateToProps) -)(PermissionPageContainer) +export default connect(mapStateToProps)(PermissionPageContainer) diff --git a/ui/app/components/app/signature-request/signature-request.container.js b/ui/app/components/app/signature-request/signature-request.container.js index 0b09c1a64..d28cc89b9 100644 --- a/ui/app/components/app/signature-request/signature-request.container.js +++ b/ui/app/components/app/signature-request/signature-request.container.js @@ -1,6 +1,4 @@ import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { compose } from 'recompose' import SignatureRequest from './signature-request.component' import { goHome } from '../../../store/actions' import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck' @@ -66,7 +64,4 @@ function mergeProps (stateProps, dispatchProps, ownProps) { } } -export default compose( - withRouter, - connect(mapStateToProps, mapDispatchToProps, mergeProps) -)(SignatureRequest) +export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(SignatureRequest) diff --git a/ui/app/components/app/transaction-list/transaction-list.container.js b/ui/app/components/app/transaction-list/transaction-list.container.js index 4da044b2a..0695c28c2 100644 --- a/ui/app/components/app/transaction-list/transaction-list.container.js +++ b/ui/app/components/app/transaction-list/transaction-list.container.js @@ -1,6 +1,4 @@ import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { compose } from 'recompose' import TransactionList from './transaction-list.component' import { nonceSortedCompletedTransactionsSelector, @@ -45,7 +43,4 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { } } -export default compose( - withRouter, - connect(mapStateToProps, mapDispatchToProps, mergeProps) -)(TransactionList) +export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(TransactionList) diff --git a/ui/app/components/app/transaction-time-remaining/transaction-time-remaining.container.js b/ui/app/components/app/transaction-time-remaining/transaction-time-remaining.container.js index 65eeaa0c3..a9ed6f4dc 100644 --- a/ui/app/components/app/transaction-time-remaining/transaction-time-remaining.container.js +++ b/ui/app/components/app/transaction-time-remaining/transaction-time-remaining.container.js @@ -1,6 +1,4 @@ import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { compose } from 'recompose' import TransactionTimeRemaining from './transaction-time-remaining.component' import { getTxParams, @@ -31,10 +29,7 @@ const mapStateToProps = (state, ownProps) => { } } -export default compose( - withRouter, - connect(mapStateToProps) -)(TransactionTimeRemaining) +export default connect(mapStateToProps)(TransactionTimeRemaining) function calcCustomGasPrice (customGasPriceInHex) { return Number(hexWEIToDecGWEI(customGasPriceInHex)) diff --git a/ui/app/helpers/higher-order-components/i18n-provider.js b/ui/app/helpers/higher-order-components/i18n-provider.js index 33f7ab862..3add2ad85 100644 --- a/ui/app/helpers/higher-order-components/i18n-provider.js +++ b/ui/app/helpers/higher-order-components/i18n-provider.js @@ -1,8 +1,6 @@ import { Component } from 'react' import { connect } from 'react-redux' import PropTypes from 'prop-types' -import { withRouter } from 'react-router-dom' -import { compose } from 'recompose' import { getMessage } from '../utils/i18n-helper' class I18nProvider extends Component { @@ -59,8 +57,4 @@ const mapStateToProps = state => { } } -export default compose( - withRouter, - connect(mapStateToProps) -)(I18nProvider) - +export default connect(mapStateToProps)(I18nProvider) diff --git a/ui/app/pages/permissions-connect/permissions-connect.container.js b/ui/app/pages/permissions-connect/permissions-connect.container.js index f1fdb17ec..0210be525 100644 --- a/ui/app/pages/permissions-connect/permissions-connect.container.js +++ b/ui/app/pages/permissions-connect/permissions-connect.container.js @@ -1,5 +1,4 @@ import { connect } from 'react-redux' -import { compose } from 'recompose' import PropTypes from 'prop-types' import PermissionApproval from './permissions-connect.component' import { @@ -63,9 +62,7 @@ const mapDispatchToProps = dispatch => { } } -const PermissionApprovalContainer = compose( - connect(mapStateToProps, mapDispatchToProps) -)(PermissionApproval) +const PermissionApprovalContainer = connect(mapStateToProps, mapDispatchToProps)(PermissionApproval) PermissionApprovalContainer.propTypes = { history: PropTypes.object.isRequired, diff --git a/ui/app/pages/settings/settings-tab/settings-tab.container.js b/ui/app/pages/settings/settings-tab/settings-tab.container.js index 96fad9ffc..90a1c5e6a 100644 --- a/ui/app/pages/settings/settings-tab/settings-tab.container.js +++ b/ui/app/pages/settings/settings-tab/settings-tab.container.js @@ -1,5 +1,4 @@ import SettingsTab from './settings-tab.component' -import { compose } from 'recompose' import { connect } from 'react-redux' import { setCurrentCurrency, @@ -44,6 +43,4 @@ const mapDispatchToProps = dispatch => { } } -export default compose( - connect(mapStateToProps, mapDispatchToProps) -)(SettingsTab) +export default connect(mapStateToProps, mapDispatchToProps)(SettingsTab) diff --git a/ui/app/pages/settings/settings.component.js b/ui/app/pages/settings/settings.component.js index f52b5fded..7c0405722 100644 --- a/ui/app/pages/settings/settings.component.js +++ b/ui/app/pages/settings/settings.component.js @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' -import { Switch, Route, matchPath, withRouter } from 'react-router-dom' +import { Switch, Route, matchPath } from 'react-router-dom' import TabBar from '../../components/app/tab-bar' import c from 'classnames' import SettingsTab from './settings-tab' @@ -244,4 +244,4 @@ class SettingsPage extends PureComponent { } } -export default withRouter(SettingsPage) +export default SettingsPage From 86c6280bc389d0e71e3fb17d4674a7bf2b1f29a9 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 24 Jan 2020 15:12:58 -0400 Subject: [PATCH 172/689] Remove unnecessary get environment type parameter (#7891) * Remove unnecessary `getEnvironmentType` parameter The default value of the first parameter is `window.location.href`, so there is no need to pass it in explicitly. * Remove junk parameter from `getEnvironmentType` invocation `getEnvironmentType` doesn't need to be passed any parameter, as the default value is `window.location.href` which is generally what is wanted. In this case, the variable `location.href` was always `undefined` anyway. This particular `location` variable is from React Router, and does not have an `href` property. * Fix comment for `getEnvironmentType` One of the possible return values was referred to by the wrong name. --- app/scripts/lib/util.js | 2 +- app/scripts/phishing-detect.js | 2 +- app/scripts/ui.js | 2 +- .../app/account-menu/account-menu.component.js | 2 +- ui/app/components/app/modals/modal.js | 6 +++--- .../signature-request-original.component.js | 4 ++-- .../signature-request/signature-request.component.js | 2 +- .../transaction-list-item.component.js | 2 +- ui/app/ducks/metamask/metamask.js | 2 +- .../confirm-transaction-base.component.js | 4 ++-- ui/app/pages/home/home.container.js | 2 +- .../permissions-connect.component.js | 10 +++++----- ui/app/pages/settings/settings.container.js | 2 +- ui/app/pages/unlock-page/unlock-page.container.js | 2 +- ui/lib/webcam-utils.js | 2 +- 15 files changed, 23 insertions(+), 23 deletions(-) diff --git a/app/scripts/lib/util.js b/app/scripts/lib/util.js index 1393557c6..119470250 100644 --- a/app/scripts/lib/util.js +++ b/app/scripts/lib/util.js @@ -18,7 +18,7 @@ import { /** * Used to determine the window type through which the app is being viewed. * - 'popup' refers to the extension opened through the browser app icon (in top right corner in chrome and firefox) - * - 'responsive' refers to the main browser window + * - 'fullscreen' refers to the main browser window * - 'notification' refers to the popup that appears in its own window when taking action outside of metamask * - 'background' refers to the background page * diff --git a/app/scripts/phishing-detect.js b/app/scripts/phishing-detect.js index 1d8e6024c..554e4bbbb 100644 --- a/app/scripts/phishing-detect.js +++ b/app/scripts/phishing-detect.js @@ -10,7 +10,7 @@ import ExtensionPlatform from './platforms/extension' document.addEventListener('DOMContentLoaded', start) function start () { - const windowType = getEnvironmentType(window.location.href) + const windowType = getEnvironmentType() const hash = window.location.hash.substring(1) const suspect = querystring.parse(hash) diff --git a/app/scripts/ui.js b/app/scripts/ui.js index 66c48e28d..f96d95955 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -52,7 +52,7 @@ async function start () { } // identify window type (popup, notification) - const windowType = getEnvironmentType(window.location.href) + const windowType = getEnvironmentType() global.METAMASK_UI_TYPE = windowType closePopupIfOpen(windowType) diff --git a/ui/app/components/app/account-menu/account-menu.component.js b/ui/app/components/app/account-menu/account-menu.component.js index 8d6b6417f..5ac9814de 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/app/components/app/account-menu/account-menu.component.js @@ -389,7 +389,7 @@ export default class AccountMenu extends Component { name: 'Clicked Connect Hardware', }, }) - if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) { + if (getEnvironmentType() === ENVIRONMENT_TYPE_POPUP) { global.platform.openExtensionInBrowser(CONNECT_HARDWARE_ROUTE) } else { history.push(CONNECT_HARDWARE_ROUTE) diff --git a/ui/app/components/app/modals/modal.js b/ui/app/components/app/modals/modal.js index 46ca0cce6..313bb7c24 100644 --- a/ui/app/components/app/modals/modal.js +++ b/ui/app/components/app/modals/modal.js @@ -236,7 +236,7 @@ const MODALS = { contents: , mobileModalStyle: { width: '95%', - top: getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP ? '52vh' : '36.5vh', + top: getEnvironmentType() === ENVIRONMENT_TYPE_POPUP ? '52vh' : '36.5vh', }, laptopModalStyle: { width: '449px', @@ -265,7 +265,7 @@ const MODALS = { contents: , mobileModalStyle: { width: '95%', - top: getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP ? '52vh' : '36.5vh', + top: getEnvironmentType() === ENVIRONMENT_TYPE_POPUP ? '52vh' : '36.5vh', }, laptopModalStyle: { width: '449px', @@ -277,7 +277,7 @@ const MODALS = { contents: , mobileModalStyle: { width: '95%', - top: getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP ? '52vh' : '36.5vh', + top: getEnvironmentType() === ENVIRONMENT_TYPE_POPUP ? '52vh' : '36.5vh', }, laptopModalStyle: { width: '449px', diff --git a/ui/app/components/app/signature-request-original/signature-request-original.component.js b/ui/app/components/app/signature-request-original/signature-request-original.component.js index 4dbb95bd3..775245539 100644 --- a/ui/app/components/app/signature-request-original/signature-request-original.component.js +++ b/ui/app/components/app/signature-request-original/signature-request-original.component.js @@ -35,7 +35,7 @@ export default class SignatureRequestOriginal extends Component { } componentDidMount = () => { - if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_NOTIFICATION) { + if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { window.addEventListener('beforeunload', this._beforeUnload) } } @@ -59,7 +59,7 @@ export default class SignatureRequestOriginal extends Component { } _removeBeforeUnload = () => { - if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_NOTIFICATION) { + if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { window.removeEventListener('beforeunload', this._beforeUnload) } } diff --git a/ui/app/components/app/signature-request/signature-request.component.js b/ui/app/components/app/signature-request/signature-request.component.js index 645b1b2ed..2a25dd895 100644 --- a/ui/app/components/app/signature-request/signature-request.component.js +++ b/ui/app/components/app/signature-request/signature-request.component.js @@ -29,7 +29,7 @@ export default class SignatureRequest extends PureComponent { componentDidMount () { const { clearConfirmTransaction, cancel } = this.props const { metricsEvent } = this.context - if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_NOTIFICATION) { + if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { window.addEventListener('beforeunload', (event) => { metricsEvent({ eventOpts: { diff --git a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js b/ui/app/components/app/transaction-list-item/transaction-list-item.component.js index 3106f7fc3..8ab08ccad 100644 --- a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js +++ b/ui/app/components/app/transaction-list-item/transaction-list-item.component.js @@ -198,7 +198,7 @@ export default class TransactionListItem extends PureComponent { ? tokenData.params && tokenData.params[0] && tokenData.params[0].value || txParams.to : txParams.to - const isFullScreen = getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_FULLSCREEN + const isFullScreen = getEnvironmentType() === ENVIRONMENT_TYPE_FULLSCREEN const showEstimatedTime = transactionTimeFeatureActive && (transaction.id === firstPendingTransactionId) && isFullScreen diff --git a/ui/app/ducks/metamask/metamask.js b/ui/app/ducks/metamask/metamask.js index e22e7e17f..728d6f2e8 100644 --- a/ui/app/ducks/metamask/metamask.js +++ b/ui/app/ducks/metamask/metamask.js @@ -14,7 +14,7 @@ function reduceMetamask (state, action) { isInitialized: false, isUnlocked: false, isAccountMenuOpen: false, - isPopup: getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP, + isPopup: getEnvironmentType() === ENVIRONMENT_TYPE_POPUP, rpcTarget: 'https://rawtestrpc.metamask.io/', identities: {}, unapprovedTxs: {}, diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js index d9ef41d65..2d6fb7249 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -584,7 +584,7 @@ export default class ConfirmTransactionBase extends Component { } _removeBeforeUnload = () => { - if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_NOTIFICATION) { + if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { window.removeEventListener('beforeunload', this._beforeUnload) } } @@ -603,7 +603,7 @@ export default class ConfirmTransactionBase extends Component { }, }) - if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_NOTIFICATION) { + if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { window.addEventListener('beforeunload', this._beforeUnload) } diff --git a/ui/app/pages/home/home.container.js b/ui/app/pages/home/home.container.js index af192740f..021f9beb1 100644 --- a/ui/app/pages/home/home.container.js +++ b/ui/app/pages/home/home.container.js @@ -27,7 +27,7 @@ const mapStateToProps = state => { const accountBalance = getCurrentEthBalance(state) const { forgottenPassword, threeBoxLastUpdated } = appState - const isPopup = getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP + const isPopup = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP const firstPermissionsRequest = getFirstPermissionRequest(state) const firstPermissionsRequestId = (firstPermissionsRequest && firstPermissionsRequest.metadata) ? firstPermissionsRequest.metadata.id diff --git a/ui/app/pages/permissions-connect/permissions-connect.component.js b/ui/app/pages/permissions-connect/permissions-connect.component.js index 18f8c9df8..9c0c9d877 100644 --- a/ui/app/pages/permissions-connect/permissions-connect.component.js +++ b/ui/app/pages/permissions-connect/permissions-connect.component.js @@ -62,7 +62,7 @@ export default class PermissionConnect extends Component { } removeBeforeUnload = () => { - if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_FULLSCREEN) { + if (getEnvironmentType() === ENVIRONMENT_TYPE_FULLSCREEN) { window.removeEventListener('beforeunload', this.beforeUnload) } } @@ -102,7 +102,7 @@ export default class PermissionConnect extends Component { }) this.removeBeforeUnload() - if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_FULLSCREEN) { + if (getEnvironmentType() === ENVIRONMENT_TYPE_FULLSCREEN) { setTimeout(async () => { const currentTab = await global.platform.currentTab() try { @@ -113,9 +113,9 @@ export default class PermissionConnect extends Component { global.platform.closeTab(currentTab.id) } }, 2000) - } else if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_NOTIFICATION) { + } else if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { history.push(DEFAULT_ROUTE) - } else if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) { + } else if (getEnvironmentType() === ENVIRONMENT_TYPE_POPUP) { history.push(CONNECTED_ROUTE) } } @@ -134,7 +134,7 @@ export default class PermissionConnect extends Component { return history.push(DEFAULT_ROUTE) } - if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_FULLSCREEN) { + if (getEnvironmentType() === ENVIRONMENT_TYPE_FULLSCREEN) { window.addEventListener('beforeunload', this.beforeUnload) } } diff --git a/ui/app/pages/settings/settings.container.js b/ui/app/pages/settings/settings.container.js index 8fe6614df..6a6f385d1 100644 --- a/ui/app/pages/settings/settings.container.js +++ b/ui/app/pages/settings/settings.container.js @@ -47,7 +47,7 @@ const mapStateToProps = (state, ownProps) => { const isEditContactPage = Boolean(pathname.match(CONTACT_EDIT_ROUTE)) const isEditMyAccountsContactPage = Boolean(pathname.match(CONTACT_MY_ACCOUNTS_EDIT_ROUTE)) - const isPopupView = getEnvironmentType(location.href) === ENVIRONMENT_TYPE_POPUP + const isPopupView = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP const pathnameI18nKey = ROUTES_TO_I18N_KEYS[pathname] let backRoute diff --git a/ui/app/pages/unlock-page/unlock-page.container.js b/ui/app/pages/unlock-page/unlock-page.container.js index b89392ab5..2f4687f82 100644 --- a/ui/app/pages/unlock-page/unlock-page.container.js +++ b/ui/app/pages/unlock-page/unlock-page.container.js @@ -38,7 +38,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { markPasswordForgotten() history.push(RESTORE_VAULT_ROUTE) - if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) { + if (getEnvironmentType() === ENVIRONMENT_TYPE_POPUP) { global.platform.openExtensionInBrowser(RESTORE_VAULT_ROUTE) } } diff --git a/ui/lib/webcam-utils.js b/ui/lib/webcam-utils.js index 83897e779..c18507df1 100644 --- a/ui/lib/webcam-utils.js +++ b/ui/lib/webcam-utils.js @@ -6,7 +6,7 @@ import { getEnvironmentType, getPlatform } from '../../app/scripts/lib/util' class WebcamUtils { static async checkStatus () { - const isPopup = getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP + const isPopup = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP const isFirefoxOrBrave = getPlatform() === (PLATFORM_FIREFOX || PLATFORM_BRAVE) const devices = await window.navigator.mediaDevices.enumerateDevices() From 560be4b4e31931c2a69459ec6b87dd8690645d7b Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 24 Jan 2020 17:11:02 -0400 Subject: [PATCH 173/689] Add top-level error page (#7889) Any error caught during a React component render or lifecycle method will now be caught by the top-level error boundary, which shows the user this new error page. The error page will display a simple error message, and will show the details of the error in a collapsible section. The caught error is also reported to Sentry. In development the error will be re-thrown to make it easier to see on the console, but it is not re-thrown in production. --- app/_locales/en/messages.json | 32 ++++++++++++ ui/app/pages/error/error.component.js | 74 +++++++++++++++++++++++++++ ui/app/pages/error/index.js | 1 + ui/app/pages/error/index.scss | 41 +++++++++++++++ ui/app/pages/index.js | 52 ++++++++++++++----- ui/app/pages/index.scss | 2 + 6 files changed, 190 insertions(+), 12 deletions(-) create mode 100644 ui/app/pages/error/error.component.js create mode 100644 ui/app/pages/error/index.js create mode 100644 ui/app/pages/error/index.scss diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index f904ffa50..55b423894 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -531,6 +531,38 @@ "enterPasswordContinue": { "message": "Enter password to continue" }, + "errorCode": { + "message": "Code: $1", + "description": "Displayed error code for debugging purposes. $1 is the error code" + }, + "errorDetails": { + "message": "Error Details", + "description": "Title for collapsible section that displays error details for debugging purposes" + }, + "errorMessage": { + "message": "Message: $1", + "description": "Displayed error message for debugging purposes. $1 is the error message" + }, + "errorName": { + "message": "Code: $1", + "description": "Displayed error name for debugging purposes. $1 is the error name" + }, + "errorPageTitle": { + "message": "MetaMask encountered an error", + "description": "Title of generic error page" + }, + "errorPageMessage": { + "message": "Try again by reloading the page, or contact support at support@metamask.io", + "description": "Message displayed on generic error page in the fullscreen or notification UI" + }, + "errorPagePopupMessage": { + "message": "Try again by closing and reopening the popup, or contact support at support@metamask.io", + "description": "Message displayed on generic error page in the popup UI" + }, + "errorStack": { + "message": "Stack:", + "description": "Title for error stack, which is displayed for debugging purposes" + }, "ethereumPublicAddress": { "message": "Ethereum Public Address" }, diff --git a/ui/app/pages/error/error.component.js b/ui/app/pages/error/error.component.js new file mode 100644 index 000000000..1da1ac609 --- /dev/null +++ b/ui/app/pages/error/error.component.js @@ -0,0 +1,74 @@ +import React, { PureComponent } from 'react' +import PropTypes from 'prop-types' +import { getEnvironmentType } from '../../../../app/scripts/lib/util' +import { ENVIRONMENT_TYPE_POPUP } from '../../../../app/scripts/lib/enums' + +class ErrorPage extends PureComponent { + static contextTypes = { + t: PropTypes.func.isRequired, + } + + static propTypes = { + error: PropTypes.object.isRequired, + } + + renderErrorDetail (content) { + return ( +
  • +

    + {content} +

    +
  • + ) + } + + renderErrorStack (title, stack) { + return ( +
  • + + {title} + +
    +          {stack}
    +        
    +
  • + ) + } + + render () { + const { error } = this.props + const { t } = this.context + + const isPopup = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP + + return ( +
    +

    + {t('errorPageTitle')} +

    +

    + { + isPopup + ? t('errorPagePopupMessage') + : t('errorPageMessage') + } +

    +
    +
    + + {t('errorDetails')} + +
      + { error.message ? this.renderErrorDetail(t('errorMessage', [error.message])) : null } + { error.code ? this.renderErrorDetail(t('errorCode', [error.code])) : null } + { error.name ? this.renderErrorDetail(t('errorName', [error.name])) : null } + { error.stack ? this.renderErrorStack(t('errorStack'), error.stack) : null } +
    +
    +
    +
    + ) + } +} + +export default ErrorPage diff --git a/ui/app/pages/error/index.js b/ui/app/pages/error/index.js new file mode 100644 index 000000000..c2a9f62d9 --- /dev/null +++ b/ui/app/pages/error/index.js @@ -0,0 +1 @@ +export { default } from './error.component' diff --git a/ui/app/pages/error/index.scss b/ui/app/pages/error/index.scss new file mode 100644 index 000000000..6784b374f --- /dev/null +++ b/ui/app/pages/error/index.scss @@ -0,0 +1,41 @@ +.error-page { + display: flex; + flex-flow: column nowrap; + align-items: center; + + font-family: Roboto; + font-style: normal; + font-weight: normal; + + padding: 35px 10px 10px 10px; + height: 100%; + + &__header { + display: flex; + justify-content: center; + font-size: 42px; + padding: 10px 0; + text-align: center; + } + + &__subheader { + font-size: 19px; + padding: 10px 0; + width: 100%; + max-width: 720px; + text-align: center; + } + + &__details { + font-size: 18px; + overflow-y: auto; + width: 100%; + max-width: 720px; + padding-top: 10px; + } + + &__stack { + overflow-x: auto; + background-color: #eee; + } +} diff --git a/ui/app/pages/index.js b/ui/app/pages/index.js index 40b2781a8..7de4fb408 100644 --- a/ui/app/pages/index.js +++ b/ui/app/pages/index.js @@ -1,25 +1,53 @@ -import React from 'react' +import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import { Provider } from 'react-redux' import { HashRouter } from 'react-router-dom' +import * as Sentry from '@sentry/browser' +import ErrorPage from './error' import Routes from './routes' import I18nProvider from '../helpers/higher-order-components/i18n-provider' import MetaMetricsProvider from '../helpers/higher-order-components/metametrics/metametrics.provider' -const Index = props => { - const { store } = props +class Index extends PureComponent { + state = {} - return ( - - - + static getDerivedStateFromError (error) { + return { error } + } + + componentDidCatch (error) { + Sentry.captureException(error) + } + + render () { + const { error, errorId } = this.state + const { store } = this.props + + if (error) { + return ( + - + - - - - ) + + ) + } + + return ( + + + + + + + + + + ) + } } Index.propTypes = { diff --git a/ui/app/pages/index.scss b/ui/app/pages/index.scss index deb6bce45..6325e0b0c 100644 --- a/ui/app/pages/index.scss +++ b/ui/app/pages/index.scss @@ -2,6 +2,8 @@ @import 'add-token/index'; +@import 'error/index'; + @import 'send/send'; @import 'confirm-add-token/index'; From a05f2c465429dd5794baf11ce845cef47942fc71 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 24 Jan 2020 19:24:42 -0330 Subject: [PATCH 174/689] Update GABA dependency version (#7894) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 8929fee7a..303015cd6 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,7 @@ "fast-deep-equal": "^2.0.1", "fast-json-patch": "^2.0.4", "fuse.js": "^3.2.0", - "gaba": "^1.9.0", + "gaba": "^1.9.3", "human-standard-token-abi": "^2.0.0", "jazzicon": "^1.2.0", "json-rpc-engine": "^5.1.6", diff --git a/yarn.lock b/yarn.lock index 4b89515cc..f63a3070f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12513,10 +12513,10 @@ fuse.js@^3.4.4: resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.4.5.tgz#8954fb43f9729bd5dbcb8c08f251db552595a7a6" integrity sha512-s9PGTaQIkT69HaeoTVjwGsLfb8V8ScJLx5XGFcKHg0MqLUH/UZ4EKOtqtXX9k7AFqCGxD1aJmYb8Q5VYDibVRQ== -gaba@^1.6.0, gaba@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/gaba/-/gaba-1.9.0.tgz#ccd9f99c56687b5acd39f9e3ceb435b2a59b6aa1" - integrity sha512-HoVreAdZssL0jNHuzZ7WP+YKZ0riu44jVDWxhQ9hsgPuzxbVEsz9fO/HDxqAdNZS1Cswayq6+ciZ3HSCFWMKbQ== +gaba@^1.6.0, gaba@^1.9.3: + version "1.9.3" + resolved "https://registry.yarnpkg.com/gaba/-/gaba-1.9.3.tgz#4e0e106f3640930f1f06ffe72546903b4c51813e" + integrity sha512-zC9CpaksncAT9SSc4QAxozUE+SKIWN+r9YwhjAJoSeh9joqPJsXlJOHg1/CrHABpvN68QdE00wAYSabYM02EqQ== dependencies: await-semaphore "^0.1.3" eth-contract-metadata "^1.11.0" From 171acae0ebcd6638bc7d4fb5ac99e72ddfd10224 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Sat, 25 Jan 2020 01:14:29 -0330 Subject: [PATCH 175/689] Use eth-contract-metadata@1.12.0 (#7896) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 303015cd6..04c159884 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "dnode": "^1.2.2", "end-of-stream": "^1.1.0", "eth-block-tracker": "^4.4.2", - "eth-contract-metadata": "^1.11.0", + "eth-contract-metadata": "^1.12.0", "eth-ens-namehash": "^2.0.8", "eth-json-rpc-errors": "^2.0.0", "eth-json-rpc-filters": "^4.1.1", diff --git a/yarn.lock b/yarn.lock index f63a3070f..4a5027996 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10339,10 +10339,10 @@ eth-block-tracker@^4.4.2: pify "^3.0.0" safe-event-emitter "^1.0.1" -eth-contract-metadata@^1.11.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/eth-contract-metadata/-/eth-contract-metadata-1.11.0.tgz#4d23a8208d5d53be9d4c0696ed8492b505c6bca1" - integrity sha512-Bbvio71M+lH+qXd8XXddpTc8hhjL9m4fNPOxmZFIX8z0/VooUdwV8YmmDAbkU5WVioZi+Jp1XaoO7VwzXnDboA== +eth-contract-metadata@^1.11.0, eth-contract-metadata@^1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/eth-contract-metadata/-/eth-contract-metadata-1.12.0.tgz#312258682733471f04747e24defade0af43f57da" + integrity sha512-ho796inrIW15aWoi9G3e2IeMPnffLr9zLtsD6GCNbgyiqrzyLgEcO4Sj2U1WZ/y8y9a7FYTEtSi5NHXUweNWNg== eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: version "2.0.8" From f32ea5f6768885f1a02ef3aae860e0d2374b6e5f Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Sun, 26 Jan 2020 13:06:44 -0330 Subject: [PATCH 176/689] Use eth-contract-metadata@1.12.1 (#7901) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 04c159884..72ced8f71 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "dnode": "^1.2.2", "end-of-stream": "^1.1.0", "eth-block-tracker": "^4.4.2", - "eth-contract-metadata": "^1.12.0", + "eth-contract-metadata": "^1.12.1", "eth-ens-namehash": "^2.0.8", "eth-json-rpc-errors": "^2.0.0", "eth-json-rpc-filters": "^4.1.1", diff --git a/yarn.lock b/yarn.lock index 4a5027996..2bdf8ae36 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10339,10 +10339,10 @@ eth-block-tracker@^4.4.2: pify "^3.0.0" safe-event-emitter "^1.0.1" -eth-contract-metadata@^1.11.0, eth-contract-metadata@^1.12.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/eth-contract-metadata/-/eth-contract-metadata-1.12.0.tgz#312258682733471f04747e24defade0af43f57da" - integrity sha512-ho796inrIW15aWoi9G3e2IeMPnffLr9zLtsD6GCNbgyiqrzyLgEcO4Sj2U1WZ/y8y9a7FYTEtSi5NHXUweNWNg== +eth-contract-metadata@^1.11.0, eth-contract-metadata@^1.12.1: + version "1.12.1" + resolved "https://registry.yarnpkg.com/eth-contract-metadata/-/eth-contract-metadata-1.12.1.tgz#41014c8c0123453cee15acbcc14299c4d470c759" + integrity sha512-9u2jUcdxaKIv4RvA9RtjyD4+M2yWt4yCulR5bpdQTiG3HUFnN9lHtNL5NIRDpvQVJKerFhexrgEM2WdGP3a6VA== eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: version "2.0.8" From 7908232719c8038d980c504252a04d9d76e912e7 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Sun, 26 Jan 2020 12:43:50 -0400 Subject: [PATCH 177/689] Replace `request-promise` with `node-fetch` (#7899) `node-fetch` is a smaller and simpler project than `request-promise`, and we already have it as a transitive dependency. `request-promise` was also incorrectly listed as a production dependency. `node-fetch` has been added as a `devDependency` to replace it, as it was only used in one CI script. --- development/metamaskbot-build-announce.js | 9 +++++---- package.json | 2 +- yarn.lock | 10 ---------- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/development/metamaskbot-build-announce.js b/development/metamaskbot-build-announce.js index d9d887b2f..baf82a0f1 100755 --- a/development/metamaskbot-build-announce.js +++ b/development/metamaskbot-build-announce.js @@ -1,7 +1,7 @@ #!/usr/bin/env node const { promises: fs } = require('fs') const path = require('path') -const request = require('request-promise') +const fetch = require('node-fetch') const VERSION = require('../dist/chrome/manifest.json').version // eslint-disable-line import/no-unresolved start().catch(console.error) @@ -152,14 +152,15 @@ async function start () { console.log(`Announcement:\n${commentBody}`) console.log(`Posting to: ${POST_COMMENT_URI}`) - await request({ + const response = await fetch(POST_COMMENT_URI, { method: 'POST', - uri: POST_COMMENT_URI, body: JSON_PAYLOAD, headers: { 'User-Agent': 'metamaskbot', 'Authorization': `token ${GITHUB_COMMENT_TOKEN}`, }, }) - + if (!response.ok) { + throw new Error(`Post comment failed with status '${response.statusText}'`) + } } diff --git a/package.json b/package.json index 72ced8f71..165342a7b 100644 --- a/package.json +++ b/package.json @@ -171,7 +171,6 @@ "redux": "^3.0.5", "redux-logger": "^3.0.6", "redux-thunk": "^2.2.0", - "request-promise": "^4.2.1", "reselect": "^3.0.1", "rpc-cap": "^1.0.1", "safe-event-emitter": "^1.0.1", @@ -272,6 +271,7 @@ "mocha-jsdom": "^1.1.0", "mocha-sinon": "^2.0.0", "nock": "^9.0.14", + "node-fetch": "^2.6.0", "node-sass": "^4.12.0", "nyc": "^13.0.0", "path": "^0.12.7", diff --git a/yarn.lock b/yarn.lock index 2bdf8ae36..065cf54b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23773,16 +23773,6 @@ request-promise-native@^1.0.3: stealthy-require "^1.1.0" tough-cookie ">=2.3.3" -request-promise@^4.2.1: - version "4.2.2" - resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.2.tgz#d1ea46d654a6ee4f8ee6a4fea1018c22911904b4" - integrity sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ= - dependencies: - bluebird "^3.5.0" - request-promise-core "1.1.1" - stealthy-require "^1.1.0" - tough-cookie ">=2.3.3" - request@^2.45.0, request@^2.81.0, request@^2.83.0: version "2.87.0" resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" From 38a71a6067d5fbcdb363b6b690de525f7c38590e Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Sun, 26 Jan 2020 12:49:58 -0400 Subject: [PATCH 178/689] Update Sentry to v5.x (#7880) Theses changes were made in accordance with the provided migration guide [1]. The two integrations added were included by default on v4.x, so this shouldn't result in any change in behavior. [1]: https://github.com/getsentry/sentry-javascript/blob/master/MIGRATION.md --- app/scripts/lib/setupSentry.js | 5 ++ package.json | 3 +- yarn.lock | 88 ++++++++++++++++++++-------------- 3 files changed, 58 insertions(+), 38 deletions(-) diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index 7b0b6b8a0..94fd870d8 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -1,4 +1,5 @@ import * as Sentry from '@sentry/browser' +import { Dedupe, ExtraErrorData } from '@sentry/integrations' const METAMASK_DEBUG = process.env.METAMASK_DEBUG import extractEthjsErrorMessage from './extractEthjsErrorMessage' @@ -26,6 +27,10 @@ function setupSentry (opts) { Sentry.init({ dsn: sentryTarget, debug: METAMASK_DEBUG, + integrations: [ + new Dedupe(), + new ExtraErrorData(), + ], release, beforeSend: (report) => rewriteReport(report), }) diff --git a/package.json b/package.json index 165342a7b..33169fedc 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,8 @@ "@babel/runtime": "^7.5.5", "@download/blockies": "^1.0.3", "@material-ui/core": "1.0.0", - "@sentry/browser": "^4.1.1", + "@sentry/browser": "^5.11.1", + "@sentry/integrations": "^5.11.1", "@zxing/library": "^0.8.0", "abi-decoder": "^1.2.0", "abortcontroller-polyfill": "^1.3.0", diff --git a/yarn.lock b/yarn.lock index 065cf54b2..3df7c1c1f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2064,14 +2064,15 @@ react-lifecycles-compat "^3.0.4" warning "^3.0.0" -"@sentry/browser@^4.1.1": - version "4.2.3" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-4.2.3.tgz#8ee405ba5cad5875945ebbfd5441daa9771bff7f" - integrity sha512-XvuIc1aclz4zuP2LamDuSy62/gl1mmNxzF+Ni5L8mcghBDq0urnOdkblVQgzqGoH8mc2QfjEctGa5djWxg3Bpg== - dependencies: - "@sentry/core" "4.2.3" - "@sentry/types" "4.2.3" - "@sentry/utils" "4.2.3" +"@sentry/browser@^5.11.1": + version "5.11.1" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.11.1.tgz#337ffcb52711b23064c847a07629e966f54a5ebb" + integrity sha512-oqOX/otmuP92DEGRyZeBuQokXdeT9HQRxH73oqIURXXNLMP3PWJALSb4HtT4AftEt/2ROGobZLuA4TaID6My/Q== + dependencies: + "@sentry/core" "5.11.1" + "@sentry/types" "5.11.0" + "@sentry/utils" "5.11.1" + tslib "^1.9.3" "@sentry/cli@^1.49.0": version "1.49.0" @@ -2085,43 +2086,56 @@ progress "2.0.0" proxy-from-env "^1.0.0" -"@sentry/core@4.2.3": - version "4.2.3" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-4.2.3.tgz#58d45e0e6b3f805e9ccd2c32fdff40bc612a7f80" - integrity sha512-xo5rvksftnaEdnKbdokyfuqgMnuqw1DFp0lDboIFHlEBcQde/AdThEgLujJWmbVNI3Cg7g8/HvP65f7QBjKfOw== +"@sentry/core@5.11.1": + version "5.11.1" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.11.1.tgz#9e2da485e196ae32971545c1c49ee6fe719930e2" + integrity sha512-BpvPosVNT20Xso4gAV54Lu3KqDmD20vO63HYwbNdST5LUi8oYV4JhvOkoBraPEM2cbBwQvwVcFdeEYKk4tin9A== dependencies: - "@sentry/hub" "4.2.3" - "@sentry/minimal" "4.2.3" - "@sentry/types" "4.2.3" - "@sentry/utils" "4.2.3" + "@sentry/hub" "5.11.1" + "@sentry/minimal" "5.11.1" + "@sentry/types" "5.11.0" + "@sentry/utils" "5.11.1" + tslib "^1.9.3" -"@sentry/hub@4.2.3": - version "4.2.3" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-4.2.3.tgz#90b84d351051cd537e36836d38dd4ae4b90617bb" - integrity sha512-7Jc/wz3vybYm1RX2wk/4zAQS8fo3uxvXYBkRfpm3OmnGgTlwDEmJwtegeGWFqufxLl85brZ19V1KAdulmO206A== +"@sentry/hub@5.11.1": + version "5.11.1" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.11.1.tgz#ddcb865563fae53852d405885c46b4c6de68a91b" + integrity sha512-ucKprYCbGGLLjVz4hWUqHN9KH0WKUkGf5ZYfD8LUhksuobRkYVyig0ZGbshECZxW5jcDTzip4Q9Qimq/PkkXBg== dependencies: - "@sentry/types" "4.2.3" - "@sentry/utils" "4.2.3" + "@sentry/types" "5.11.0" + "@sentry/utils" "5.11.1" + tslib "^1.9.3" -"@sentry/minimal@4.2.3": - version "4.2.3" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-4.2.3.tgz#f7cde49e797fa75df652bcb95fb06a8a4df4d7ac" - integrity sha512-Hus7LUeJDGsYpT2RTe6bUjG7mHG9uQoyDmW6pYUMN2dhD+cP5cPoTIXO4yxokwgAeDa+GH2/UXoASWc4s2eA2w== +"@sentry/integrations@^5.11.1": + version "5.11.1" + resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-5.11.1.tgz#6612efc620c187ba85a57c6e70e69d9474af7fb6" + integrity sha512-zubOE9zQ4qSutS0ZTnAteDnzbVcHSI2bXD/0nTD3t3ljY+OWgcluBXYCAeAp8vOv2qCoef5ySdQa1DBCW7NQ3Q== dependencies: - "@sentry/hub" "4.2.3" - "@sentry/types" "4.2.3" + "@sentry/types" "5.11.0" + "@sentry/utils" "5.11.1" + tslib "^1.9.3" -"@sentry/types@4.2.3": - version "4.2.3" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-4.2.3.tgz#e53df8ac5c2419d333be8671972a2db6d34de230" - integrity sha512-Z7laXlLtLSEXcKzgcD2caWPMTM8sAvR86rssYM5uYb3azC5PO0aAvuhjokkdv1+Ke1Bg7lkaNZamiCSyaH/9xg== +"@sentry/minimal@5.11.1": + version "5.11.1" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.11.1.tgz#0e705d01a567282d8fbbda2aed848b4974cc3cec" + integrity sha512-HK8zs7Pgdq7DsbZQTThrhQPrJsVWzz7MaluAbQA0rTIAJ3TvHKQpsVRu17xDpjZXypqWcKCRsthDrC4LxDM1Bg== + dependencies: + "@sentry/hub" "5.11.1" + "@sentry/types" "5.11.0" + tslib "^1.9.3" -"@sentry/utils@4.2.3": - version "4.2.3" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-4.2.3.tgz#46119e0938308245054984303ee1b049a7ab7523" - integrity sha512-D6+M1081wCwGp8adWV3KFOxrxFmVyjMJ45x6/TnYvXdgDyc+t28oil21FHeKhwjld9eMqgQ5Tf1OOvos1MNBQg== +"@sentry/types@5.11.0": + version "5.11.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.11.0.tgz#40f0f3174362928e033ddd9725d55e7c5cb7c5b6" + integrity sha512-1Uhycpmeo1ZK2GLvrtwZhTwIodJHcyIS6bn+t4IMkN9MFoo6ktbAfhvexBDW/IDtdLlCGJbfm8nIZerxy0QUpg== + +"@sentry/utils@5.11.1": + version "5.11.1" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.11.1.tgz#aa19fcc234cf632257b2281261651d2fac967607" + integrity sha512-O0Zl4R2JJh8cTkQ8ZL2cDqGCmQdpA5VeXpuBbEl1v78LQPkBDISi35wH4mKmLwMsLBtTVpx2UeUHBj0KO5aLlA== dependencies: - "@sentry/types" "4.2.3" + "@sentry/types" "5.11.0" + tslib "^1.9.3" "@sindresorhus/is@^0.14.0": version "0.14.0" From 245952f236a459887bf5b81e748f61d22e12e52c Mon Sep 17 00:00:00 2001 From: ricky Date: Sun, 26 Jan 2020 18:44:58 -0500 Subject: [PATCH 179/689] Minimum changes to get storybook working (#7884) * Minimum changes to get storybook working Undo path changes * Add build:storybook scripts to package.json * Add storybook deployer * Add storybook:deploy to package.json * Update circle ci config * Update yarn.lock * Remove addon-info * Update yarn.lock file to reflect removing of addon-info Co-authored-by: Dan J Miller --- .circleci/config.yml | 16 + .storybook/decorators.js | 2 - package.json | 11 +- yarn.lock | 4196 ++++++++++++++++++++++++++------------ 4 files changed, 2899 insertions(+), 1326 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 16293ef20..8f2aad2e7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -83,6 +83,12 @@ workflows: - prep-build # - prep-docs - all-tests-pass + - job-publish-storybook: + filters: + branches: + only: develop + requires: + - prep-deps - coveralls-upload: requires: - test-unit @@ -349,6 +355,16 @@ jobs: # git config --global user.name "metamaskbot" && # git config --global user.email "admin@metamask.io" && # yarn publish-docs + job-publish-storybook: + docker: + - image: circleci/node:10.17-browsers + steps: + - checkout + - attach_workspace: + at: . + - run: + name: storybook:deploy + command: yarn storybook:deploy test-unit: docker: diff --git a/.storybook/decorators.js b/.storybook/decorators.js index 7b0745ac4..f204a7cd2 100644 --- a/.storybook/decorators.js +++ b/.storybook/decorators.js @@ -1,6 +1,5 @@ import React from 'react' import { addDecorator } from '@storybook/react' -import { withInfo } from '@storybook/addon-info' import { withKnobs } from '@storybook/addon-knobs/react' const styles = { @@ -16,6 +15,5 @@ const CenterDecorator = story => (
    ) -addDecorator((story, context) => withInfo()(story)(context)) addDecorator(withKnobs) addDecorator(CenterDecorator) diff --git a/package.json b/package.json index 33169fedc..689b24f50 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,8 @@ "announce": "node development/announcer.js", "version:bump": "node development/run-version-bump.js", "storybook": "start-storybook -p 6006 -c .storybook", + "storybook:build": "build-storybook -c .storybook -o .out", + "storybook:deploy": "storybook-to-ghpages", "update-changelog": "./development/auto-changelog.sh", "rollback": "./development/rollback.sh", "generate:migration": "./development/generate-migration.sh" @@ -197,12 +199,13 @@ "@metamask/forwarder": "^1.1.0", "@metamask/onboarding": "^0.2.0", "@sentry/cli": "^1.49.0", - "@storybook/addon-actions": "^5.2.6", - "@storybook/addon-info": "^5.1.1", - "@storybook/addon-knobs": "^5.1.1", - "@storybook/react": "^5.1.1", + "@storybook/addon-actions": "^5.2.8", + "@storybook/addon-knobs": "^5.2.8", + "@storybook/react": "^5.2.8", + "@storybook/storybook-deployer": "^2.8.1", "addons-linter": "1.14.0", "babel-eslint": "^10.0.2", + "babel-loader": "^8.0.6", "babelify": "^10.0.0", "brfs": "^1.6.1", "browserify": "^16.2.3", diff --git a/yarn.lock b/yarn.lock index 3df7c1c1f..f3f4e8385 100644 --- a/yarn.lock +++ b/yarn.lock @@ -68,25 +68,12 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/core@7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.4.3.tgz#198d6d3af4567be3989550d97e068de94503074f" - integrity sha512-oDpASqKFlbspQfzAE7yaeTmdljSH2ADIvBlb0RwbStltTuWa0+7CCI1fYVINNv9saHPa1W7oaKeuNuKj+RQCvA== +"@babel/code-frame@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" + integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.4.0" - "@babel/helpers" "^7.4.3" - "@babel/parser" "^7.4.3" - "@babel/template" "^7.4.0" - "@babel/traverse" "^7.4.3" - "@babel/types" "^7.4.0" - convert-source-map "^1.1.0" - debug "^4.1.0" - json5 "^2.1.0" - lodash "^4.17.11" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" + "@babel/highlight" "^7.8.3" "@babel/core@>=7.2.2": version "7.6.0" @@ -108,20 +95,21 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.0.0", "@babel/core@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.5.5.tgz#17b2686ef0d6bc58f963dddd68ab669755582c30" - integrity sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.5.5" - "@babel/helpers" "^7.5.5" - "@babel/parser" "^7.5.5" - "@babel/template" "^7.4.4" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" - convert-source-map "^1.1.0" +"@babel/core@^7.1.0", "@babel/core@^7.7.5": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.3.tgz#30b0ebb4dd1585de6923a0b4d179e0b9f5d82941" + integrity sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.3" + "@babel/helpers" "^7.8.3" + "@babel/parser" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + convert-source-map "^1.7.0" debug "^4.1.0" + gensync "^1.0.0-beta.1" json5 "^2.1.0" lodash "^4.17.13" resolve "^1.3.2" @@ -148,6 +136,26 @@ semver "^5.4.1" source-map "^0.5.0" +"@babel/core@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.5.5.tgz#17b2686ef0d6bc58f963dddd68ab669755582c30" + integrity sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.5.5" + "@babel/helpers" "^7.5.5" + "@babel/parser" "^7.5.5" + "@babel/template" "^7.4.4" + "@babel/traverse" "^7.5.5" + "@babel/types" "^7.5.5" + convert-source-map "^1.1.0" + debug "^4.1.0" + json5 "^2.1.0" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + "@babel/generator@7.0.0-beta.51": version "7.0.0-beta.51" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.51.tgz#6c7575ffde761d07485e04baedc0392c6d9e30f6" @@ -192,6 +200,16 @@ source-map "^0.5.0" trim-right "^1.0.1" +"@babel/generator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.3.tgz#0e22c005b0a94c1c74eafe19ef78ce53a4d45c03" + integrity sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug== + dependencies: + "@babel/types" "^7.8.3" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" @@ -199,6 +217,13 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-annotate-as-pure@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" + integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" @@ -224,18 +249,6 @@ "@babel/traverse" "^7.4.4" "@babel/types" "^7.4.4" -"@babel/helper-create-class-features-plugin@^7.4.0", "@babel/helper-create-class-features-plugin@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.4.4.tgz#fc3d690af6554cc9efc607364a82d48f58736dba" - integrity sha512-UbBHIa2qeAGgyiNR9RszVF7bUHEdgS4JAUNT8SiqrAN6YJVxlOxeLr5pBzb5kan302dejJ9nla4RyKcR1XT6XA== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-member-expression-to-functions" "^7.0.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.4.4" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/helper-create-class-features-plugin@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.5.5.tgz#401f302c8ddbc0edd36f7c6b2887d8fa1122e5a4" @@ -248,7 +261,19 @@ "@babel/helper-replace-supers" "^7.5.5" "@babel/helper-split-export-declaration" "^7.4.4" -"@babel/helper-define-map@^7.4.0", "@babel/helper-define-map@^7.4.4": +"@babel/helper-create-class-features-plugin@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz#5b94be88c255f140fd2c10dd151e7f98f4bff397" + integrity sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + +"@babel/helper-define-map@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz#6969d1f570b46bdc900d1eba8e5d59c48ba2c12a" integrity sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg== @@ -292,6 +317,15 @@ "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" +"@babel/helper-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" + integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + "@babel/helper-get-function-arity@7.0.0-beta.51": version "7.0.0-beta.51" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.51.tgz#3281b2d045af95c172ce91b20825d85ea4676411" @@ -306,6 +340,13 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-get-function-arity@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" + integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-hoist-variables@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a" @@ -327,6 +368,13 @@ dependencies: "@babel/types" "^7.5.5" +"@babel/helper-member-expression-to-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" + integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-module-imports@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" @@ -353,11 +401,23 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-optimise-call-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" + integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-plugin-utils@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== +"@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" + integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== + "@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.4.4.tgz#a47e02bc91fb259d2e6727c2a30013e3ac13c4a2" @@ -376,7 +436,7 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-replace-supers@^7.1.0", "@babel/helper-replace-supers@^7.4.0", "@babel/helper-replace-supers@^7.4.4": +"@babel/helper-replace-supers@^7.1.0", "@babel/helper-replace-supers@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz#aee41783ebe4f2d3ab3ae775e1cc6f1a90cefa27" integrity sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg== @@ -396,6 +456,16 @@ "@babel/traverse" "^7.5.5" "@babel/types" "^7.5.5" +"@babel/helper-replace-supers@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz#91192d25f6abbcd41da8a989d4492574fb1530bc" + integrity sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + "@babel/helper-simple-access@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" @@ -411,13 +481,20 @@ dependencies: "@babel/types" "7.0.0-beta.51" -"@babel/helper-split-export-declaration@^7.4.0", "@babel/helper-split-export-declaration@^7.4.4": +"@babel/helper-split-export-declaration@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== dependencies: "@babel/types" "^7.4.4" +"@babel/helper-split-export-declaration@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" + integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-wrap-function@^7.1.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" @@ -428,15 +505,6 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.2.0" -"@babel/helpers@^7.4.3": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.4.4.tgz#868b0ef59c1dd4e78744562d5ce1b59c89f2f2a5" - integrity sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A== - dependencies: - "@babel/template" "^7.4.4" - "@babel/traverse" "^7.4.4" - "@babel/types" "^7.4.4" - "@babel/helpers@^7.4.4", "@babel/helpers@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.5.5.tgz#63908d2a73942229d1e6685bc2a0e730dde3b75e" @@ -455,6 +523,15 @@ "@babel/traverse" "^7.6.0" "@babel/types" "^7.6.0" +"@babel/helpers@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.3.tgz#382fbb0382ce7c4ce905945ab9641d688336ce85" + integrity sha512-LmU3q9Pah/XyZU89QvBgGt+BCsTPoQa+73RxAQh8fb8qkDyIfeQnmgs+hvzhTCKTzqOyk7JTkS3MS1S8Mq5yrQ== + dependencies: + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + "@babel/highlight@7.0.0-beta.51": version "7.0.0-beta.51" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.51.tgz#e8844ae25a1595ccfd42b89623b4376ca06d225d" @@ -473,6 +550,15 @@ esutils "^2.0.2" js-tokens "^4.0.0" +"@babel/highlight@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" + integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + "@babel/parser@7.0.0-beta.51": version "7.0.0-beta.51" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.0.0-beta.51.tgz#27cec2df409df60af58270ed8f6aa55409ea86f6" @@ -483,6 +569,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.5.tgz#02f077ac8817d3df4a832ef59de67565e71cca4b" integrity sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g== +"@babel/parser@^7.1.0", "@babel/parser@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.3.tgz#790874091d2001c9be6ec426c2eed47bc7679081" + integrity sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ== + "@babel/parser@^7.4.3": version "7.4.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.5.tgz#04af8d5d5a2b044a2a1bffacc1e5e6673544e872" @@ -502,22 +593,6 @@ "@babel/helper-remap-async-to-generator" "^7.1.0" "@babel/plugin-syntax-async-generators" "^7.2.0" -"@babel/plugin-proposal-class-properties@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.4.0.tgz#d70db61a2f1fd79de927eea91f6411c964e084b8" - integrity sha512-t2ECPNOXsIeK1JxJNKmgbzQtoG27KIlVE61vTqX0DKR9E9sZlVVxWUtEW9D5FlZ8b8j7SBNCHY47GgPKCKlpPg== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.4.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-proposal-class-properties@^7.3.3": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.4.4.tgz#93a6486eed86d53452ab9bab35e368e9461198ce" - integrity sha512-WjKTI8g8d5w1Bc9zgwSz2nfrsNQsXcCf9J9cdCvrJV6RF56yztwm4TmJC0MgJ9tvwO9gUA/mcYe89bLdGfiXFg== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.4.4" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-class-properties@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.5.tgz#a974cfae1e37c3110e71f3c6a2e48b8e71958cd4" @@ -526,14 +601,13 @@ "@babel/helper-create-class-features-plugin" "^7.5.5" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-proposal-decorators@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.4.0.tgz#8e1bfd83efa54a5f662033afcc2b8e701f4bb3a9" - integrity sha512-d08TLmXeK/XbgCo7ZeZ+JaeZDtDai/2ctapTRsWWkkmy7G/cqz8DQN/HlWG7RR4YmfXxmExsbU3SuCjlM7AtUg== +"@babel/plugin-proposal-class-properties@^7.7.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz#5e06654af5cd04b608915aada9b2a6788004464e" + integrity sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.4.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-decorators" "^7.2.0" + "@babel/helper-create-class-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-proposal-dynamic-import@^7.5.0": version "7.5.0" @@ -551,15 +625,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-json-strings" "^7.2.0" -"@babel/plugin-proposal-object-rest-spread@7.4.3", "@babel/plugin-proposal-object-rest-spread@^7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.3.tgz#be27cd416eceeba84141305b93c282f5de23bbb4" - integrity sha512-xC//6DNSSHVjq8O2ge0dyYlhshsH4T7XdCVoxbi5HzLYWfsC5ooFlJjrXk8RcAT+hjHAK9UjBXdylzSoDK3t4g== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" - -"@babel/plugin-proposal-object-rest-spread@^7.3.2", "@babel/plugin-proposal-object-rest-spread@^7.4.4": +"@babel/plugin-proposal-object-rest-spread@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz#1ef173fcf24b3e2df92a678f027673b55e7e3005" integrity sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g== @@ -575,6 +641,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" +"@babel/plugin-proposal-object-rest-spread@^7.6.2": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz#eb5ae366118ddca67bed583b53d7554cad9951bb" + integrity sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-proposal-optional-catch-binding@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" @@ -583,7 +657,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" -"@babel/plugin-proposal-unicode-property-regex@^7.4.0", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": +"@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz#501ffd9826c0b91da22690720722ac7cb1ca9c78" integrity sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA== @@ -599,14 +673,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-decorators@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.2.0.tgz#c50b1b957dcc69e4b1127b65e1c33eef61570c1b" - integrity sha512-38QdqVoXdHUQfTpZo3rQwqQdWtCn5tMv4uV6r2RMfTqNBuv4ZBhz79SfaQWKTVmxHjeFv/DnXVC/+agHCklYWA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-dynamic-import@7.2.0", "@babel/plugin-syntax-dynamic-import@^7.2.0": +"@babel/plugin-syntax-dynamic-import@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612" integrity sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w== @@ -634,6 +701,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + "@babel/plugin-syntax-object-rest-spread@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" @@ -648,13 +722,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-typescript@^7.2.0": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.3.3.tgz#a7cc3f66119a9f7ebe2de5383cce193473d65991" - integrity sha512-dGwbSMA1YhVS8+31CnPR7LB4pcbrzcV99wQzby4uAfrkZPYZlQ7ImwdpzLqi6Z6IL02b8IAL379CaMwo0x5Lag== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-transform-arrow-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" @@ -662,7 +729,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-async-to-generator@^7.4.0", "@babel/plugin-transform-async-to-generator@^7.4.4": +"@babel/plugin-transform-async-to-generator@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz#a3f1d01f2f21cadab20b33a82133116f14fb5894" integrity sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA== @@ -687,7 +754,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-block-scoping@^7.4.0", "@babel/plugin-transform-block-scoping@^7.4.4": +"@babel/plugin-transform-block-scoping@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz#c13279fabf6b916661531841a23c4b7dae29646d" integrity sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA== @@ -703,20 +770,6 @@ "@babel/helper-plugin-utils" "^7.0.0" lodash "^4.17.13" -"@babel/plugin-transform-classes@7.4.3", "@babel/plugin-transform-classes@^7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.3.tgz#adc7a1137ab4287a555d429cc56ecde8f40c062c" - integrity sha512-PUaIKyFUDtG6jF5DUJOfkBdwAS/kFFV3XFk7Nn0a6vR7ZT8jYw5cGtIlat77wcnd0C6ViGqo/wyNf4ZHytF/nQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-define-map" "^7.4.0" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.4.0" - "@babel/helper-split-export-declaration" "^7.4.0" - globals "^11.1.0" - "@babel/plugin-transform-classes@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz#0ce4094cdafd709721076d3b9c38ad31ca715eb6" @@ -752,13 +805,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-destructuring@7.4.3", "@babel/plugin-transform-destructuring@^7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.3.tgz#1a95f5ca2bf2f91ef0648d5de38a8d472da4350f" - integrity sha512-rVTLLZpydDFDyN4qnXdzwoVpk1oaXHIvPEOkOLyr88o7oHxVc/LyrnDx+amuBWGOwUb7D1s/uLsKBNTx08htZg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-transform-destructuring@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz#9d964717829cc9e4b601fc82a26a71a4d8faf20f" @@ -773,7 +819,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-dotall-regex@^7.4.3", "@babel/plugin-transform-dotall-regex@^7.4.4": +"@babel/plugin-transform-dotall-regex@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz#361a148bc951444312c69446d76ed1ea8e4450c3" integrity sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg== @@ -804,14 +850,6 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-flow-strip-types@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.4.0.tgz#f3c59eecff68c99b9c96eaafe4fe9d1fa8947138" - integrity sha512-C4ZVNejHnfB22vI2TYN4RUp2oCmq6cSEAg4RygSvYZUECRqUu9O4PMEMNJ4wsemaRGg27BbgYctG4BZh+AgIHw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-flow" "^7.2.0" - "@babel/plugin-transform-flow-strip-types@^7.0.0": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.4.4.tgz#d267a081f49a8705fc9146de0768c6b58dccd8f7" @@ -820,14 +858,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-flow" "^7.2.0" -"@babel/plugin-transform-for-of@^7.4.3", "@babel/plugin-transform-for-of@^7.4.4": +"@babel/plugin-transform-for-of@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-function-name@^7.4.3", "@babel/plugin-transform-function-name@^7.4.4": +"@babel/plugin-transform-function-name@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz#e1436116abb0610c2259094848754ac5230922ad" integrity sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA== @@ -866,7 +904,7 @@ "@babel/helper-plugin-utils" "^7.0.0" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-commonjs@^7.4.3", "@babel/plugin-transform-modules-commonjs@^7.4.4": +"@babel/plugin-transform-modules-commonjs@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz#0bef4713d30f1d78c2e59b3d6db40e60192cac1e" integrity sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw== @@ -885,7 +923,7 @@ "@babel/helper-simple-access" "^7.1.0" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-systemjs@^7.4.0", "@babel/plugin-transform-modules-systemjs@^7.4.4": +"@babel/plugin-transform-modules-systemjs@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz#dc83c5665b07d6c2a7b224c00ac63659ea36a405" integrity sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ== @@ -910,14 +948,14 @@ "@babel/helper-module-transforms" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-named-capturing-groups-regex@^7.4.2", "@babel/plugin-transform-named-capturing-groups-regex@^7.4.5": +"@babel/plugin-transform-named-capturing-groups-regex@^7.4.5": version "7.4.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz#9d269fd28a370258199b4294736813a60bbdd106" integrity sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg== dependencies: regexp-tree "^0.1.6" -"@babel/plugin-transform-new-target@^7.4.0", "@babel/plugin-transform-new-target@^7.4.4": +"@babel/plugin-transform-new-target@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5" integrity sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA== @@ -940,7 +978,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-replace-supers" "^7.5.5" -"@babel/plugin-transform-parameters@^7.4.3", "@babel/plugin-transform-parameters@^7.4.4": +"@babel/plugin-transform-parameters@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16" integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw== @@ -956,7 +994,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-react-constant-elements@7.2.0", "@babel/plugin-transform-react-constant-elements@^7.0.0", "@babel/plugin-transform-react-constant-elements@^7.2.0": +"@babel/plugin-transform-react-constant-elements@^7.0.0", "@babel/plugin-transform-react-constant-elements@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.2.0.tgz#ed602dc2d8bff2f0cb1a5ce29263dbdec40779f7" integrity sha512-YYQFg6giRFMsZPKUM9v+VcHOdfSQdz9jHCx3akAi3UYgyjndmdYGSXylQ/V+HswQt4fL8IklchD9HTsaOCrWQQ== @@ -964,7 +1002,15 @@ "@babel/helper-annotate-as-pure" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-react-display-name@7.2.0", "@babel/plugin-transform-react-display-name@^7.0.0": +"@babel/plugin-transform-react-constant-elements@^7.6.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.8.3.tgz#784c25294bddaad2323eb4ff0c9f4a3f6c87d6bc" + integrity sha512-glrzN2U+egwRfkNFtL34xIBYTxbbUF2qJTP8HD3qETBBqzAWSeNB821X0GjU06+dNpq/UyCIjI72FmGE5NNkQQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-react-display-name@^7.0.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.2.0.tgz#ebfaed87834ce8dc4279609a4f0c324c156e3eb0" integrity sha512-Htf/tPa5haZvRMiNSQSFifK12gtr/8vwfr+A9y69uF0QcU77AVu4K7MiHEkTxF7lQoHOL0F9ErqgfNEAKgXj7A== @@ -996,7 +1042,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-jsx" "^7.2.0" -"@babel/plugin-transform-regenerator@^7.4.3", "@babel/plugin-transform-regenerator@^7.4.5": +"@babel/plugin-transform-regenerator@^7.4.5": version "7.4.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz#629dc82512c55cee01341fb27bdfcb210354680f" integrity sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA== @@ -1010,16 +1056,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-runtime@7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.4.3.tgz#4d6691690ecdc9f5cb8c3ab170a1576c1f556371" - integrity sha512-7Q61bU+uEI7bCUFReT1NKn7/X6sDQsZ7wL1sJ9IYMAO7cI+eg6x9re1cEw2fCRMbbTVyoeUKWSV1M6azEfKCfg== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - resolve "^1.8.1" - semver "^5.5.1" - "@babel/plugin-transform-runtime@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.5.5.tgz#a6331afbfc59189d2135b2e09474457a8e3d28bc" @@ -1052,7 +1088,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" -"@babel/plugin-transform-template-literals@^7.2.0", "@babel/plugin-transform-template-literals@^7.4.4": +"@babel/plugin-transform-template-literals@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0" integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g== @@ -1067,15 +1103,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-typescript@^7.3.2": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.4.5.tgz#ab3351ba35307b79981993536c93ff8be050ba28" - integrity sha512-RPB/YeGr4ZrFKNwfuQRlMf2lxoCUaU01MTw39/OFE/RiL8HDjtn68BwEPft1P7JN4akyEmjGWAMNldOV7o9V2g== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-typescript" "^7.2.0" - -"@babel/plugin-transform-unicode-regex@^7.4.3", "@babel/plugin-transform-unicode-regex@^7.4.4": +"@babel/plugin-transform-unicode-regex@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz#ab4634bb4f14d36728bf5978322b35587787970f" integrity sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA== @@ -1084,60 +1112,6 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" -"@babel/preset-env@7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.4.3.tgz#e71e16e123dc0fbf65a52cbcbcefd072fbd02880" - integrity sha512-FYbZdV12yHdJU5Z70cEg0f6lvtpZ8jFSDakTm7WXeJbLXh4R0ztGEu/SW7G1nJ2ZvKwDhz8YrbA84eYyprmGqw== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-async-generator-functions" "^7.2.0" - "@babel/plugin-proposal-json-strings" "^7.2.0" - "@babel/plugin-proposal-object-rest-spread" "^7.4.3" - "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.0" - "@babel/plugin-syntax-async-generators" "^7.2.0" - "@babel/plugin-syntax-json-strings" "^7.2.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" - "@babel/plugin-transform-arrow-functions" "^7.2.0" - "@babel/plugin-transform-async-to-generator" "^7.4.0" - "@babel/plugin-transform-block-scoped-functions" "^7.2.0" - "@babel/plugin-transform-block-scoping" "^7.4.0" - "@babel/plugin-transform-classes" "^7.4.3" - "@babel/plugin-transform-computed-properties" "^7.2.0" - "@babel/plugin-transform-destructuring" "^7.4.3" - "@babel/plugin-transform-dotall-regex" "^7.4.3" - "@babel/plugin-transform-duplicate-keys" "^7.2.0" - "@babel/plugin-transform-exponentiation-operator" "^7.2.0" - "@babel/plugin-transform-for-of" "^7.4.3" - "@babel/plugin-transform-function-name" "^7.4.3" - "@babel/plugin-transform-literals" "^7.2.0" - "@babel/plugin-transform-member-expression-literals" "^7.2.0" - "@babel/plugin-transform-modules-amd" "^7.2.0" - "@babel/plugin-transform-modules-commonjs" "^7.4.3" - "@babel/plugin-transform-modules-systemjs" "^7.4.0" - "@babel/plugin-transform-modules-umd" "^7.2.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.4.2" - "@babel/plugin-transform-new-target" "^7.4.0" - "@babel/plugin-transform-object-super" "^7.2.0" - "@babel/plugin-transform-parameters" "^7.4.3" - "@babel/plugin-transform-property-literals" "^7.2.0" - "@babel/plugin-transform-regenerator" "^7.4.3" - "@babel/plugin-transform-reserved-words" "^7.2.0" - "@babel/plugin-transform-shorthand-properties" "^7.2.0" - "@babel/plugin-transform-spread" "^7.2.0" - "@babel/plugin-transform-sticky-regex" "^7.2.0" - "@babel/plugin-transform-template-literals" "^7.2.0" - "@babel/plugin-transform-typeof-symbol" "^7.2.0" - "@babel/plugin-transform-unicode-regex" "^7.4.3" - "@babel/types" "^7.4.0" - browserslist "^4.5.2" - core-js-compat "^3.0.0" - invariant "^2.2.2" - js-levenshtein "^1.1.3" - semver "^5.5.0" - "@babel/preset-env@^7.4.3", "@babel/preset-env@^7.4.5": version "7.4.5" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.4.5.tgz#2fad7f62983d5af563b5f3139242755884998a58" @@ -1256,7 +1230,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-flow-strip-types" "^7.0.0" -"@babel/preset-react@7.0.0", "@babel/preset-react@^7.0.0": +"@babel/preset-react@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.0.0.tgz#e86b4b3d99433c7b3e9e91747e2653958bc6b3c0" integrity sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w== @@ -1267,14 +1241,6 @@ "@babel/plugin-transform-react-jsx-self" "^7.0.0" "@babel/plugin-transform-react-jsx-source" "^7.0.0" -"@babel/preset-typescript@7.3.3": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.3.3.tgz#88669911053fa16b2b276ea2ede2ca603b3f307a" - integrity sha512-mzMVuIP4lqtn4du2ynEfdO0+RYcslwrZiJHXu4MGaC1ctJiW2fyaeDrtjJGs7R/KebZ1sgowcIoWf4uRpEfKEg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-transform-typescript" "^7.3.2" - "@babel/register@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.5.5.tgz#40fe0d474c8c8587b28d6ae18a03eddad3dac3c1" @@ -1294,13 +1260,6 @@ dependencies: regenerator-runtime "^0.12.0" -"@babel/runtime@7.4.3", "@babel/runtime@^7.4.2": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.3.tgz#79888e452034223ad9609187a0ad1fe0d2ad4bdc" - integrity sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA== - dependencies: - regenerator-runtime "^0.13.2" - "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5": version "7.4.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.5.tgz#582bb531f5f9dc67d2fcb682979894f75e253f12" @@ -1323,6 +1282,20 @@ dependencies: regenerator-runtime "^0.13.2" +"@babel/runtime@^7.4.2": + version "7.4.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.3.tgz#79888e452034223ad9609187a0ad1fe0d2ad4bdc" + integrity sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA== + dependencies: + regenerator-runtime "^0.13.2" + +"@babel/runtime@^7.5.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.3.tgz#0811944f73a6c926bb2ad35e918dcc1bfab279f1" + integrity sha512-fVHx1rzEmwB130VTkLnxR+HmxcTjGzH12LYQcFFoBwakMd3aOMD4OsRN7tGG/UOYE2ektgFrS8uACAoRk1CY0w== + dependencies: + regenerator-runtime "^0.13.2" + "@babel/runtime@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132" @@ -1358,6 +1331,15 @@ "@babel/parser" "^7.6.0" "@babel/types" "^7.6.0" +"@babel/template@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8" + integrity sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/parser" "^7.8.3" + "@babel/types" "^7.8.3" + "@babel/traverse@7.0.0-beta.51": version "7.0.0-beta.51" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.51.tgz#981daf2cec347a6231d3aa1d9e1803b03aaaa4a8" @@ -1419,6 +1401,21 @@ globals "^11.1.0" lodash "^4.17.13" +"@babel/traverse@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.3.tgz#a826215b011c9b4f73f3a893afbc05151358bf9a" + integrity sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.3" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.8.3" + "@babel/types" "^7.8.3" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + "@babel/types@7.0.0-beta.51": version "7.0.0-beta.51" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.51.tgz#d802b7b543b5836c778aa691797abf00f3d97ea9" @@ -1455,20 +1452,47 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" + integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@chromaui/localtunnel@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@chromaui/localtunnel/-/localtunnel-1.10.1.tgz#34da7dab7055a16b1b9034a9eb7e3054ebec4b98" + integrity sha512-LXhAogVc9SOQ45+mtk2mhcQxW4bE8aadfx9WbDzuDlBXcDgDMFBaxOmd5VYsPxQYA+cLFkKeuKOpROzsZSEySA== + dependencies: + axios "0.19.0" + debug "^3.0.1" + openurl "1.1.1" + yargs "6.6.0" + +"@cnakazawa/watch@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef" + integrity sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA== + dependencies: + exec-sh "^0.3.2" + minimist "^1.2.0" + "@download/blockies@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@download/blockies/-/blockies-1.0.3.tgz#9aea770f9de72f3f947f1b3a53ee1e92f8dc4a68" integrity sha512-iGDh2M6pFuXg9kyW+U//963LKylSLFpLG5hZvUppCjhkiDwsYquQPyamxCQlLASYySS3gGKAki2eWG9qIHKCew== -"@emotion/cache@^10.0.17": - version "10.0.19" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.19.tgz#d258d94d9c707dcadaf1558def968b86bb87ad71" - integrity sha512-BoiLlk4vEsGBg2dAqGSJu0vJl/PgVtCYLBFJaEO8RmQzPugXewQCXZJNXTDFaRlfCs0W+quesayav4fvaif5WQ== +"@emotion/cache@^10.0.27": + version "10.0.27" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.27.tgz#7895db204e2c1a991ae33d51262a3a44f6737303" + integrity sha512-Zp8BEpbMunFsTcqAK4D7YTm3MvCp1SekflSLJH8lze2fCcSZ/yMkXHo8kb3t1/1Tdd3hAqf3Fb7z9VZ+FMiC9w== dependencies: - "@emotion/sheet" "0.9.3" - "@emotion/stylis" "0.8.4" - "@emotion/utils" "0.11.2" - "@emotion/weak-memoize" "0.2.4" + "@emotion/sheet" "0.9.4" + "@emotion/stylis" "0.8.5" + "@emotion/utils" "0.11.3" + "@emotion/weak-memoize" "0.2.5" "@emotion/cache@^10.0.9": version "10.0.9" @@ -1480,17 +1504,17 @@ "@emotion/utils" "0.11.1" "@emotion/weak-memoize" "0.2.2" -"@emotion/core@^10.0.14": - version "10.0.22" - resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.22.tgz#2ac7bcf9b99a1979ab5b0a876fbf37ab0688b177" - integrity sha512-7eoP6KQVUyOjAkE6y4fdlxbZRA4ILs7dqkkm6oZUJmihtHv0UBq98VgPirq9T8F9K2gKu0J/au/TpKryKMinaA== +"@emotion/core@^10.0.20": + version "10.0.27" + resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.27.tgz#7c3f78be681ab2273f3bf11ca3e2edc4a9dd1fdc" + integrity sha512-XbD5R36pVbohQMnKfajHv43g8EbN4NHdF6Zh9zg/C0nr0jqwOw3gYnC07Xj3yG43OYSRyrGsoQ5qPwc8ycvLZw== dependencies: "@babel/runtime" "^7.5.5" - "@emotion/cache" "^10.0.17" - "@emotion/css" "^10.0.22" - "@emotion/serialize" "^0.11.12" - "@emotion/sheet" "0.9.3" - "@emotion/utils" "0.11.2" + "@emotion/cache" "^10.0.27" + "@emotion/css" "^10.0.27" + "@emotion/serialize" "^0.11.15" + "@emotion/sheet" "0.9.4" + "@emotion/utils" "0.11.3" "@emotion/core@^10.0.9": version "10.0.10" @@ -1503,14 +1527,14 @@ "@emotion/sheet" "0.9.2" "@emotion/utils" "0.11.1" -"@emotion/css@^10.0.22": - version "10.0.22" - resolved "https://registry.yarnpkg.com/@emotion/css/-/css-10.0.22.tgz#37b1abb6826759fe8ac0af0ac0034d27de6d1793" - integrity sha512-8phfa5mC/OadBTmGpMpwykIVH0gFCbUoO684LUkyixPq4F1Wwri7fK5Xlm8lURNBrd2TuvTbPUGxFsGxF9UacA== +"@emotion/css@^10.0.27": + version "10.0.27" + resolved "https://registry.yarnpkg.com/@emotion/css/-/css-10.0.27.tgz#3a7458198fbbebb53b01b2b87f64e5e21241e14c" + integrity sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw== dependencies: - "@emotion/serialize" "^0.11.12" - "@emotion/utils" "0.11.2" - babel-plugin-emotion "^10.0.22" + "@emotion/serialize" "^0.11.15" + "@emotion/utils" "0.11.3" + babel-plugin-emotion "^10.0.27" "@emotion/css@^10.0.9": version "10.0.9" @@ -1526,44 +1550,37 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.1.tgz#9833722341379fb7d67f06a4b00ab3c37913da53" integrity sha512-OYpa/Sg+2GDX+jibUfpZVn1YqSVRpYmTLF2eyAfrFTIJSbwyIrc+YscayoykvaOME/wV4BV0Sa0yqdMrgse6mA== -"@emotion/hash@0.7.3": - version "0.7.3" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.3.tgz#a166882c81c0c6040975dd30df24fae8549bd96f" - integrity sha512-14ZVlsB9akwvydAdaEnVnvqu6J2P6ySv39hYyl/aoB6w/V+bXX0tay8cF6paqbgZsN2n5Xh15uF4pE+GvE+itw== - -"@emotion/is-prop-valid@0.7.3": - version "0.7.3" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.7.3.tgz#a6bf4fa5387cbba59d44e698a4680f481a8da6cc" - integrity sha512-uxJqm/sqwXw3YPA5GXX365OBcJGFtxUVkB6WyezqFHlNe9jqUWH5ur2O2M8dGBz61kn1g3ZBlzUunFQXQIClhA== - dependencies: - "@emotion/memoize" "0.7.1" +"@emotion/hash@0.7.4": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.4.tgz#f14932887422c9056b15a8d222a9074a7dfa2831" + integrity sha512-fxfMSBMX3tlIbKUdtGKxqB1fyrH6gVrX39Gsv3y8lRYKUqlgDt3UMqQyGnR1bQMa2B8aGnhLZokZgg8vT0Le+A== -"@emotion/is-prop-valid@0.8.5": - version "0.8.5" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.5.tgz#2dda0791f0eafa12b7a0a5b39858405cc7bde983" - integrity sha512-6ZODuZSFofbxSbcxwsFz+6ioPjb0ISJRRPLZ+WIbjcU2IMU0Io+RGQjjaTgOvNQl007KICBm7zXQaYQEC1r6Bg== +"@emotion/is-prop-valid@0.8.6": + version "0.8.6" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.6.tgz#4757646f0a58e9dec614c47c838e7147d88c263c" + integrity sha512-mnZMho3Sq8BfzkYYRVc8ilQTnc8U02Ytp6J1AwM6taQStZ3AhsEJBX2LzhA/LJirNCwM2VtHL3VFIZ+sNJUgUQ== dependencies: - "@emotion/memoize" "0.7.3" + "@emotion/memoize" "0.7.4" "@emotion/memoize@0.7.1": version "0.7.1" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.1.tgz#e93c13942592cf5ef01aa8297444dc192beee52f" integrity sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg== -"@emotion/memoize@0.7.3": - version "0.7.3" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.3.tgz#5b6b1c11d6a6dddf1f2fc996f74cf3b219644d78" - integrity sha512-2Md9mH6mvo+ygq1trTeVp2uzAKwE2P7In0cRpD/M9Q70aH8L+rxMLbb3JCN2JoSWsV2O+DdFjfbbXoMoLBczow== - -"@emotion/serialize@^0.11.12", "@emotion/serialize@^0.11.14": - version "0.11.14" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.14.tgz#56a6d8d04d837cc5b0126788b2134c51353c6488" - integrity sha512-6hTsySIuQTbDbv00AnUO6O6Xafdwo5GswRlMZ5hHqiFx+4pZ7uGWXUQFW46Kc2taGhP89uXMXn/lWQkdyTosPA== - dependencies: - "@emotion/hash" "0.7.3" - "@emotion/memoize" "0.7.3" - "@emotion/unitless" "0.7.4" - "@emotion/utils" "0.11.2" +"@emotion/memoize@0.7.4": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" + integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== + +"@emotion/serialize@^0.11.15": + version "0.11.15" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.15.tgz#9a0f5873fb458d87d4f23e034413c12ed60a705a" + integrity sha512-YE+qnrmGwyR+XB5j7Bi+0GT1JWsdcjM/d4POu+TXkcnrRs4RFCCsi3d/Ebf+wSStHqAlTT2+dfd+b9N9EO2KBg== + dependencies: + "@emotion/hash" "0.7.4" + "@emotion/memoize" "0.7.4" + "@emotion/unitless" "0.7.5" + "@emotion/utils" "0.11.3" csstype "^2.5.7" "@emotion/serialize@^0.11.6": @@ -1582,86 +1599,68 @@ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.2.tgz#74e5c6b5e489a1ba30ab246ab5eedd96916487c4" integrity sha512-pVBLzIbC/QCHDKJF2E82V2H/W/B004mDFQZiyo/MSR+VC4pV5JLG0TF/zgQDFvP3fZL/5RTPGEmXlYJBMUuJ+A== -"@emotion/sheet@0.9.3": - version "0.9.3" - resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.3.tgz#689f135ecf87d3c650ed0c4f5ddcbe579883564a" - integrity sha512-c3Q6V7Df7jfwSq5AzQWbXHa5soeE4F5cbqi40xn0CzXxWW9/6Mxq48WJEtqfWzbZtW9odZdnRAkwCQwN12ob4A== - -"@emotion/styled-base@^10.0.10": - version "10.0.10" - resolved "https://registry.yarnpkg.com/@emotion/styled-base/-/styled-base-10.0.10.tgz#ffb811295c9dcd9b3c12bf93301d7d8bcb02e6f4" - integrity sha512-uZwKrBfcH7jCRAQi5ZxsEGIZ+1Zr9/lof4TMsIolC0LSwpnWkQ+JRJLy+p4ZyATee9SdmyCV0sG/VTngVSnrpA== - dependencies: - "@emotion/is-prop-valid" "0.7.3" - "@emotion/serialize" "^0.11.6" - "@emotion/utils" "0.11.1" - object-assign "^4.1.1" +"@emotion/sheet@0.9.4": + version "0.9.4" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.4.tgz#894374bea39ec30f489bbfc3438192b9774d32e5" + integrity sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA== -"@emotion/styled-base@^10.0.23": - version "10.0.24" - resolved "https://registry.yarnpkg.com/@emotion/styled-base/-/styled-base-10.0.24.tgz#9497efd8902dfeddee89d24b0eeb26b0665bfe8b" - integrity sha512-AnBImerf0h4dGAJVo0p0VE8KoAns71F28ErGFK474zbNAHX6yqSWQUasb+1jvg/VPwZjCp19+tAr6oOB0pwmLQ== +"@emotion/styled-base@^10.0.27": + version "10.0.27" + resolved "https://registry.yarnpkg.com/@emotion/styled-base/-/styled-base-10.0.27.tgz#d9efa307ae4e938fcc4d0596b40b7e8bc10f7c7c" + integrity sha512-ufHM/HhE3nr309hJG9jxuFt71r6aHn7p+bwXduFxcwPFEfBIqvmZUMtZ9YxIsY61PVwK3bp4G1XhaCzy9smVvw== dependencies: "@babel/runtime" "^7.5.5" - "@emotion/is-prop-valid" "0.8.5" - "@emotion/serialize" "^0.11.14" - "@emotion/utils" "0.11.2" - -"@emotion/styled@^10.0.14": - version "10.0.23" - resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-10.0.23.tgz#2f8279bd59b99d82deade76d1046249ddfab7c1b" - integrity sha512-gNr04eqBQ2iYUx8wFLZDfm3N8/QUOODu/ReDXa693uyQGy2OqA+IhPJk+kA7id8aOfwAsMuvZ0pJImEXXKtaVQ== - dependencies: - "@emotion/styled-base" "^10.0.23" - babel-plugin-emotion "^10.0.23" + "@emotion/is-prop-valid" "0.8.6" + "@emotion/serialize" "^0.11.15" + "@emotion/utils" "0.11.3" -"@emotion/styled@^10.0.7": - version "10.0.11" - resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-10.0.11.tgz#f749ca95bfe398b3e511b65ea14b16984f049e6d" - integrity sha512-c/M/JJHTQuqdY9viSZD41ccCJDe07/VMrj+JgOcyb8uDnRAr+3cCQ03tyrgl72bQD0YWcjXHhpA7Ja9S3+vuRw== +"@emotion/styled@^10.0.17": + version "10.0.27" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-10.0.27.tgz#12cb67e91f7ad7431e1875b1d83a94b814133eaf" + integrity sha512-iK/8Sh7+NLJzyp9a5+vIQIXTYxfT4yB/OJbjzQanB2RZpvmzBQOHZWhpAMZWYEKRNNbsD6WfBw5sVWkb6WzS/Q== dependencies: - "@emotion/styled-base" "^10.0.10" - babel-plugin-emotion "^10.0.9" + "@emotion/styled-base" "^10.0.27" + babel-plugin-emotion "^10.0.27" "@emotion/stylis@0.8.3": version "0.8.3" resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.3.tgz#3ca7e9bcb31b3cb4afbaeb66156d86ee85e23246" integrity sha512-M3nMfJ6ndJMYloSIbYEBq6G3eqoYD41BpDOxreE8j0cb4fzz/5qvmqU9Mb2hzsXcCnIlGlWhS03PCzVGvTAe0Q== -"@emotion/stylis@0.8.4": - version "0.8.4" - resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.4.tgz#6c51afdf1dd0d73666ba09d2eb6c25c220d6fe4c" - integrity sha512-TLmkCVm8f8gH0oLv+HWKiu7e8xmBIaokhxcEKPh1m8pXiV/akCiq50FvYgOwY42rjejck8nsdQxZlXZ7pmyBUQ== +"@emotion/stylis@0.8.5": + version "0.8.5" + resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" + integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== "@emotion/unitless@0.7.3": version "0.7.3" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.3.tgz#6310a047f12d21a1036fb031317219892440416f" integrity sha512-4zAPlpDEh2VwXswwr/t8xGNDGg8RQiPxtxZ3qQEXyQsBV39ptTdESCjuBvGze1nLMVrxmTIKmnO/nAV8Tqjjzg== -"@emotion/unitless@0.7.4": - version "0.7.4" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.4.tgz#a87b4b04e5ae14a88d48ebef15015f6b7d1f5677" - integrity sha512-kBa+cDHOR9jpRJ+kcGMsysrls0leukrm68DmFQoMIWQcXdr2cZvyvypWuGYT7U+9kAExUE7+T7r6G3C3A6L8MQ== +"@emotion/unitless@0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" + integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== "@emotion/utils@0.11.1": version "0.11.1" resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.1.tgz#8529b7412a6eb4b48bdf6e720cc1b8e6e1e17628" integrity sha512-8M3VN0hetwhsJ8dH8VkVy7xo5/1VoBsDOk/T4SJOeXwTO1c4uIqVNx2qyecLFnnUWD5vvUqHQ1gASSeUN6zcTg== -"@emotion/utils@0.11.2": - version "0.11.2" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.2.tgz#713056bfdffb396b0a14f1c8f18e7b4d0d200183" - integrity sha512-UHX2XklLl3sIaP6oiMmlVzT0J+2ATTVpf0dHQVyPJHTkOITvXfaSqnRk6mdDhV9pR8T/tHc3cex78IKXssmzrA== +"@emotion/utils@0.11.3": + version "0.11.3" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.3.tgz#a759863867befa7e583400d322652a3f44820924" + integrity sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw== "@emotion/weak-memoize@0.2.2": version "0.2.2" resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.2.tgz#63985d3d8b02530e0869962f4da09142ee8e200e" integrity sha512-n/VQ4mbfr81aqkx/XmVicOLjviMuy02eenSdJY33SVA7S2J42EU0P1H0mOogfYedb3wXA0d/LVtBrgTSm04WEA== -"@emotion/weak-memoize@0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.4.tgz#622a72bebd1e3f48d921563b4b60a762295a81fc" - integrity sha512-6PYY5DVdAY1ifaQW6XYTnOMihmBVT27elqSjEoodchsGjzYlEsTQMcEhSud99kVawatyTZRTiVkJ/c6lwbQ7nA== +"@emotion/weak-memoize@0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" + integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== "@gulp-sourcemaps/identity-map@1.X": version "1.0.1" @@ -1964,6 +1963,154 @@ resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw== +"@jest/console@^24.7.1", "@jest/console@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0" + integrity sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ== + dependencies: + "@jest/source-map" "^24.9.0" + chalk "^2.0.1" + slash "^2.0.0" + +"@jest/core@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.9.0.tgz#2ceccd0b93181f9c4850e74f2a9ad43d351369c4" + integrity sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A== + dependencies: + "@jest/console" "^24.7.1" + "@jest/reporters" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/transform" "^24.9.0" + "@jest/types" "^24.9.0" + ansi-escapes "^3.0.0" + chalk "^2.0.1" + exit "^0.1.2" + graceful-fs "^4.1.15" + jest-changed-files "^24.9.0" + jest-config "^24.9.0" + jest-haste-map "^24.9.0" + jest-message-util "^24.9.0" + jest-regex-util "^24.3.0" + jest-resolve "^24.9.0" + jest-resolve-dependencies "^24.9.0" + jest-runner "^24.9.0" + jest-runtime "^24.9.0" + jest-snapshot "^24.9.0" + jest-util "^24.9.0" + jest-validate "^24.9.0" + jest-watcher "^24.9.0" + micromatch "^3.1.10" + p-each-series "^1.0.0" + realpath-native "^1.1.0" + rimraf "^2.5.4" + slash "^2.0.0" + strip-ansi "^5.0.0" + +"@jest/environment@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.9.0.tgz#21e3afa2d65c0586cbd6cbefe208bafade44ab18" + integrity sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ== + dependencies: + "@jest/fake-timers" "^24.9.0" + "@jest/transform" "^24.9.0" + "@jest/types" "^24.9.0" + jest-mock "^24.9.0" + +"@jest/fake-timers@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.9.0.tgz#ba3e6bf0eecd09a636049896434d306636540c93" + integrity sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A== + dependencies: + "@jest/types" "^24.9.0" + jest-message-util "^24.9.0" + jest-mock "^24.9.0" + +"@jest/reporters@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.9.0.tgz#86660eff8e2b9661d042a8e98a028b8d631a5b43" + integrity sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw== + dependencies: + "@jest/environment" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/transform" "^24.9.0" + "@jest/types" "^24.9.0" + chalk "^2.0.1" + exit "^0.1.2" + glob "^7.1.2" + istanbul-lib-coverage "^2.0.2" + istanbul-lib-instrument "^3.0.1" + istanbul-lib-report "^2.0.4" + istanbul-lib-source-maps "^3.0.1" + istanbul-reports "^2.2.6" + jest-haste-map "^24.9.0" + jest-resolve "^24.9.0" + jest-runtime "^24.9.0" + jest-util "^24.9.0" + jest-worker "^24.6.0" + node-notifier "^5.4.2" + slash "^2.0.0" + source-map "^0.6.0" + string-length "^2.0.0" + +"@jest/source-map@^24.3.0", "@jest/source-map@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.9.0.tgz#0e263a94430be4b41da683ccc1e6bffe2a191714" + integrity sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.1.15" + source-map "^0.6.0" + +"@jest/test-result@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.9.0.tgz#11796e8aa9dbf88ea025757b3152595ad06ba0ca" + integrity sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA== + dependencies: + "@jest/console" "^24.9.0" + "@jest/types" "^24.9.0" + "@types/istanbul-lib-coverage" "^2.0.0" + +"@jest/test-sequencer@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz#f8f334f35b625a4f2f355f2fe7e6036dad2e6b31" + integrity sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A== + dependencies: + "@jest/test-result" "^24.9.0" + jest-haste-map "^24.9.0" + jest-runner "^24.9.0" + jest-runtime "^24.9.0" + +"@jest/transform@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.9.0.tgz#4ae2768b296553fadab09e9ec119543c90b16c56" + integrity sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^24.9.0" + babel-plugin-istanbul "^5.1.0" + chalk "^2.0.1" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.1.15" + jest-haste-map "^24.9.0" + jest-regex-util "^24.9.0" + jest-util "^24.9.0" + micromatch "^3.1.10" + pirates "^4.0.1" + realpath-native "^1.1.0" + slash "^2.0.0" + source-map "^0.6.1" + write-file-atomic "2.4.1" + +"@jest/types@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59" + integrity sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^1.1.1" + "@types/yargs" "^13.0.0" + "@material-ui/core@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-1.0.0.tgz#857b871038bb300f2d25594ce0cd250be944e71b" @@ -2175,58 +2322,37 @@ resolved "https://registry.yarnpkg.com/@stablelib/utf8/-/utf8-0.10.1.tgz#eecf54884da7b2bee235e3c70efb8cd5c07ba5bd" integrity sha512-+uM1YZ4MhBC82vt99prF7DXNGqhYmJ9cQ3p5qNowMNkkzn9OWEkqBvguBW3ChAt7JvqZ3SD5HJOfc6YgnfMTHw== -"@storybook/addon-actions@^5.2.6": - version "5.2.6" - resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-5.2.6.tgz#4fe411fc3bdb1d44058f23fbc8eb8d1bac29d521" - integrity sha512-CwTJPqe3NcEU7oqS5KoiCX9FXYmI2Dyp1Sh6r90JmXZ8B49ZXm6BDLX0gS3TooD6/AcdU8xdBcSvN0CkxQ5QGA== - dependencies: - "@storybook/addons" "5.2.6" - "@storybook/api" "5.2.6" - "@storybook/client-api" "5.2.6" - "@storybook/components" "5.2.6" - "@storybook/core-events" "5.2.6" - "@storybook/theming" "5.2.6" +"@storybook/addon-actions@^5.2.8": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-5.3.9.tgz#fc8b1d912c87f418e69c2b52031d29465bb4867b" + integrity sha512-saTxUXnu8O8pE1G2yPDY8NbvK+qZS27HcoeN3HzU/ooAQDffMTnreU4C8LU6/yKAx4KBDvXS4oyiBguOlQfIgg== + dependencies: + "@storybook/addons" "5.3.9" + "@storybook/api" "5.3.9" + "@storybook/client-api" "5.3.9" + "@storybook/components" "5.3.9" + "@storybook/core-events" "5.3.9" + "@storybook/theming" "5.3.9" core-js "^3.0.1" fast-deep-equal "^2.0.1" global "^4.3.2" polished "^3.3.1" prop-types "^15.7.2" react "^16.8.3" - react-inspector "^3.0.2" + react-inspector "^4.0.0" uuid "^3.3.2" -"@storybook/addon-info@^5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@storybook/addon-info/-/addon-info-5.1.1.tgz#17230d82a5f3aaa3a74c35806f63ff1ce24e01fa" - integrity sha512-E1uEx/+Erux5I/Ym5qans0oM1Dq3zA2fPROnxAp4N8LzqNTNZ/MoNDlxK0WWdNxvlotASu6McV1OSGIXjPinkw== - dependencies: - "@storybook/addons" "5.1.1" - "@storybook/client-logger" "5.1.1" - "@storybook/components" "5.1.1" - "@storybook/theming" "5.1.1" - core-js "^3.0.1" - global "^4.3.2" - marksy "^7.0.0" - nested-object-assign "^1.0.3" - prop-types "^15.7.2" - react "^16.8.4" - react-addons-create-fragment "^15.6.2" - react-element-to-jsx-string "^14.0.2" - react-is "^16.8.4" - react-lifecycles-compat "^3.0.4" - util-deprecate "^1.0.2" - -"@storybook/addon-knobs@^5.1.1": - version "5.2.8" - resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-5.2.8.tgz#e0d03823969921a0da57a329376d03066dd749ee" - integrity sha512-5SAMJj+0pbhCiyNkKjkUxEbM9L/wrOE4HTvM7gvm902fULuKZklb3wV8iiUNRfIPCs6VhmmIhPzXICGjhW5xIg== - dependencies: - "@storybook/addons" "5.2.8" - "@storybook/api" "5.2.8" - "@storybook/client-api" "5.2.8" - "@storybook/components" "5.2.8" - "@storybook/core-events" "5.2.8" - "@storybook/theming" "5.2.8" +"@storybook/addon-knobs@^5.2.8": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-5.3.9.tgz#b51be01731dd31ad1b883276acdbeabedc0b7095" + integrity sha512-blMiksvApq4lGiZM1A8FpwnIOXC0PsBXja0LkWQDDHN+snREzjZV85XLrYdz688RhN/7MTXZXMgsvRMSug/r3g== + dependencies: + "@storybook/addons" "5.3.9" + "@storybook/api" "5.3.9" + "@storybook/client-api" "5.3.9" + "@storybook/components" "5.3.9" + "@storybook/core-events" "5.3.9" + "@storybook/theming" "5.3.9" "@types/react-color" "^3.0.1" copy-to-clipboard "^3.0.8" core-js "^3.0.1" @@ -2238,102 +2364,34 @@ qs "^6.6.0" react-color "^2.17.0" react-lifecycles-compat "^3.0.4" - react-select "^3.0.0" - -"@storybook/addons@5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.1.1.tgz#6457c4f60ae0cc49ad4919c45272b1cc181b217c" - integrity sha512-k7EhHudEkVkv43ytaK3dh+51qWT3Mww3Ezz/uYffLDYIu3ya7KpleWnbdAJ7Zrd4Htc2Jl5RDmm8tz+JFSYtcw== - dependencies: - "@storybook/api" "5.1.1" - "@storybook/channels" "5.1.1" - "@storybook/client-logger" "5.1.1" - core-js "^3.0.1" - global "^4.3.2" - util-deprecate "^1.0.2" + react-select "^3.0.8" -"@storybook/addons@5.2.6": - version "5.2.6" - resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.2.6.tgz#c1278137acb3502e068b0b0d07a8371c607e9c02" - integrity sha512-5MF64lsAhIEMxTbVpYROz5Wez595iwSw45yXyP8gWt12d+EmFO5tdy7cYJCxcMuVhDfaCI78tFqS9orr1atVyA== +"@storybook/addons@5.3.9": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.3.9.tgz#f2492de356e0cd38e3da357f4dafa058a4756e36" + integrity sha512-LrlO6nQ4S6yroFuG9Pn1rXhg0AjT/jx7UKZjZTJNqo4ZdPy88QhQO0ClbOVL+KhUiY773zEBYIk0BvwA3WYtSQ== dependencies: - "@storybook/api" "5.2.6" - "@storybook/channels" "5.2.6" - "@storybook/client-logger" "5.2.6" - "@storybook/core-events" "5.2.6" + "@storybook/api" "5.3.9" + "@storybook/channels" "5.3.9" + "@storybook/client-logger" "5.3.9" + "@storybook/core-events" "5.3.9" core-js "^3.0.1" global "^4.3.2" util-deprecate "^1.0.2" -"@storybook/addons@5.2.8": - version "5.2.8" - resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.2.8.tgz#f8bf8bd555b7a69fb1e9a52ab8cdb96384d931ff" - integrity sha512-yAo1N5z/45bNIQP8SD+HVTr7X898bYAtz1EZBrQ6zD8bGamzA2Br06rOLL9xXw29eQhsaVnPlqgDwCS1sTC7aQ== +"@storybook/api@5.3.9": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/api/-/api-5.3.9.tgz#090119c6fd4082442e926a434d3d171535ec6784" + integrity sha512-ix6WS880K5C3H4wjEN0IKqIlVNV0f7zHgvyRf8maL1UFEya5wkBkZg9REDOiCH0tSByzRN73NmPdII3Q1FoAvA== dependencies: - "@storybook/api" "5.2.8" - "@storybook/channels" "5.2.8" - "@storybook/client-logger" "5.2.8" - "@storybook/core-events" "5.2.8" - core-js "^3.0.1" - global "^4.3.2" - util-deprecate "^1.0.2" - -"@storybook/api@5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@storybook/api/-/api-5.1.1.tgz#9f758fa694644a76a70b9d522d340ddafa9892af" - integrity sha512-/TuaqShnlr41guH5oH83cCOCT1JcvAhRrfxjpGjBYMxogI1/gi/07hcPsfNXIwpbH43zLvQ+sLIsRWcNeIaZGQ== - dependencies: - "@storybook/channels" "5.1.1" - "@storybook/client-logger" "5.1.1" - "@storybook/core-events" "5.1.1" - "@storybook/router" "5.1.1" - "@storybook/theming" "5.1.1" - core-js "^3.0.1" - fast-deep-equal "^2.0.1" - global "^4.3.2" - lodash "^4.17.11" - memoizerific "^1.11.3" - prop-types "^15.6.2" - react "^16.7.0" - semver "^6.0.0" - shallow-equal "^1.1.0" - store2 "^2.7.1" - telejson "^2.2.1" - util-deprecate "^1.0.2" - -"@storybook/api@5.2.6": - version "5.2.6" - resolved "https://registry.yarnpkg.com/@storybook/api/-/api-5.2.6.tgz#43d3c20b90e585e6c94b36e29845d39704ae2135" - integrity sha512-X/di44/SAL68mD6RHTX2qdWwhjRW6BgcfPtu0dMd38ErB3AfsfP4BITXs6kFOeSM8kWiaQoyuw0pOBzA8vlYug== - dependencies: - "@storybook/channels" "5.2.6" - "@storybook/client-logger" "5.2.6" - "@storybook/core-events" "5.2.6" - "@storybook/router" "5.2.6" - "@storybook/theming" "5.2.6" - core-js "^3.0.1" - fast-deep-equal "^2.0.1" - global "^4.3.2" - lodash "^4.17.15" - memoizerific "^1.11.3" - prop-types "^15.6.2" - react "^16.8.3" - semver "^6.0.0" - shallow-equal "^1.1.0" - store2 "^2.7.1" - telejson "^3.0.2" - util-deprecate "^1.0.2" - -"@storybook/api@5.2.8": - version "5.2.8" - resolved "https://registry.yarnpkg.com/@storybook/api/-/api-5.2.8.tgz#21f03df8041114eb929bd10b570a17f266568b7f" - integrity sha512-rFrPtTFDIPQoicLwq1AVsOvZNTUKnjD1w/NX1kKcyuWLL9BcOkU3YNLBlliGBg2JX/yS+fJKMyKk4NMzNBCZCg== - dependencies: - "@storybook/channels" "5.2.8" - "@storybook/client-logger" "5.2.8" - "@storybook/core-events" "5.2.8" - "@storybook/router" "5.2.8" - "@storybook/theming" "5.2.8" + "@reach/router" "^1.2.1" + "@storybook/channels" "5.3.9" + "@storybook/client-logger" "5.3.9" + "@storybook/core-events" "5.3.9" + "@storybook/csf" "0.0.1" + "@storybook/router" "5.3.9" + "@storybook/theming" "5.3.9" + "@types/reach__router" "^1.2.3" core-js "^3.0.1" fast-deep-equal "^2.0.1" global "^4.3.2" @@ -2344,114 +2402,39 @@ semver "^6.0.0" shallow-equal "^1.1.0" store2 "^2.7.1" - telejson "^3.0.2" + telejson "^3.2.0" util-deprecate "^1.0.2" -"@storybook/channel-postmessage@5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.1.1.tgz#e322cbcdd9fbef48aadb93c52aa29cb7e1e7aa5c" - integrity sha512-kFsLv5Sbgbp431d3aNgrPioGE+oCtXlUVSFh9711ZulARfqgAZMDDWxVnTaiuHBIf5yjfpDLn9ZqohheZCKScg== - dependencies: - "@storybook/channels" "5.1.1" - "@storybook/client-logger" "5.1.1" - core-js "^3.0.1" - global "^4.3.2" - telejson "^2.2.1" - -"@storybook/channel-postmessage@5.2.6": - version "5.2.6" - resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.2.6.tgz#60aaef0e80300c9812a571ca3ce0f28e2c404f04" - integrity sha512-y+63wWiEc/Q4s4MZ3KJ//5A8j5VLufxuLvPxwv9FuS4z8lmN0fqeGJn857qIlFGbZhzsQaoRdmfsCQpBBgUneg== - dependencies: - "@storybook/channels" "5.2.6" - "@storybook/client-logger" "5.2.6" - core-js "^3.0.1" - global "^4.3.2" - telejson "^3.0.2" - -"@storybook/channel-postmessage@5.2.8": - version "5.2.8" - resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.2.8.tgz#7a84869ce0fc270c3b5dcd7fa4ed798b6055816f" - integrity sha512-RS3iDW1kpfODN+kBq3youn+KtLqHslZ4m7mTlOL80BUHKb4YkrA1lVkzpy1kVMWBU523pyDVQUVXr+M8y3iVug== +"@storybook/channel-postmessage@5.3.9": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.3.9.tgz#3846ae7ea5bc2fe36b1ef64fbc215f480cf8a189" + integrity sha512-gMzPwxTsN0Xgpd01ERlC2lpJzzeOMgP+eSruHh1pwieplL8CEctn8HV1eXrAtF/JtFIXjd4jkoRHAwRptHuJ2w== dependencies: - "@storybook/channels" "5.2.8" - "@storybook/client-logger" "5.2.8" + "@storybook/channels" "5.3.9" + "@storybook/client-logger" "5.3.9" core-js "^3.0.1" global "^4.3.2" - telejson "^3.0.2" - -"@storybook/channels@5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-5.1.1.tgz#a8947a9e1575dcceabf223c31fc3d49fcf69b442" - integrity sha512-IaOEFKdAYCMK5veEFEbauOqNOwD6ro02X50TN91Oz/t2kA1ktkSvBA/0+JjhP9KvkKFQ+fh6TltqpIJHIB4oqw== - dependencies: - core-js "^3.0.1" - -"@storybook/channels@5.2.6": - version "5.2.6" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-5.2.6.tgz#e2837508864dc4d5b5e03f078886f0ce113762ea" - integrity sha512-/UsktYsXuvb1efjVPCEivhh5ywRhm7hl73pQnpJLJHRqyLMM2I5nGPFELTTNuU9yWy7sP9QL5gRqBBPe1sqjZQ== - dependencies: - core-js "^3.0.1" + telejson "^3.2.0" -"@storybook/channels@5.2.8": - version "5.2.8" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-5.2.8.tgz#79a99ad85dcacb688073c22340c5b7d16b801202" - integrity sha512-mFwQec27QSrqcl+IH0xA+4jfoEqC4m1G99LBHt/aTDjLZXclX1A470WqeZCp7Gx4OALpaPEVTaaaKPbiKz4C6w== +"@storybook/channels@5.3.9": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-5.3.9.tgz#7ee8f6e6f4c9465227120d6711805b5e6862107f" + integrity sha512-8JFTDTI4hQyAJPDBgwnK99lye2oyxEheko4vD2Pv5M7LblcFBZJuCRhO5wiBsgHi5eV4srSD9kuBsPkYSxB2Xw== dependencies: core-js "^3.0.1" -"@storybook/client-api@5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.1.1.tgz#a29cc1e78ea15229aa2461a42006e4953b336f5a" - integrity sha512-rCu1kpfM/Jg8rYz2HBD2j+TaZ0twUrZR5EYs5tJve4CBGpMFKbRxu4jLjkVCEkAwTVCT+glEs586+kktVSyOLQ== - dependencies: - "@storybook/addons" "5.1.1" - "@storybook/client-logger" "5.1.1" - "@storybook/core-events" "5.1.1" - "@storybook/router" "5.1.1" - common-tags "^1.8.0" - core-js "^3.0.1" - eventemitter3 "^3.1.0" - global "^4.3.2" - is-plain-object "^3.0.0" - lodash "^4.17.11" - memoizerific "^1.11.3" - qs "^6.6.0" - -"@storybook/client-api@5.2.6": - version "5.2.6" - resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.2.6.tgz#5760cb4302d82ce9210a63f3f55b1e05f04759c1" - integrity sha512-upynf4ER2fkThNnE+mBlfRFFJxTiOh60fho1ODFcBun9BbvRD2wOHLvw7+WigIhb99HM20vk8f2dhv3I5Udzlg== - dependencies: - "@storybook/addons" "5.2.6" - "@storybook/channel-postmessage" "5.2.6" - "@storybook/channels" "5.2.6" - "@storybook/client-logger" "5.2.6" - "@storybook/core-events" "5.2.6" - "@storybook/router" "5.2.6" - common-tags "^1.8.0" - core-js "^3.0.1" - eventemitter3 "^4.0.0" - global "^4.3.2" - is-plain-object "^3.0.0" - lodash "^4.17.15" - memoizerific "^1.11.3" - qs "^6.6.0" - util-deprecate "^1.0.2" - -"@storybook/client-api@5.2.8": - version "5.2.8" - resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.2.8.tgz#1de791f7888442287f848e5f544eb883c5edc0da" - integrity sha512-OCKhZ+2sS3ot0ZV48nD79BWVzvvdMjUFYl0073ps5q+1+TLic1AlNmH0Sb5/9NrYXNV86v3VrM2jUbGsKe1qyw== - dependencies: - "@storybook/addons" "5.2.8" - "@storybook/channel-postmessage" "5.2.8" - "@storybook/channels" "5.2.8" - "@storybook/client-logger" "5.2.8" - "@storybook/core-events" "5.2.8" - "@storybook/router" "5.2.8" - common-tags "^1.8.0" +"@storybook/client-api@5.3.9": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.3.9.tgz#43ae2651bf303e832e97c014fd6c77a523669fd9" + integrity sha512-c2AO8R/CKJfOGCQxWva6te7Fhlbs+6nzBj14rnb+BC6e7zORuozLNugGXTc7w2aR7manI86WFjSWWfzX64Jr3w== + dependencies: + "@storybook/addons" "5.3.9" + "@storybook/channel-postmessage" "5.3.9" + "@storybook/channels" "5.3.9" + "@storybook/client-logger" "5.3.9" + "@storybook/core-events" "5.3.9" + "@storybook/csf" "0.0.1" + "@types/webpack-env" "^1.15.0" core-js "^3.0.1" eventemitter3 "^4.0.0" global "^4.3.2" @@ -2460,89 +2443,28 @@ memoizerific "^1.11.3" qs "^6.6.0" stable "^0.1.8" + ts-dedent "^1.1.0" util-deprecate "^1.0.2" -"@storybook/client-logger@5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-5.1.1.tgz#e62a214a801079e75b4b101afd73cc66c262701d" - integrity sha512-I0j9tGyjQpLC7dKhQuotJzaAl9j6++hJdUT5ieoqVIC4Hya15wIyc63lpa6ugXQLeRpW73x72CTFV8K+132Qow== +"@storybook/client-logger@5.3.9": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-5.3.9.tgz#06654be9caa8d37366270b0426c2d5acb217f504" + integrity sha512-EbA9id/Fk2BZkIWGSICYh+Iu4j7JFRZce4Lp69/MPmHpQk8YKnjL6NdxGsHj/83OFQ9CCbtqNOBzBdtiCy/23w== dependencies: core-js "^3.0.1" -"@storybook/client-logger@5.2.6": - version "5.2.6" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-5.2.6.tgz#cfc4536e9b724b086f7509c2bb34c221016713c9" - integrity sha512-hJvPD267cCwLIRMOISjDH8h9wbwOcXIJip29UlJbU9iMtZtgE+YelmlpmZJvqcDfUiXWWrOh7tP76mj8EAfwIQ== +"@storybook/components@5.3.9": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.3.9.tgz#1fbc688770889ddadb8c603f5a4dbcf987f3eb0f" + integrity sha512-R4xDR3pIYu7yPHex6DG3PPC3ekLgQuG03ZMQEgCfmWdl2wKXcLtEfQPYLRpC59xnQobfR3wqWgqrGchW54HPow== dependencies: - core-js "^3.0.1" - -"@storybook/client-logger@5.2.8": - version "5.2.8" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-5.2.8.tgz#5affe2f9dbbee374721fd2e8729116f5ac39c779" - integrity sha512-+oVSEJdeh7TQ1Bhanb3mCr7fc3Bug3+K79abZ28J45Ub5x4L/ZVClj1xMgUsJs30BZ5FB8vhdgH6TQb0NSxR4A== - dependencies: - core-js "^3.0.1" - -"@storybook/components@5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.1.1.tgz#4ca7343009ebd92cdfb79cfa373628d6f3bb12d0" - integrity sha512-17rqqxant4zqCNxcESLZR0yAhz1mGHDz6THj8fz5rUncEnSrPYIcdvRKIfeao8yDaiK1Bh48jAjSPdfUO8BngA== - dependencies: - "@storybook/client-logger" "5.1.1" - "@storybook/theming" "5.1.1" - core-js "^3.0.1" - global "^4.3.2" - markdown-to-jsx "^6.9.1" - memoizerific "^1.11.3" - polished "^3.3.1" - popper.js "^1.14.7" - prop-types "^15.7.2" - react "^16.8.4" - react-dom "^16.8.4" - react-focus-lock "^1.18.3" - react-helmet-async "^1.0.2" - react-popper-tooltip "^2.8.3" - react-syntax-highlighter "^8.0.1" - react-textarea-autosize "^7.1.0" - recompose "^0.30.0" - simplebar-react "^1.0.0-alpha.6" - -"@storybook/components@5.2.6": - version "5.2.6" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.2.6.tgz#cddb60227720aea7cae34fe782d0370bcdbd4005" - integrity sha512-C7OS90bZ1ZvxlWUZ3B2MPFFggqAtUo7X8DqqS3IwsuDUiK9dD/KS0MwPgOuFDnOTW1R5XqmQd/ylt53w3s/U5g== - dependencies: - "@storybook/client-logger" "5.2.6" - "@storybook/theming" "5.2.6" - "@types/react-syntax-highlighter" "10.1.0" - "@types/react-textarea-autosize" "^4.3.3" - core-js "^3.0.1" - global "^4.3.2" - markdown-to-jsx "^6.9.1" - memoizerific "^1.11.3" - polished "^3.3.1" - popper.js "^1.14.7" - prop-types "^15.7.2" - react "^16.8.3" - react-dom "^16.8.3" - react-focus-lock "^1.18.3" - react-helmet-async "^1.0.2" - react-popper-tooltip "^2.8.3" - react-syntax-highlighter "^8.0.1" - react-textarea-autosize "^7.1.0" - simplebar-react "^1.0.0-alpha.6" - -"@storybook/components@5.2.8": - version "5.2.8" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.2.8.tgz#f5d4a06ba4ba8c700b2d962deae182105b72fb99" - integrity sha512-h9l/LAMaj+emUCOyY/+ETy/S3P0npwQU280J88uL4O9XJALJ72EKfyttBCvMLvpM50E+fAPeDzuYn0t5qzGGxg== - dependencies: - "@storybook/client-logger" "5.2.8" - "@storybook/theming" "5.2.8" - "@types/react-syntax-highlighter" "10.1.0" + "@storybook/client-logger" "5.3.9" + "@storybook/theming" "5.3.9" + "@types/react-syntax-highlighter" "11.0.2" "@types/react-textarea-autosize" "^4.3.3" core-js "^3.0.1" global "^4.3.2" + lodash "^4.17.15" markdown-to-jsx "^6.9.1" memoizerific "^1.11.3" polished "^3.3.1" @@ -2550,266 +2472,228 @@ prop-types "^15.7.2" react "^16.8.3" react-dom "^16.8.3" - react-focus-lock "^1.18.3" + react-focus-lock "^2.1.0" react-helmet-async "^1.0.2" react-popper-tooltip "^2.8.3" - react-syntax-highlighter "^8.0.1" + react-syntax-highlighter "^11.0.2" react-textarea-autosize "^7.1.0" simplebar-react "^1.0.0-alpha.6" + ts-dedent "^1.1.0" -"@storybook/core-events@5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.1.1.tgz#179ca9e49fb7e81c5ed4ce3a8eb93d90003f6478" - integrity sha512-5mxaz4azHkeuZcejwY6NNWFzPrUqn7OnU/rrzgJbxXoKps9Q0p2EmVdD0sh9nLuhVqvOvMdzOiwSerra6aVJiw== - dependencies: - core-js "^3.0.1" - -"@storybook/core-events@5.2.6": - version "5.2.6" - resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.2.6.tgz#34c9aae256e7e5f4a565b81f1e77dda8bccc6752" - integrity sha512-W8kLJ7tc0aAxs11CPUxUOCReocKL4MYGyjTg8qwk0USLzPUb/FUQWmhcm2ilFz6Nz8dXLcKrXdRVYTmiMsgAeg== - dependencies: - core-js "^3.0.1" - -"@storybook/core-events@5.2.8": - version "5.2.8" - resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.2.8.tgz#93fc458ea0820ff1409d268b0fe51abba200f5a4" - integrity sha512-NkQKC5doO/YL9gsO61bqaxgveKktkiJWZ3XyyhL1ZebgnO9wTlrU+i9b5aX73Myk1oxbicQw9KcwDGYk0qFuNQ== +"@storybook/core-events@5.3.9": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.3.9.tgz#3c7fbc20204ae4b937c896ed6281e782cc09c4aa" + integrity sha512-JFnVjOHMnxbArIHEGuVvAcQuwf0l2yUJEsx5zJZ6OkCOFXKGDjqATGNtyZEOhVXTwONIWT6Y6ZTfKZLmdiSksQ== dependencies: core-js "^3.0.1" -"@storybook/core@5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@storybook/core/-/core-5.1.1.tgz#f2697258fe1d7636e08e29206e8551f36f5d99b8" - integrity sha512-09/EcL6Ev6HY1OlzE95CYrsb2U8gPxgvn1l/nQQwwG8XDwd5eQNWzTggCfu+jTdm/JIzfp6k6T1SruZsAX+YXA== +"@storybook/core@5.3.9": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/core/-/core-5.3.9.tgz#a13149714c46788555641124ed4f9fb7359e4550" + integrity sha512-AsyNLlFczEz5wGu92fJA6ioiSkUtK2Qgr+fXNOAFXA/FLhgBIijsNoAvEwkfCs8Koe3xNkbMRE1Tk4WRIl0kCw== dependencies: - "@babel/plugin-proposal-class-properties" "^7.3.3" - "@babel/plugin-proposal-object-rest-spread" "^7.3.2" + "@babel/plugin-proposal-class-properties" "^7.7.0" + "@babel/plugin-proposal-object-rest-spread" "^7.6.2" "@babel/plugin-syntax-dynamic-import" "^7.2.0" "@babel/plugin-transform-react-constant-elements" "^7.2.0" "@babel/preset-env" "^7.4.5" - "@storybook/addons" "5.1.1" - "@storybook/channel-postmessage" "5.1.1" - "@storybook/client-api" "5.1.1" - "@storybook/client-logger" "5.1.1" - "@storybook/core-events" "5.1.1" - "@storybook/node-logger" "5.1.1" - "@storybook/router" "5.1.1" - "@storybook/theming" "5.1.1" - "@storybook/ui" "5.1.1" - airbnb-js-shims "^1 || ^2" - autoprefixer "^9.4.9" + "@storybook/addons" "5.3.9" + "@storybook/channel-postmessage" "5.3.9" + "@storybook/client-api" "5.3.9" + "@storybook/client-logger" "5.3.9" + "@storybook/core-events" "5.3.9" + "@storybook/csf" "0.0.1" + "@storybook/node-logger" "5.3.9" + "@storybook/router" "5.3.9" + "@storybook/theming" "5.3.9" + "@storybook/ui" "5.3.9" + airbnb-js-shims "^2.2.1" + ansi-to-html "^0.6.11" + autoprefixer "^9.7.2" babel-plugin-add-react-displayname "^0.0.5" - babel-plugin-emotion "^10.0.9" - babel-plugin-macros "^2.4.5" + babel-plugin-emotion "^10.0.20" + babel-plugin-macros "^2.7.0" babel-preset-minify "^0.5.0 || 0.6.0-alpha.5" - boxen "^3.0.0" + boxen "^4.1.0" case-sensitive-paths-webpack-plugin "^2.2.0" - chalk "^2.4.2" + chalk "^3.0.0" cli-table3 "0.5.1" - commander "^2.19.0" - common-tags "^1.8.0" + commander "^4.0.1" core-js "^3.0.1" - css-loader "^2.1.1" + corejs-upgrade-webpack-plugin "^2.2.0" + css-loader "^3.0.0" detect-port "^1.3.0" dotenv-webpack "^1.7.0" - ejs "^2.6.1" + ejs "^2.7.4" express "^4.17.0" - file-loader "^3.0.1" + file-loader "^4.2.0" file-system-cache "^1.0.5" find-cache-dir "^3.0.0" + find-up "^4.1.0" fs-extra "^8.0.1" + glob-base "^0.3.0" global "^4.3.2" html-webpack-plugin "^4.0.0-beta.2" - inquirer "^6.2.0" - interpret "^1.2.0" + inquirer "^7.0.0" + interpret "^2.0.0" ip "^1.1.5" - json5 "^2.1.0" - lazy-universal-dotenv "^2.0.0" + json5 "^2.1.1" + lazy-universal-dotenv "^3.0.1" + micromatch "^4.0.2" node-fetch "^2.6.0" - open "^6.1.0" + open "^7.0.0" + pnp-webpack-plugin "1.5.0" postcss-flexbugs-fixes "^4.1.0" postcss-loader "^3.0.0" pretty-hrtime "^1.0.3" qs "^6.6.0" - raw-loader "^2.0.0" + raw-loader "^3.1.0" react-dev-utils "^9.0.0" - regenerator-runtime "^0.12.1" + regenerator-runtime "^0.13.3" resolve "^1.11.0" resolve-from "^5.0.0" semver "^6.0.0" serve-favicon "^2.5.0" shelljs "^0.8.3" - style-loader "^0.23.1" - terser-webpack-plugin "^1.2.4" - url-loader "^1.1.2" + style-loader "^1.0.0" + terser-webpack-plugin "^2.1.2" + ts-dedent "^1.1.0" + unfetch "^4.1.0" + url-loader "^2.0.1" util-deprecate "^1.0.2" - webpack "^4.32.0" + webpack "^4.33.0" webpack-dev-middleware "^3.7.0" webpack-hot-middleware "^2.25.0" + webpack-virtual-modules "^0.2.0" -"@storybook/node-logger@5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-5.1.1.tgz#4874718697c8bc783b606724ce24dd0533ae52a0" - integrity sha512-fQ3scxoc3+v9xU1q4C1UqMtJ8rOXW6j51q7mI8vxSzCauKCSdODp3YvsNeu9FmCohrH1TqZUYsq3y6Tk9oDZrw== +"@storybook/csf@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@storybook/csf/-/csf-0.0.1.tgz#95901507dc02f0bc6f9ac8ee1983e2fc5bb98ce6" + integrity sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw== dependencies: - chalk "^2.4.2" + lodash "^4.17.15" + +"@storybook/node-logger@5.3.9": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-5.3.9.tgz#5de49697b5e2565a4a84bd56244a424368f5e726" + integrity sha512-Uxk7YjlIMkf5Bsyw/EOdlYa4JT3m+FUqb5bV+vtkfzPhzKA9FLdSFEh5OVKct4lG74XxOgaKWJxudINeWKz0qQ== + dependencies: + "@types/npmlog" "^4.1.2" + chalk "^3.0.0" core-js "^3.0.1" npmlog "^4.1.2" pretty-hrtime "^1.0.3" - regenerator-runtime "^0.12.1" + regenerator-runtime "^0.13.3" -"@storybook/react@^5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@storybook/react/-/react-5.1.1.tgz#9041aaec5f7ce606554a321568c248f86b1b92ab" - integrity sha512-6iAwEekEF0MKeVCogyeRHvKNShmHu4LQPqERRKwJnzbmK+Mr9cx4GS0t2lok9QNruNWNdoe8U3zOvlAI0FimBQ== +"@storybook/react@^5.2.8": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/react/-/react-5.3.9.tgz#cf3a954b5d0430c5a3558ea5df305bb70e2af3cd" + integrity sha512-pOc6xw1c83fUnTRcCpIrtLLDKkZUhW3EkNvwYyMHrGXMRcgDETAlpoxBMHXpnbfV7qaAsE/UAVQQ1rRq5pgPBA== dependencies: - "@babel/plugin-transform-react-constant-elements" "^7.2.0" + "@babel/plugin-transform-react-constant-elements" "^7.6.3" "@babel/preset-flow" "^7.0.0" "@babel/preset-react" "^7.0.0" - "@storybook/core" "5.1.1" - "@storybook/node-logger" "5.1.1" + "@storybook/addons" "5.3.9" + "@storybook/core" "5.3.9" + "@storybook/node-logger" "5.3.9" "@svgr/webpack" "^4.0.3" + "@types/webpack-env" "^1.15.0" + babel-plugin-add-react-displayname "^0.0.5" babel-plugin-named-asset-import "^0.3.1" - babel-plugin-react-docgen "^3.0.0" - babel-preset-react-app "^9.0.0" - common-tags "^1.8.0" + babel-plugin-react-docgen "^4.0.0" core-js "^3.0.1" global "^4.3.2" - lodash "^4.17.11" - mini-css-extract-plugin "^0.7.0" + lodash "^4.17.15" + mini-css-extract-plugin "^0.8.0" prop-types "^15.7.2" react-dev-utils "^9.0.0" - regenerator-runtime "^0.12.1" + regenerator-runtime "^0.13.3" semver "^6.0.0" - webpack "^4.28.0" - -"@storybook/router@5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@storybook/router/-/router-5.1.1.tgz#bebdfd8ae8f80f38b91e6df8648afdf9e95660ba" - integrity sha512-w8tREuJG6eav5uqJXqjkmcmymHqJ7HG9kLPqrp60VhliU7tnkcelDZmdIRk49C51AkHYj+s5hLo8HWSy76g21Q== - dependencies: - "@reach/router" "^1.2.1" - core-js "^3.0.1" - global "^4.3.2" - memoizerific "^1.11.3" - qs "^6.6.0" + ts-dedent "^1.1.0" + webpack "^4.33.0" -"@storybook/router@5.2.6": - version "5.2.6" - resolved "https://registry.yarnpkg.com/@storybook/router/-/router-5.2.6.tgz#5180d3785501699283c6c3717986c877f84fead5" - integrity sha512-/FZd3fYg5s2QzOqSIP8UMOSnCIFFIlli/jKlOxvm3WpcpxgwQOY4lfHsLO+r9ThCLs2UvVg2R/HqGrOHqDFU7A== +"@storybook/router@5.3.9": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-5.3.9.tgz#3c6e01f4dced9de8e8c5c314352fdc437f2441c2" + integrity sha512-z7ptxekGRAXP7hU74wdfeFY/ugrHXtpQcAM1X0k4tvbasJpm+fvqAD3yEYQpfEDL7cLlHEFLbOm6xDqtf1e5qQ== dependencies: "@reach/router" "^1.2.1" + "@storybook/csf" "0.0.1" "@types/reach__router" "^1.2.3" core-js "^3.0.1" global "^4.3.2" lodash "^4.17.15" memoizerific "^1.11.3" qs "^6.6.0" + util-deprecate "^1.0.2" -"@storybook/router@5.2.8": - version "5.2.8" - resolved "https://registry.yarnpkg.com/@storybook/router/-/router-5.2.8.tgz#d7de2d401701857c033e28560c30e16512f7f72f" - integrity sha512-wnbyKESUMyv9fwo9W+n4Fev/jXylB8whpjtHrOttjguUOYX1zGSHdwNI66voPetbtVLxUeHyJteJwdyRDSirJg== - dependencies: - "@reach/router" "^1.2.1" - "@types/reach__router" "^1.2.3" - core-js "^3.0.1" - global "^4.3.2" - lodash "^4.17.15" - memoizerific "^1.11.3" - qs "^6.6.0" - -"@storybook/theming@5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.1.1.tgz#605572b650049457dbd102aa5686933ff2202ace" - integrity sha512-70Pf6XZnTI4wniItQxIhAOQjVi7fDRzR3xZUIBC+pEatbKD+OoyFOALwkww5uW66jeWBYC5AhRPEHWo7ylcXUQ== - dependencies: - "@emotion/core" "^10.0.9" - "@emotion/styled" "^10.0.7" - "@storybook/client-logger" "5.1.1" - common-tags "^1.8.0" - core-js "^3.0.1" - deep-object-diff "^1.1.0" - emotion-theming "^10.0.9" - global "^4.3.2" - memoizerific "^1.11.3" - polished "^3.3.1" - prop-types "^15.7.2" - resolve-from "^5.0.0" - -"@storybook/theming@5.2.6": - version "5.2.6" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.2.6.tgz#e04170b3e53dcfc791b2381c8a39192ae88cd291" - integrity sha512-Xa9R/H8DDgmvxsCHloJUJ2d9ZQl80AeqHrL+c/AKNpx05s9lV74DcinusCf0kz72YGUO/Xt1bAjuOvLnAaS8Gw== - dependencies: - "@emotion/core" "^10.0.14" - "@emotion/styled" "^10.0.14" - "@storybook/client-logger" "5.2.6" - common-tags "^1.8.0" - core-js "^3.0.1" - deep-object-diff "^1.1.0" - emotion-theming "^10.0.14" - global "^4.3.2" - memoizerific "^1.11.3" - polished "^3.3.1" - prop-types "^15.7.2" - resolve-from "^5.0.0" - -"@storybook/theming@5.2.8": - version "5.2.8" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.2.8.tgz#a4c9e0e9a5789c1aa71e4fcb7a8ee86efe3dadcf" - integrity sha512-rGb66GkXb0jNJMH8UQ3Ru4FL+m1x0+UdxM8a8HSE/qb1GMv2qOwjVETfAL6nVL9u6ZmrtbhHoero4f6xDwZdRg== +"@storybook/storybook-deployer@^2.8.1": + version "2.8.1" + resolved "https://registry.yarnpkg.com/@storybook/storybook-deployer/-/storybook-deployer-2.8.1.tgz#18018114d58d0c1e584d06b68e57900804469e51" + integrity sha512-tXgD7vpX2nRGpMZr4hzZ3J34Xt3h5sbk3HjnNrBM3bMMWYf5/pMfTtlpIzyzA+ljoI77ZjuFOWZfgPaUTxHeJw== dependencies: - "@emotion/core" "^10.0.14" - "@emotion/styled" "^10.0.14" - "@storybook/client-logger" "5.2.8" - common-tags "^1.8.0" + git-url-parse "^8.1.0" + glob "^7.1.3" + parse-repo "^1.0.4" + shelljs "^0.8.1" + yargs "^11.0.0" + +"@storybook/theming@5.3.9": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.3.9.tgz#caaeea398f9e630394298ccfe8f36a185a289e4f" + integrity sha512-1vG+H1D5j2vcMv54eEKixAoa4UlTuS/dxMZubJfcZYY1PDNtnvQM6B1CE/4EU+qsIYPFQiGFXB4b6gjCFYIFpQ== + dependencies: + "@emotion/core" "^10.0.20" + "@emotion/styled" "^10.0.17" + "@storybook/client-logger" "5.3.9" core-js "^3.0.1" deep-object-diff "^1.1.0" - emotion-theming "^10.0.14" + emotion-theming "^10.0.19" global "^4.3.2" memoizerific "^1.11.3" polished "^3.3.1" prop-types "^15.7.2" resolve-from "^5.0.0" - -"@storybook/ui@5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-5.1.1.tgz#8c285102e2f6bd9978ce13ead7141b066c032d6e" - integrity sha512-hIVH1HWak93p+jvWrlaA8SepLsdRxooqF9AEJkNM7M95f9P0DiwTeeEKmGkI6h2pmIxLSNNgrxZDHQXYGGCVAw== - dependencies: - "@storybook/addons" "5.1.1" - "@storybook/api" "5.1.1" - "@storybook/client-logger" "5.1.1" - "@storybook/components" "5.1.1" - "@storybook/core-events" "5.1.1" - "@storybook/router" "5.1.1" - "@storybook/theming" "5.1.1" + ts-dedent "^1.1.0" + +"@storybook/ui@5.3.9": + version "5.3.9" + resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-5.3.9.tgz#7e084ef93abb90b50ac18d4eea879c1f16b3e741" + integrity sha512-J1ktdeNaEGJmJUNFPGej71eVmjKct9DXaZq88eY3hwjrdfbBIPFrF6kUcAiP4SY900VlwMKuEtUJDcJpz55FYw== + dependencies: + "@emotion/core" "^10.0.20" + "@storybook/addons" "5.3.9" + "@storybook/api" "5.3.9" + "@storybook/channels" "5.3.9" + "@storybook/client-logger" "5.3.9" + "@storybook/components" "5.3.9" + "@storybook/core-events" "5.3.9" + "@storybook/router" "5.3.9" + "@storybook/theming" "5.3.9" copy-to-clipboard "^3.0.8" core-js "^3.0.1" core-js-pure "^3.0.1" + emotion-theming "^10.0.19" fast-deep-equal "^2.0.1" - fuse.js "^3.4.4" + fuse.js "^3.4.6" global "^4.3.2" - lodash "^4.17.11" + lodash "^4.17.15" markdown-to-jsx "^6.9.3" memoizerific "^1.11.3" polished "^3.3.1" prop-types "^15.7.2" qs "^6.6.0" - react "^16.8.4" - react-dom "^16.8.4" - react-draggable "^3.1.1" + react "^16.8.3" + react-dom "^16.8.3" + react-draggable "^4.0.3" react-helmet-async "^1.0.2" - react-hotkeys "2.0.0-pre4" - react-resize-detector "^4.0.5" - recompose "^0.30.0" + react-hotkeys "2.0.0" + react-sizeme "^2.6.7" + regenerator-runtime "^0.13.2" resolve-from "^5.0.0" semver "^6.0.0" store2 "^2.7.1" - telejson "^2.2.1" + telejson "^3.2.0" util-deprecate "^1.0.2" "@svgr/babel-plugin-add-jsx-attribute@^4.2.0": @@ -2924,6 +2808,39 @@ dependencies: defer-to-connect "^1.0.1" +"@types/babel__core@^7.1.0": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.3.tgz#e441ea7df63cd080dfcd02ab199e6d16a735fc30" + integrity sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.1" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.1.tgz#4901767b397e8711aeb99df8d396d7ba7b7f0e04" + integrity sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307" + integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.0.8" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.8.tgz#479a4ee3e291a403a1096106013ec22cf9b64012" + integrity sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw== + dependencies: + "@babel/types" "^7.3.0" + "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" @@ -2958,6 +2875,26 @@ resolved "https://registry.yarnpkg.com/@types/is-function/-/is-function-1.0.0.tgz#1b0b819b1636c7baf0d6785d030d12edf70c3e83" integrity sha512-iTs9HReBu7evG77Q4EC8hZnqRt57irBDkK9nvmHroiOIVwYMQc4IvYvdRgwKfYepunIY7Oh/dBuuld+Gj9uo6w== +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" + integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a" + integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA== + dependencies: + "@types/istanbul-lib-coverage" "*" + "@types/istanbul-lib-report" "*" + "@types/jss@^9.5.3": version "9.5.3" resolved "https://registry.yarnpkg.com/@types/jss/-/jss-9.5.3.tgz#0c106de3fe0b324cd4173fac7dab26c12cda624e" @@ -3001,6 +2938,16 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.48.tgz#e385073561643a9ba6199a1985ffc03530f90781" integrity sha512-c35YEBTkL4rzXY2ucpSKy+UYHjUBIIkuJbWYbsGIrKLEWU5dgJMmLkkIb3qeC3O3Tpb1ZQCwecscvJTDjDjkRw== +"@types/npmlog@^4.1.2": + version "4.1.2" + resolved "https://registry.yarnpkg.com/@types/npmlog/-/npmlog-4.1.2.tgz#d070fe6a6b78755d1092a3dc492d34c3d8f871c4" + integrity sha512-4QQmOF5KlwfxJ5IGXFIudkeLCdMABz03RcUXu+LCb24zmln8QW6aDjuGl4d4XPVLf2j+FnjelHTP7dvceAFbhA== + +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + "@types/q@^1.5.1": version "1.5.2" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" @@ -3021,10 +2968,10 @@ dependencies: "@types/react" "*" -"@types/react-syntax-highlighter@10.1.0": - version "10.1.0" - resolved "https://registry.yarnpkg.com/@types/react-syntax-highlighter/-/react-syntax-highlighter-10.1.0.tgz#9c534e29bbe05dba9beae1234f3ae944836685d4" - integrity sha512-dF49hC4FZp1dIKyzacOrHvqMUe8U2IXyQCQXOcT1e6n64gLBp+xM6qGtPsThIT9XjiIHSg2W5Jc2V5IqekBfnA== +"@types/react-syntax-highlighter@11.0.2": + version "11.0.2" + resolved "https://registry.yarnpkg.com/@types/react-syntax-highlighter/-/react-syntax-highlighter-11.0.2.tgz#a2e3ff657d7c47813f80ca930f3d959c31ec51e3" + integrity sha512-iMNcixH8330f2dq0RY+VOXCP8JFehgmOhLOtnO85Ty+qu0fHXJNEqWx5VuFv8v0aEq0U/N9d/k1yvA+c6PEmPw== dependencies: "@types/react" "*" @@ -3056,6 +3003,11 @@ dependencies: redux "*" +"@types/stack-utils@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" + integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== + "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" @@ -3078,6 +3030,23 @@ "@types/unist" "*" "@types/vfile-message" "*" +"@types/webpack-env@^1.15.0": + version "1.15.0" + resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.15.0.tgz#bd9956d5044b1fb43e869a9ba9148862ff98d9fd" + integrity sha512-TfcyNecCz8Z9/s90gBOBniyzZrTru8u2Vp0VZODq4KEBaQu8bfXvu7o/KUOecMpzjbFPUA7aqgSq628Iue5BQg== + +"@types/yargs-parser@*": + version "15.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" + integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw== + +"@types/yargs@^13.0.0": + version "13.0.6" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.6.tgz#6aed913a92c262c13b94d4bca8043237de202124" + integrity sha512-IkltIncDQWv6fcAvnHtJ6KtkmY/vtR3bViOaCzpj/A3yNhlfZAgxNe6AEQD1cQrkYD+YsKVo08DSxvNKEsD7BA== + dependencies: + "@types/yargs-parser" "*" + "@webassemblyjs/ast@1.8.5": version "1.8.5" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" @@ -3276,6 +3245,11 @@ abab@^1.0.3: resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" integrity sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4= +abab@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" + integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -3388,7 +3362,7 @@ acorn-globals@^4.0.0: dependencies: acorn "^5.0.0" -acorn-globals@^4.3.3: +acorn-globals@^4.1.0, acorn-globals@^4.3.3: version "4.3.4" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A== @@ -3448,7 +3422,7 @@ acorn@^4.0.3: resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= -acorn@^5.5.0: +acorn@^5.5.0, acorn@^5.5.3: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== @@ -3463,16 +3437,16 @@ acorn@^6.0.2: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.4.tgz#77377e7353b72ec5104550aa2d2097a2fd40b754" integrity sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg== -acorn@^6.0.5: - version "6.1.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" - integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== - acorn@^6.0.7: version "6.2.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.0.tgz#67f0da2fc339d6cfb5d6fb244fd449f33cd8bbe3" integrity sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw== +acorn@^6.2.1: + version "6.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" + integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== + acorn@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.0.0.tgz#26b8d1cd9a9b700350b71c0905546f64d1284e7a" @@ -3592,10 +3566,18 @@ agentkeepalive@^3.5.2: dependencies: humanize-ms "^1.2.1" -"airbnb-js-shims@^1 || ^2": - version "2.2.0" - resolved "https://registry.yarnpkg.com/airbnb-js-shims/-/airbnb-js-shims-2.2.0.tgz#46e1d9d9516f704ef736de76a3b6d484df9a96d8" - integrity sha512-pcSQf1+Kx7/0ibRmxj6rmMYc5V8SHlKu+rkQ80h0bjSLDaIxHg/3PiiFJi4A9mDc01CoBHoc8Fls2G/W0/+s5g== +aggregate-error@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" + integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +airbnb-js-shims@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/airbnb-js-shims/-/airbnb-js-shims-2.2.1.tgz#db481102d682b98ed1daa4c5baa697a05ce5c040" + integrity sha512-wJNXPH66U2xjgo1Zwyjf9EydvJ2Si94+vSdk6EERcBfB2VZkeltpqIats0cqIZMLCXP3zcyaUKGYQeIBT6XjsQ== dependencies: array-includes "^3.0.3" array.prototype.flat "^1.2.1" @@ -3610,7 +3592,7 @@ agentkeepalive@^3.5.2: object.values "^1.1.0" promise.allsettled "^1.0.0" promise.prototype.finally "^3.1.0" - string.prototype.matchall "^3.0.1" + string.prototype.matchall "^4.0.0 || ^3.0.1" string.prototype.padend "^3.0.0" string.prototype.padstart "^3.0.0" symbol.prototype.description "^1.0.0" @@ -3651,6 +3633,11 @@ ajv-keywords@^3.1.0: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.0.tgz#4b831e7b531415a7cc518cd404e73f6193c6349d" integrity sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw== +ajv-keywords@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" + integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== + ajv-merge-patch@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ajv-merge-patch/-/ajv-merge-patch-4.1.0.tgz#cd580e5860ac53431d6aa901fa3d5e2eb2b74a6c" @@ -3767,6 +3754,13 @@ ansi-escapes@^3.2.0: resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== +ansi-escapes@^4.2.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" + integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg== + dependencies: + type-fest "^0.8.1" + ansi-gray@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" @@ -3796,7 +3790,7 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= -ansi-regex@^4.1.0: +ansi-regex@^4.0.0, ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== @@ -3833,11 +3827,26 @@ ansi-styles@^4.0.0: "@types/color-name" "^1.1.1" color-convert "^2.0.1" +ansi-styles@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + ansi-styles@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178" integrity sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg= +ansi-to-html@^0.6.11: + version "0.6.13" + resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.13.tgz#c72eae8b63e5ca0643aab11bfc6e6f2217425833" + integrity sha512-Ys2/umuaTlQvP9DLkaa7UzRKF2FLrfod/hNHXS9QhXCrw7seObG6ksOGmNz3UoK+adwM8L9vQfG7mvaxfJ3Jvw== + dependencies: + entities "^1.1.2" + ansi-wrap@0.1.0, ansi-wrap@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" @@ -4289,16 +4298,16 @@ ast-types@0.11.3: resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.11.3.tgz#c20757fe72ee71278ea0ff3d87e5c2ca30d9edf8" integrity sha512-XA5o5dsNw8MhyW0Q7MWXJWc4oOzZKbdsEJq45h7c8q/d9DwWZ5F2ugUc1PuMLPGsUnphCt/cNDHu8JeBbxf1qA== -ast-types@0.12.4: - version "0.12.4" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.12.4.tgz#71ce6383800f24efc9a1a3308f3a6e420a0974d1" - integrity sha512-ky/YVYCbtVAS8TdMIaTiPFHwEpRB5z1hctepJplTr3UW5q8TDrpIMCILyk8pmLxGtn2KCtC/lSn7zOsaI7nzDw== - ast-types@0.x.x: version "0.9.6" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9" integrity sha1-ECyenpAF0+fjgpvwxPok7oYu6bk= +ast-types@^0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.2.tgz#df39b677a911a83f3a049644fb74fdded23cea48" + integrity sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA== + astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" @@ -4371,6 +4380,13 @@ async-limiter@^1.0.0, async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== +async-retry@^1.1.4: + version "1.3.1" + resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.1.tgz#139f31f8ddce50c0870b0ba558a6079684aaed55" + integrity sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA== + dependencies: + retry "0.12.0" + async-settle@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz#1d0a914bb02575bec8a8f3a74e5080f72b2c0c6b" @@ -4524,18 +4540,18 @@ autoprefixer@^9.0.0: postcss "^7.0.17" postcss-value-parser "^4.0.0" -autoprefixer@^9.4.9: - version "9.6.0" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.6.0.tgz#0111c6bde2ad20c6f17995a33fad7cf6854b4c87" - integrity sha512-kuip9YilBqhirhHEGHaBTZKXL//xxGnzvsD0FtBQa6z+A69qZD6s/BAX9VzDF1i9VKDquTJDQaPLSEhOnL6FvQ== +autoprefixer@^9.7.2: + version "9.7.4" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.4.tgz#f8bf3e06707d047f0641d87aee8cfb174b2a5378" + integrity sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g== dependencies: - browserslist "^4.6.1" - caniuse-lite "^1.0.30000971" + browserslist "^4.8.3" + caniuse-lite "^1.0.30001020" chalk "^2.4.2" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^7.0.16" - postcss-value-parser "^3.3.1" + postcss "^7.0.26" + postcss-value-parser "^4.0.2" await-semaphore@^0.1.1, await-semaphore@^0.1.3: version "0.1.3" @@ -4557,6 +4573,14 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== +axios@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8" + integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ== + dependencies: + follow-redirects "1.5.10" + is-buffer "^2.0.2" + babel-code-frame@^6.16.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" @@ -4765,6 +4789,29 @@ babel-helpers@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" +babel-jest@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.9.0.tgz#3fc327cb8467b89d14d7bc70e315104a783ccd54" + integrity sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw== + dependencies: + "@jest/transform" "^24.9.0" + "@jest/types" "^24.9.0" + "@types/babel__core" "^7.1.0" + babel-plugin-istanbul "^5.1.0" + babel-preset-jest "^24.9.0" + chalk "^2.4.2" + slash "^2.0.0" + +babel-loader@^8.0.6: + version "8.0.6" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.6.tgz#e33bdb6f362b03f4bb141a0c21ab87c501b70dfb" + integrity sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw== + dependencies: + find-cache-dir "^2.0.0" + loader-utils "^1.0.2" + mkdirp "^0.5.1" + pify "^4.0.1" + babel-messages@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" @@ -4784,13 +4831,6 @@ babel-plugin-check-es2015-constants@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-dynamic-import-node@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.2.0.tgz#c0adfb07d95f4a4495e9aaac6ec386c4d7c2524e" - integrity sha512-fP899ELUnTaBcIzmrW7nniyqqdYWrWuJUyPWHxFa/c7r7hS6KC8FscNfLlBNIoPSc55kYMGEEKjPjJGCLbE1qA== - dependencies: - object.assign "^4.1.0" - babel-plugin-dynamic-import-node@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" @@ -4798,15 +4838,15 @@ babel-plugin-dynamic-import-node@^2.3.0: dependencies: object.assign "^4.1.0" -babel-plugin-emotion@^10.0.22, babel-plugin-emotion@^10.0.23: - version "10.0.23" - resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.23.tgz#040d40bf61dcab6d31dd6043d10e180240b8515b" - integrity sha512-1JiCyXU0t5S2xCbItejCduLGGcKmF3POT0Ujbexog2MI4IlRcIn/kWjkYwCUZlxpON0O5FC635yPl/3slr7cKQ== +babel-plugin-emotion@^10.0.20, babel-plugin-emotion@^10.0.27: + version "10.0.27" + resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.27.tgz#59001cf5de847c1d61f2079cd906a90a00d3184f" + integrity sha512-SUNYcT4FqhOqvwv0z1oeYhqgheU8qrceLojuHyX17ngo7WtWqN5I9l3IGHzf21Xraj465CVzF4IvOlAF+3ed0A== dependencies: "@babel/helper-module-imports" "^7.0.0" - "@emotion/hash" "0.7.3" - "@emotion/memoize" "0.7.3" - "@emotion/serialize" "^0.11.14" + "@emotion/hash" "0.7.4" + "@emotion/memoize" "0.7.4" + "@emotion/serialize" "^0.11.15" babel-plugin-macros "^2.0.0" babel-plugin-syntax-jsx "^6.18.0" convert-source-map "^1.5.0" @@ -4830,16 +4870,24 @@ babel-plugin-emotion@^10.0.9: find-root "^1.1.0" source-map "^0.5.7" -babel-plugin-macros@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.5.1.tgz#4a119ac2c2e19b458c259b9accd7ee34fd57ec6f" - integrity sha512-xN3KhAxPzsJ6OQTktCanNpIFnnMsCV+t8OloKxIL72D6+SUZYFn9qfklPgef5HyyDtzYZqqb+fs1S12+gQY82Q== +babel-plugin-istanbul@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz#df4ade83d897a92df069c4d9a25cf2671293c854" + integrity sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw== dependencies: - "@babel/runtime" "^7.4.2" - cosmiconfig "^5.2.0" - resolve "^1.10.0" + "@babel/helper-plugin-utils" "^7.0.0" + find-up "^3.0.0" + istanbul-lib-instrument "^3.3.0" + test-exclude "^5.2.3" + +babel-plugin-jest-hoist@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz#4f837091eb407e01447c8843cbec546d0002d756" + integrity sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw== + dependencies: + "@types/babel__traverse" "^7.0.6" -babel-plugin-macros@^2.0.0, babel-plugin-macros@^2.4.5: +babel-plugin-macros@^2.0.0: version "2.6.1" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.6.1.tgz#41f7ead616fc36f6a93180e89697f69f51671181" integrity sha512-6W2nwiXme6j1n2erPOnmRiWfObUhWH7Qw1LMi9XZy8cj+KtESu3T6asZvtk5bMQQjX8te35o7CFueiSdL/2NmQ== @@ -4848,6 +4896,15 @@ babel-plugin-macros@^2.0.0, babel-plugin-macros@^2.4.5: cosmiconfig "^5.2.0" resolve "^1.10.0" +babel-plugin-macros@^2.7.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" + integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== + dependencies: + "@babel/runtime" "^7.7.2" + cosmiconfig "^6.0.0" + resolve "^1.12.0" + babel-plugin-minify-builtins@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz#31eb82ed1a0d0efdc31312f93b6e4741ce82c36b" @@ -4927,13 +4984,13 @@ babel-plugin-named-asset-import@^0.3.1: resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.2.tgz#20978ed446b8e1bf4a2f42d0a94c0ece85f75f4f" integrity sha512-CxwvxrZ9OirpXQ201Ec57OmGhmI8/ui/GwTDy0hSp6CmRvgRC0pSair6Z04Ck+JStA0sMPZzSJ3uE4n17EXpPQ== -babel-plugin-react-docgen@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-react-docgen/-/babel-plugin-react-docgen-3.1.0.tgz#14b02b363a38cc9e08c871df16960d27ef92030f" - integrity sha512-W6xqZnZIWjZuE9IjP7XolxxgFGB5Y9GZk4cLPSWKa10MrT86q7bX4ke9jbrNhFVIRhbmzL8wE1Sn++mIWoJLbw== +babel-plugin-react-docgen@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-react-docgen/-/babel-plugin-react-docgen-4.1.0.tgz#1dfa447dac9ca32d625a123df5733a9e47287c26" + integrity sha512-vzpnBlfGv8XOhJM2zbPyyqw2OLEbelgZZsaaRRTpVwNKuYuc+pUg4+dy7i9gCRms0uOQn4osX571HRcCJMJCmA== dependencies: - lodash "^4.17.11" - react-docgen "^4.1.0" + lodash "^4.17.15" + react-docgen "^5.0.0" recast "^0.14.7" babel-plugin-syntax-async-functions@^6.8.0: @@ -5191,11 +5248,6 @@ babel-plugin-transform-property-literals@^6.9.4: dependencies: esutils "^2.0.2" -babel-plugin-transform-react-remove-prop-types@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" - integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== - babel-plugin-transform-regenerator@^6.22.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" @@ -5288,6 +5340,14 @@ babel-preset-env@^1.7.0: invariant "^2.2.2" semver "^5.3.0" +babel-preset-jest@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz#192b521e2217fb1d1f67cf73f70c336650ad3cdc" + integrity sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg== + dependencies: + "@babel/plugin-syntax-object-rest-spread" "^7.0.0" + babel-plugin-jest-hoist "^24.9.0" + "babel-preset-minify@^0.5.0 || 0.6.0-alpha.5": version "0.5.0" resolved "https://registry.yarnpkg.com/babel-preset-minify/-/babel-preset-minify-0.5.0.tgz#e25bb8d3590087af02b650967159a77c19bfb96b" @@ -5317,30 +5377,6 @@ babel-preset-env@^1.7.0: babel-plugin-transform-undefined-to-void "^6.9.4" lodash.isplainobject "^4.0.6" -babel-preset-react-app@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-9.0.0.tgz#703108142bc9dd7173bde6a1a0138a762abc76f9" - integrity sha512-YVsDA8HpAKklhFLJtl9+AgaxrDaor8gGvDFlsg1ByOS0IPGUovumdv4/gJiAnLcDmZmKlH6+9sVOz4NVW7emAg== - dependencies: - "@babel/core" "7.4.3" - "@babel/plugin-proposal-class-properties" "7.4.0" - "@babel/plugin-proposal-decorators" "7.4.0" - "@babel/plugin-proposal-object-rest-spread" "7.4.3" - "@babel/plugin-syntax-dynamic-import" "7.2.0" - "@babel/plugin-transform-classes" "7.4.3" - "@babel/plugin-transform-destructuring" "7.4.3" - "@babel/plugin-transform-flow-strip-types" "7.4.0" - "@babel/plugin-transform-react-constant-elements" "7.2.0" - "@babel/plugin-transform-react-display-name" "7.2.0" - "@babel/plugin-transform-runtime" "7.4.3" - "@babel/preset-env" "7.4.3" - "@babel/preset-react" "7.0.0" - "@babel/preset-typescript" "7.3.3" - "@babel/runtime" "7.4.3" - babel-plugin-dynamic-import-node "2.2.0" - babel-plugin-macros "2.5.1" - babel-plugin-transform-react-remove-prop-types "0.4.24" - babel-register@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" @@ -5362,11 +5398,6 @@ babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: core-js "^2.4.0" regenerator-runtime "^0.11.0" -babel-standalone@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-standalone/-/babel-standalone-6.26.0.tgz#15fb3d35f2c456695815ebf1ed96fe7f015b6886" - integrity sha1-Ffs9NfLEVmlYFevx7Zb+fwFbaIY= - babel-template@^6.24.1, babel-template@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" @@ -5527,6 +5558,11 @@ basic-auth@~2.0.0: dependencies: safe-buffer "5.1.2" +batch-processor@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/batch-processor/-/batch-processor-1.0.0.tgz#75c95c32b748e0850d10c2b168f6bdbe9891ace8" + integrity sha1-dclcMrdI4IUNEMKxaPa9vpiRrOg= + bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" @@ -5787,11 +5823,16 @@ bluebird@^3.1.1, bluebird@^3.3.0, bluebird@^3.3.5, bluebird@^3.4.6, bluebird@^3. resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" integrity sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA== -bluebird@^3.5.3, bluebird@^3.5.4: +bluebird@^3.5.4: version "3.5.5" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== +bluebird@^3.5.5: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + bn.js@4.11.6: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" @@ -5898,6 +5939,20 @@ boxen@^3.0.0: type-fest "^0.3.0" widest-line "^2.0.0" +boxen@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" + integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^5.3.1" + chalk "^3.0.0" + cli-boxes "^2.2.0" + string-width "^4.1.0" + term-size "^2.1.0" + type-fest "^0.8.1" + widest-line "^3.1.0" + brace-expansion@^1.1.7: version "1.1.8" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" @@ -5982,7 +6037,7 @@ browser-process-hrtime@^0.1.2: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz#425d68a58d3447f02a04aa894187fce8af8b7b8e" integrity sha1-Ql1opY00R/AqBKqJQYf86K+Le44= -browser-resolve@^1.11.0, browser-resolve@^1.7.0: +browser-resolve@^1.11.0, browser-resolve@^1.11.3, browser-resolve@^1.7.0: version "1.11.3" resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ== @@ -6164,7 +6219,7 @@ browserslist@^3.1.1, browserslist@^3.2.6: caniuse-lite "^1.0.30000844" electron-to-chromium "^1.3.47" -browserslist@^4.5.2, browserslist@^4.6.0, browserslist@^4.6.1, browserslist@^4.6.3: +browserslist@^4.6.0, browserslist@^4.6.3: version "4.7.0" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.0.tgz#9ee89225ffc07db03409f2fee524dc8227458a17" integrity sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA== @@ -6173,6 +6228,15 @@ browserslist@^4.5.2, browserslist@^4.6.0, browserslist@^4.6.1, browserslist@^4.6 electron-to-chromium "^1.3.247" node-releases "^1.1.29" +browserslist@^4.8.3: + version "4.8.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.5.tgz#691af4e327ac877b25e7a3f7ee869c4ef36cdea3" + integrity sha512-4LMHuicxkabIB+n9874jZX/az1IaZ5a+EUuvD7KFOu9x/Bd5YHyO0DIz2ls/Kl8g0ItS4X/ilEgf4T1Br0lgSg== + dependencies: + caniuse-lite "^1.0.30001022" + electron-to-chromium "^1.3.338" + node-releases "^1.1.46" + bs58@4.0.1, bs58@^4.0.0, bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" @@ -6214,6 +6278,13 @@ bs58check@^1.0.8: bs58 "^3.1.0" create-hash "^1.1.0" +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + btoa@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" @@ -6381,26 +6452,51 @@ c3@^0.6.7: dependencies: d3 "^5.0.0" -cacache@^11.3.2: - version "11.3.2" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.2.tgz#2d81e308e3d258ca38125b676b98b2ac9ce69bfa" - integrity sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg== +cacache@^12.0.2: + version "12.0.3" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" + integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== dependencies: - bluebird "^3.5.3" + bluebird "^3.5.5" chownr "^1.1.1" figgy-pudding "^3.5.1" - glob "^7.1.3" + glob "^7.1.4" graceful-fs "^4.1.15" + infer-owner "^1.0.3" lru-cache "^5.1.1" mississippi "^3.0.0" mkdirp "^0.5.1" move-concurrently "^1.0.1" promise-inflight "^1.0.1" - rimraf "^2.6.2" + rimraf "^2.6.3" ssri "^6.0.1" unique-filename "^1.1.1" y18n "^4.0.0" +cacache@^13.0.1: + version "13.0.1" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-13.0.1.tgz#a8000c21697089082f85287a1aec6e382024a71c" + integrity sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w== + dependencies: + chownr "^1.1.2" + figgy-pudding "^3.5.1" + fs-minipass "^2.0.0" + glob "^7.1.4" + graceful-fs "^4.2.2" + infer-owner "^1.0.4" + lru-cache "^5.1.1" + minipass "^3.0.0" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.2" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + p-map "^3.0.0" + promise-inflight "^1.0.1" + rimraf "^2.7.1" + ssri "^7.0.0" + unique-filename "^1.1.1" + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -6583,11 +6679,23 @@ can-use-dom@^0.1.0: resolved "https://registry.yarnpkg.com/can-use-dom/-/can-use-dom-0.1.0.tgz#22cc4a34a0abc43950f42c6411024a3f6366b45a" integrity sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo= -caniuse-lite@^1.0.30000810, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000955, caniuse-lite@^1.0.30000971, caniuse-lite@^1.0.30000980, caniuse-lite@^1.0.30000989: +caniuse-lite@^1.0.30000810, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000955, caniuse-lite@^1.0.30000980, caniuse-lite@^1.0.30000989: version "1.0.30001005" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001005.tgz#823054210be638c725521edcb869435dae46728d" integrity sha512-g78miZm1Z5njjYR216a5812oPiLgV1ssndgGxITHWUopmjUrCswMisA0a2kSB7a0vZRox6JOKhM51+efmYN8Mg== +caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.30001022: + version "1.0.30001023" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001023.tgz#b82155827f3f5009077bdd2df3d8968bcbcc6fc4" + integrity sha512-C5TDMiYG11EOhVOA62W1p3UsJ2z4DsHtMBQtjzp3ZsUglcQn62WOUgW0y795c7A5uZ+GCEIvzkMatLIlAsbNTA== + +capture-exit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" + integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g== + dependencies: + rsvp "^4.8.4" + capture-stack-trace@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d" @@ -6699,6 +6807,14 @@ chalk@^2.1.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.4.0.tgz#5199a3ddcd0c1efe23bc08c1b027b06176e0c64f" @@ -6831,7 +6947,12 @@ chownr@^1.1.1: resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== -chrome-trace-event@^1.0.0: +chownr@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" + integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== + +chrome-trace-event@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== @@ -6930,6 +7051,11 @@ clean-css@4.2.x: dependencies: source-map "~0.6.0" +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + cli-boxes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" @@ -6954,6 +7080,13 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + cli-table3@0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" @@ -7289,6 +7422,16 @@ commander@^2.15.0, commander@^2.16.0, commander@^2.19.0, commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== +commander@^2.9.0, commander@~2.20.3: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.0.tgz#545983a0603fe425bc672d66c9e3c89c42121a83" + integrity sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw== + commander@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781" @@ -7299,11 +7442,6 @@ commander@~2.19.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== -commander@~2.20.3: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - commander@~2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" @@ -7311,7 +7449,7 @@ commander@~2.8.1: dependencies: graceful-readlink ">= 1.0.0" -common-tags@1.8.0, common-tags@^1.8.0: +common-tags@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw== @@ -7519,6 +7657,13 @@ convert-source-map@^1.1.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0: dependencies: safe-buffer "~5.1.1" +convert-source-map@^1.4.0, convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + convert-source-map@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" @@ -7584,7 +7729,7 @@ copy-to-clipboard@^3.0.8: dependencies: toggle-selection "^1.0.3" -core-js-compat@^3.0.0, core-js-compat@^3.1.1: +core-js-compat@^3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.1.3.tgz#0cc3ba4c7f62928c2837e1cffbe8dc78b4f1ae14" integrity sha512-EP018pVhgwsKHz3YoN1hTq49aRe+h017Kjz0NQz3nXV0cCRMvH3fLQl+vEPGr4r4J5sk4sU3tUC7U1aqTCeJeA== @@ -7613,11 +7758,6 @@ core-js@^2.4.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== -core-js@^2.5.7: - version "2.6.9" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" - integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== - core-js@^3.0.0: version "3.1.4" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.1.4.tgz#3a2837fc48e582e1ae25907afcd6cf03b0cc7a07" @@ -7628,11 +7768,24 @@ core-js@^3.0.1: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.1.3.tgz#95700bca5f248f5f78c0ec63e784eca663ec4138" integrity sha512-PWZ+ZfuaKf178BIAg+CRsljwjIMRV8MY00CbZczkR6Zk5LfkSkjGoaab3+bqRQWVITNZxQB7TFYz+CFcyuamvA== +core-js@^3.0.4: + version "3.6.4" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.4.tgz#440a83536b458114b9cb2ac1580ba377dc470647" + integrity sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw== + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +corejs-upgrade-webpack-plugin@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/corejs-upgrade-webpack-plugin/-/corejs-upgrade-webpack-plugin-2.2.0.tgz#503293bf1fdcb104918eb40d0294e4776ad6923a" + integrity sha512-J0QMp9GNoiw91Kj/dkIQFZeiCXgXoja/Wlht1SPybxerBWh4NCmb0pOgCv61lrlQZETwvVVfAFAA3IqoEO9aqQ== + dependencies: + resolve-from "^5.0.0" + webpack "^4.38.0" + cors@^2.7.1, cors@^2.8.1: version "2.8.5" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" @@ -7666,6 +7819,17 @@ cosmiconfig@^5.0.0, cosmiconfig@^5.2.0: js-yaml "^3.13.1" parse-json "^4.0.0" +cosmiconfig@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" + integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.7.2" + coveralls@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.0.tgz#22ef730330538080d29b8c151dc9146afde88a99" @@ -7862,6 +8026,24 @@ css-loader@^2.1.1: postcss-value-parser "^3.3.0" schema-utils "^1.0.0" +css-loader@^3.0.0: + version "3.4.2" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.4.2.tgz#d3fdb3358b43f233b78501c5ed7b1c6da6133202" + integrity sha512-jYq4zdZT0oS0Iykt+fqnzVLRIeiPWhka+7BqPn+oSIpWJAHak5tmB/WZrJ2a21JhCeFyNnnlroSl8c+MtVndzA== + dependencies: + camelcase "^5.3.1" + cssesc "^3.0.0" + icss-utils "^4.1.1" + loader-utils "^1.2.3" + normalize-path "^3.0.0" + postcss "^7.0.23" + postcss-modules-extract-imports "^2.0.0" + postcss-modules-local-by-default "^3.0.2" + postcss-modules-scope "^2.1.1" + postcss-modules-values "^3.0.0" + postcss-value-parser "^4.0.2" + schema-utils "^2.6.0" + css-select-base-adapter@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" @@ -7967,6 +8149,13 @@ cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": dependencies: cssom "0.3.x" +cssstyle@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1" + integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA== + dependencies: + cssom "0.3.x" + csstype@^2.0.0, csstype@^2.2.0: version "2.4.2" resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.4.2.tgz#158e36c69566bf968da63d0ba14eda1c20e8643a" @@ -8293,6 +8482,15 @@ data-uri-to-buffer@1: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz#77163ea9c20d8641b4707e8f18abdf9a78f34835" integrity sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ== +data-urls@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe" + integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ== + dependencies: + abab "^2.0.0" + whatwg-mimetype "^2.2.0" + whatwg-url "^7.0.0" + datastore-core@~0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/datastore-core/-/datastore-core-0.6.1.tgz#73ca9eecec21f001e4f625631398b94afafd2823" @@ -8401,14 +8599,14 @@ debug@2, debug@2.6.9, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, de dependencies: ms "2.0.0" -debug@3.1.0, debug@3.X, debug@~3.1.0: +debug@3.1.0, debug@3.X, debug@=3.1.0, debug@~3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== dependencies: ms "2.0.0" -debug@3.2.6, debug@^3.0.0, debug@^3.1.0, debug@^3.2.5, debug@^3.2.6: +debug@3.2.6, debug@^3.0.0, debug@^3.0.1, debug@^3.1.0, debug@^3.2.5, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -8739,6 +8937,11 @@ delimit-stream@0.1.0: resolved "https://registry.yarnpkg.com/delimit-stream/-/delimit-stream-0.1.0.tgz#9b8319477c0e5f8aeb3ce357ae305fc25ea1cd2b" integrity sha1-m4MZR3wOX4rrPONXrjBfwl6hzSs= +denodeify@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" + integrity sha1-OjYof1A05pnnV3kBBSwubJQlFjE= + depd@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" @@ -8835,7 +9038,7 @@ detect-libc@^1.0.2: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= -detect-newline@2.X: +detect-newline@2.X, detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I= @@ -8930,6 +9133,11 @@ did-resolver@0.0.6: resolved "https://registry.yarnpkg.com/did-resolver/-/did-resolver-0.0.6.tgz#2d4638b8914871c19945fb3243f6f298c1cca9db" integrity sha512-PqxzaoomTbJG3IzEouUGgppu3xrsbGKHS75zS3vS/Hfm56XxLpwIe7yFLokgXUbMWmLa0dczFHOibmebO4wRLA== +diff-sequences@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5" + integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew== + diff@3.3.1, diff@^3.1.0: version "3.3.1" resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" @@ -9154,6 +9362,13 @@ domexception@^1.0.0: resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.0.tgz#81fe5df81b3f057052cde3a9fa9bf536a85b9ab0" integrity sha512-WpwuBlZ2lQRFa4H/4w49deb9rJLot9KmqrKKjMc9qBl7CID+DdC2swoa34ccRl+anL2B6bLp6TjFdIdnzekMBQ== +domexception@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" + integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== + dependencies: + webidl-conversions "^4.0.2" + domhandler@2.3: version "2.3.0" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" @@ -9198,10 +9413,10 @@ dotenv-defaults@^1.0.2: dependencies: dotenv "^6.2.0" -dotenv-expand@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-4.2.0.tgz#def1f1ca5d6059d24a766e587942c21106ce1275" - integrity sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU= +dotenv-expand@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" + integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== dotenv-webpack@^1.7.0: version "1.7.0" @@ -9210,11 +9425,16 @@ dotenv-webpack@^1.7.0: dependencies: dotenv-defaults "^1.0.2" -dotenv@^6.0.0, dotenv@^6.2.0: +dotenv@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064" integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w== +dotenv@^8.0.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" + integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== + download@^6.2.2: version "6.2.5" resolved "https://registry.yarnpkg.com/download/-/download-6.2.5.tgz#acd6a542e4cd0bb42ca70cfc98c9e43b07039714" @@ -9331,7 +9551,7 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -ejs@^2.4.1, ejs@^2.6.1: +ejs@^2.4.1: version "2.6.1" resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ== @@ -9341,6 +9561,11 @@ ejs@^2.6.2: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.1.tgz#5b5ab57f718b79d4aca9254457afecd36fa80228" integrity sha512-kS/gEPzZs3Y1rRsbGX4UOSjtP/CeJP0CxSNZHYxGfVM/VgLcv0ZqM7C45YyTj2DI2g7+P9Dd24C+IMIg6D0nYQ== +ejs@^2.7.4: + version "2.7.4" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" + integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== + electron-download@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.1.tgz#02e69556705cc456e520f9e035556ed5a015ebe8" @@ -9366,6 +9591,11 @@ electron-to-chromium@^1.3.247: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.262.tgz#8022933e46e5a2c7b0fd1565d215872326520a7c" integrity sha512-YFr53qZWr2pWkiTUorWEhAweujdf0ALiUp8VkNa0WGtbMVR+kZ8jNy3VTCemLsA4sT6+srCqehNn8TEAD0Ngrw== +electron-to-chromium@^1.3.338: + version "1.3.340" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.340.tgz#5d4fe78e984d4211194cf5a52e08069543da146f" + integrity sha512-hRFBAglhcj5iVYH+o8QU0+XId1WGoc0VGowJB1cuJAt3exHGrivZvWeAO5BRgBZqwZtwxjm8a5MQeGoT/Su3ww== + electron-to-chromium@^1.3.47: version "1.3.52" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz#d2d9f1270ba4a3b967b831c40ef71fb4d9ab5ce0" @@ -9380,6 +9610,13 @@ electron@^5.0.0: electron-download "^4.1.0" extract-zip "^1.0.3" +element-resize-detector@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/element-resize-detector/-/element-resize-detector-1.2.1.tgz#b0305194447a4863155e58f13323a0aef30851d1" + integrity sha512-BdFsPepnQr9fznNPF9nF4vQ457U/ZJXQDSNF1zBe7yaga8v9AdZf3/NElYxFdUh7SitSGt040QygiTo6dtatIw== + dependencies: + batch-processor "1.0.0" + elliptic@6.3.3: version "6.3.3" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" @@ -9441,23 +9678,14 @@ emojis-list@^2.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= -emotion-theming@^10.0.14: - version "10.0.19" - resolved "https://registry.yarnpkg.com/emotion-theming/-/emotion-theming-10.0.19.tgz#66d13db74fccaefad71ba57c915b306cf2250295" - integrity sha512-dQRBPLAAQ6eA8JKhkLCIWC8fdjPbiNC1zNTdFF292h9amhZXofcNGUP7axHoHX4XesqQESYwZrXp53OPInMrKw== +emotion-theming@^10.0.19: + version "10.0.27" + resolved "https://registry.yarnpkg.com/emotion-theming/-/emotion-theming-10.0.27.tgz#1887baaec15199862c89b1b984b79806f2b9ab10" + integrity sha512-MlF1yu/gYh8u+sLUqA0YuA9JX0P4Hb69WlKc/9OLo+WCXuX6sy/KoIa+qJimgmr2dWqnypYKYPX37esjDBbhdw== dependencies: "@babel/runtime" "^7.5.5" - "@emotion/weak-memoize" "0.2.4" - hoist-non-react-statics "^3.3.0" - -emotion-theming@^10.0.9: - version "10.0.10" - resolved "https://registry.yarnpkg.com/emotion-theming/-/emotion-theming-10.0.10.tgz#efe8751119751bdc70fdc1795fe4cde0fb0cf14c" - integrity sha512-E4SQ3Y91avxxydDgubi/po/GaC5MM1XHm8kcClKg1PA/TeOye0PiLBzAzlgt9dBzDRV9+qHDunsayPvzVYIYng== - dependencies: - "@emotion/weak-memoize" "0.2.2" + "@emotion/weak-memoize" "0.2.5" hoist-non-react-statics "^3.3.0" - object-assign "^4.1.1" encodeurl@^1.0.2, encodeurl@~1.0.2: version "1.0.2" @@ -9604,6 +9832,19 @@ entities@^1.1.1, entities@~1.1.1: resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" integrity sha1-blwtClYhtdra7O+AuQ7ftc13cvA= +entities@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== + +env-ci@^2.1.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/env-ci/-/env-ci-2.6.0.tgz#3fc46537c972b4d3ab5f0b82d07dfc1491297662" + integrity sha512-tnOi9qgtDxY3mvf69coXLHbSZtFMNGAJ1s/huirAhJZTx9rs/1qgFjl+6Z5ULQCfpDmlsf34L7wm+eJGwMazYg== + dependencies: + execa "^1.0.0" + java-properties "^0.2.9" + env-paths@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0" @@ -9780,6 +10021,23 @@ es-abstract@^1.15.0: string.prototype.trimleft "^2.1.0" string.prototype.trimright "^2.1.0" +es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2: + version "1.17.4" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184" + integrity sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" + es-to-primitive@^1.1.1, es-to-primitive@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" @@ -9939,6 +10197,18 @@ escodegen@^1.9.0: optionalDependencies: source-map "~0.5.6" +escodegen@^1.9.1: + version "1.13.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.13.0.tgz#c7adf9bd3f3cc675bb752f202f79a720189cab29" + integrity sha512-eYk2dCkxR07DsHA/X2hRBj0CFAZeri/LyDMc0C8JT1Hqi6JnVpMhJ7XFITbb0+yZS3lVkaPL2oCkZ3AVmeVbMw== + dependencies: + esprima "^4.0.1" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + escope@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" @@ -10039,7 +10309,7 @@ eslint-scope@3.7.1, eslint-scope@^3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-scope@^4.0.0, eslint-scope@^4.0.3: +eslint-scope@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== @@ -10276,7 +10546,7 @@ esprima@3.x.x, esprima@^3.1.3: resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= -esprima@4.0.1: +esprima@4.0.1, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -11280,6 +11550,11 @@ exec-buffer@^3.0.0: rimraf "^2.5.4" tempfile "^2.0.0" +exec-sh@^0.3.2: + version "0.3.4" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5" + integrity sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A== + execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" @@ -11330,7 +11605,7 @@ exit-hook@^1.0.0: resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g= -exit@0.1.2, exit@0.1.x: +exit@0.1.2, exit@0.1.x, exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= @@ -11376,6 +11651,18 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" +expect@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-24.9.0.tgz#b75165b4817074fa4a157794f46fe9f1ba15b6ca" + integrity sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q== + dependencies: + "@jest/types" "^24.9.0" + ansi-styles "^3.2.0" + jest-get-type "^24.9.0" + jest-matcher-utils "^24.9.0" + jest-message-util "^24.9.0" + jest-regex-util "^24.9.0" + expirymanager@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/expirymanager/-/expirymanager-0.9.3.tgz#e5f6b3ba00d8d76cf63311c2b71d7dfc9bde3e4f" @@ -11555,6 +11842,11 @@ fake-merkle-patricia-tree@^1.0.1: dependencies: checkpoint-store "^1.1.0" +fake-tag@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fake-tag/-/fake-tag-1.0.1.tgz#1d59da482240a02bd83500ca98976530ed154b0d" + integrity sha512-qmewZoBpa71mM+y6oxXYW/d1xOYQmeIvnEXAt1oCmdP0sqcogWYLepR87QL1jQVLSVMVYDq2cjY6ec/Wu8/4pg== + falafel@^2.0.0, falafel@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.1.0.tgz#96bb17761daba94f46d001738b3cedf3a67fe06c" @@ -11613,7 +11905,7 @@ fast-glob@^3.0.3: merge2 "^1.2.3" micromatch "^4.0.2" -fast-json-parse@^1.0.3: +fast-json-parse@^1.0.0, fast-json-parse@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/fast-json-parse/-/fast-json-parse-1.0.3.tgz#43e5c61ee4efa9265633046b770fb682a7577c4d" integrity sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw== @@ -11640,6 +11932,11 @@ fast-redact@^1.4.4: resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-1.5.0.tgz#302892f566750c4f5eec7b830bfc9bc473484034" integrity sha512-Afo61CgUjkzdvOKDHn08qnZ0kwck38AOGcMlvSGzvJbIab6soAP5rdoQayecGCDsD69AiF9vJBXyq31eoEO2tQ== +fast-safe-stringify@^1.0.8, fast-safe-stringify@^1.2.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-1.2.3.tgz#9fe22c37fb2f7f86f06b8f004377dbf8f1ee7bc1" + integrity sha512-QJYT/i0QYoiZBQ71ivxdyTqkwKkQ0oxACXHYxH2zYHJEgzi2LsbjgvtzTbLi1SZcF190Db2YP7I7eTsU2egOlw== + fast-safe-stringify@^2.0.6, fast-safe-stringify@^2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" @@ -11685,7 +11982,14 @@ faye-websocket@~0.11.1: dependencies: websocket-driver ">=0.5.1" -fbjs@^0.8.0, fbjs@^0.8.1, fbjs@^0.8.16, fbjs@^0.8.4: +fb-watchman@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== + dependencies: + bser "2.1.1" + +fbjs@^0.8.0, fbjs@^0.8.1, fbjs@^0.8.16: version "0.8.16" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" integrity sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s= @@ -11748,6 +12052,13 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" +figures@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec" + integrity sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" @@ -11778,13 +12089,13 @@ file-loader@^1.1.11: loader-utils "^1.0.2" schema-utils "^0.4.5" -file-loader@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-3.0.1.tgz#f8e0ba0b599918b51adfe45d66d1e771ad560faa" - integrity sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw== +file-loader@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-4.3.0.tgz#780f040f729b3d18019f20605f723e844b8a58af" + integrity sha512-aKrYPYjF1yG3oX0kWRrqrSMfgftm7oJW5M+m4owoldH5C51C0RkIwB++JbRvEW3IU6/ZG5n8UvEcdgwOt2UOWA== dependencies: - loader-utils "^1.0.2" - schema-utils "^1.0.0" + loader-utils "^1.2.3" + schema-utils "^2.5.0" file-system-cache@^1.0.5: version "1.0.5" @@ -11944,7 +12255,7 @@ find-cache-dir@^1.0.0: make-dir "^1.0.0" pkg-dir "^2.0.0" -find-cache-dir@^2.0.0: +find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== @@ -11962,6 +12273,15 @@ find-cache-dir@^3.0.0: make-dir "^3.0.0" pkg-dir "^4.1.0" +find-cache-dir@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.2.0.tgz#e7fe44c1abc1299f516146e563108fd1006c1874" + integrity sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.0" + pkg-dir "^4.1.0" + find-root@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" @@ -12113,7 +12433,7 @@ flatmap@0.0.3: resolved "https://registry.yarnpkg.com/flatmap/-/flatmap-0.0.3.tgz#1f18a4d938152d495965f9c958d923ab2dd669b4" integrity sha1-Hxik2TgVLUlZZfnJWNkjqy3WabQ= -flatstr@^1.0.12, flatstr@^1.0.9: +flatstr@^1.0.12, flatstr@^1.0.4, flatstr@^1.0.9: version "1.0.12" resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.12.tgz#c2ba6a08173edbb6c9640e3055b95e287ceb5931" integrity sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw== @@ -12151,10 +12471,17 @@ fnv1a@^1.0.1: resolved "https://registry.yarnpkg.com/fnv1a/-/fnv1a-1.0.1.tgz#915e2d6d023c43d5224ad9f6d2a3c4156f5712f5" integrity sha1-kV4tbQI8Q9UiStn20qPEFW9XEvU= -focus-lock@^0.6.3: - version "0.6.4" - resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.6.4.tgz#066af3ed5875d85745ab45ef4fbbb43e8a73514a" - integrity sha512-+waElh6m7dbNmEabXQIblZjJMIRQOoHMNqB8RZkyemK+vN1XQ9uHLi740DVwTcK5fzAq3g+tBglLjIqUDHX/Og== +focus-lock@^0.6.6: + version "0.6.6" + resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.6.6.tgz#98119a755a38cfdbeda0280eaa77e307eee850c7" + integrity sha512-Dx69IXGCq1qsUExWuG+5wkiMqVM/zGx/reXSJSLogECwp3x6KeNQZ+NAetgxEFpnC41rD8U3+jRCW68+LNzdtw== + +follow-redirects@1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" + integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== + dependencies: + debug "=3.1.0" follow-redirects@^1.0.0: version "1.5.0" @@ -12405,6 +12732,13 @@ fs-minipass@^1.2.5: dependencies: minipass "^2.2.1" +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + fs-mkdirp-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" @@ -12522,10 +12856,10 @@ fuse.js@^3.2.0: resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.2.0.tgz#f0448e8069855bf2a3e683cdc1d320e7e2a07ef4" integrity sha1-8ESOgGmFW/Kj5oPNwdMg5+KgfvQ= -fuse.js@^3.4.4: - version "3.4.5" - resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.4.5.tgz#8954fb43f9729bd5dbcb8c08f251db552595a7a6" - integrity sha512-s9PGTaQIkT69HaeoTVjwGsLfb8V8ScJLx5XGFcKHg0MqLUH/UZ4EKOtqtXX9k7AFqCGxD1aJmYb8Q5VYDibVRQ== +fuse.js@^3.4.6: + version "3.4.6" + resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.4.6.tgz#545c3411fed88bf2e27c457cab6e73e7af697a45" + integrity sha512-H6aJY4UpLFwxj1+5nAvufom5b2BT2v45P1MkPvdGIK8fWjQx/7o6tTT1+ALV0yawQvbmvCF0ufl2et8eJ7v7Cg== gaba@^1.6.0, gaba@^1.9.3: version "1.9.3" @@ -12655,6 +12989,11 @@ generate-object-property@^1.1.0: dependencies: is-property "^1.0.0" +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== + get-assigned-identifiers@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz#6dbf411de648cbaf8d9169ebb0d2d576191e2ff1" @@ -12816,6 +13155,22 @@ gifsicle@^4.0.0: execa "^1.0.0" logalot "^2.0.0" +git-up@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/git-up/-/git-up-2.1.0.tgz#2f14cfe78327e7c4a2b92fcac7bfc674fdfad40c" + integrity sha512-MJgwfcSd9qxgDyEYpRU/CDxNpUadrK80JHuEQDG4Urn0m7tpSOgCBrtiSIa9S9KH8Tbuo/TN8SSQmJBvsw1HkA== + dependencies: + is-ssh "^1.3.0" + parse-url "^3.0.2" + +git-url-parse@^8.1.0: + version "8.3.1" + resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-8.3.1.tgz#9d7d762993dc498aab16937c844e11afe3748817" + integrity sha512-r/FxXIdfgdSO+V2zl4ZK1JGYkHT9nqVRSzom5WsYPLg3XzeBeKPl3R/6X9E9ZJRx/sE/dXwXtfl+Zp7YL8ktWQ== + dependencies: + git-up "^2.0.0" + parse-domain "^2.0.0" + gl-mat4@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/gl-mat4/-/gl-mat4-1.1.4.tgz#1e895b55892e56a896867abd837d38f37a178086" @@ -13208,7 +13563,7 @@ got@^7.0.0, got@^7.1.0: url-parse-lax "^1.0.0" url-to-options "^1.0.1" -got@^8.3.1: +got@^8.3.1, got@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/got/-/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937" integrity sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw== @@ -13241,6 +13596,11 @@ graceful-fs@^4.1.10, graceful-fs@^4.1.15: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== +graceful-fs@^4.2.2: + version "4.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + "graceful-readlink@>= 1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" @@ -13658,6 +14018,11 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + has-gulplog@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" @@ -13848,10 +14213,10 @@ hi-base32@~0.5.0: resolved "https://registry.yarnpkg.com/hi-base32/-/hi-base32-0.5.0.tgz#61329f76a31f31008533f1c36f2473e259d64571" integrity sha512-DDRmxSyoYuvjUb9EnXdoiMChBZ7ZcUVJsK5Frd3kqMhuBxvmZdnBeynAVfj7/ECbn++CekcoprvC/rprHPAtow== -highlight.js@~9.12.0: - version "9.12.0" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" - integrity sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4= +highlight.js@~9.13.0: + version "9.13.1" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e" + integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A== history@^4.9.0: version "4.10.1" @@ -13935,7 +14300,7 @@ html-element-map@^1.0.0: dependencies: array-filter "^1.0.0" -html-encoding-sniffer@^1.0.1: +html-encoding-sniffer@^1.0.1, html-encoding-sniffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw== @@ -13947,6 +14312,11 @@ html-entities@^1.2.0: resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= +html-escaper@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.0.tgz#71e87f931de3fe09e56661ab9a29aadec707b491" + integrity sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig== + html-minifier@^3.5.20: version "3.5.21" resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c" @@ -14205,7 +14575,7 @@ icss-replace-symbols@^1.1.0: resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= -icss-utils@^4.1.0: +icss-utils@^4.0.0, icss-utils@^4.1.0, icss-utils@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== @@ -14350,6 +14720,14 @@ import-fresh@^3.0.0: parent-module "^1.0.0" resolve-from "^4.0.0" +import-fresh@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" + integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + import-from@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" @@ -14367,6 +14745,14 @@ import-lazy@^3.1.0: resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-3.1.0.tgz#891279202c8a2280fdbd6674dbd8da1a1dfc67cc" integrity sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ== +import-local@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" + integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== + dependencies: + pkg-dir "^3.0.0" + resolve-cwd "^2.0.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -14396,6 +14782,11 @@ indent-string@^3.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + indexes-of@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" @@ -14406,6 +14797,11 @@ indexof@0.0.1: resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= +infer-owner@^1.0.3, infer-owner@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -14518,7 +14914,7 @@ inquirer@^3.0.6: strip-ansi "^4.0.0" through "^2.3.6" -inquirer@^6.2.0, inquirer@^6.2.2: +inquirer@^6.2.2: version "6.3.1" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.3.1.tgz#7a413b5e7950811013a3db491c61d1f3b776e8e7" integrity sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA== @@ -14537,6 +14933,25 @@ inquirer@^6.2.0, inquirer@^6.2.2: strip-ansi "^5.1.0" through "^2.3.6" +inquirer@^7.0.0: + version "7.0.4" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.4.tgz#99af5bde47153abca23f5c7fc30db247f39da703" + integrity sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ== + dependencies: + ansi-escapes "^4.2.1" + chalk "^2.4.2" + cli-cursor "^3.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.15" + mute-stream "0.0.8" + run-async "^2.2.0" + rxjs "^6.5.3" + string-width "^4.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + insert-module-globals@^7.0.0: version "7.2.0" resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.2.0.tgz#ec87e5b42728479e327bd5c5c71611ddfb4752ba" @@ -14572,15 +14987,24 @@ interface-datastore@~0.6.0: pull-stream "^3.6.9" uuid "^3.2.2" +internal-slot@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3" + integrity sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g== + dependencies: + es-abstract "^1.17.0-next.1" + has "^1.0.3" + side-channel "^1.0.2" + interpret@^1.0.0, interpret@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ= -interpret@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" - integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== +interpret@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.0.0.tgz#b783ffac0b8371503e9ab39561df223286aa5433" + integrity sha512-e0/LknJ8wpMMhTiWcjivB+ESwIuvHnBSlBbmP/pSb8CQJldoj1p2qv7xGZ/+BtbTziYRFSz8OsvdbiX45LtYQA== intersect-objects@^1.0.0: version "1.0.0" @@ -15257,6 +15681,11 @@ is-buffer@^2.0.0, is-buffer@^2.0.3: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== +is-buffer@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" + integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== + is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" @@ -15269,6 +15698,11 @@ is-callable@^1.1.3, is-callable@^1.1.4: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== +is-callable@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" + integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== + is-ci@^1.0.10: version "1.2.1" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" @@ -15413,6 +15847,11 @@ is-function@^1.0.1, is-function@~1.0.0: resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" integrity sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU= +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + is-generator-function@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522" @@ -15633,7 +16072,7 @@ is-plain-obj@^1.0.0, is-plain-obj@^1.1, is-plain-obj@^1.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= -is-plain-object@2.0.4, is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== @@ -15694,6 +16133,13 @@ is-regex@^1.0.4: dependencies: has "^1.0.1" +is-regex@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== + dependencies: + has "^1.0.3" + is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" @@ -15726,6 +16172,13 @@ is-root@2.0.0: resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.0.0.tgz#838d1e82318144e5a6f77819d90207645acc7019" integrity sha512-F/pJIk8QD6OX5DNhRB7hWamLsUilmkDGho48KbgZ6xg/lmAZXHxzXQ91jzB3yRSw5kdQGGGc4yz8HYhTYIMWPg== +is-ssh@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.1.tgz#f349a8cadd24e65298037a522cf7520f2e81a0f3" + integrity sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg== + dependencies: + protocols "^1.1.0" + is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -15765,6 +16218,13 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.0" +is-symbol@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== + dependencies: + has-symbols "^1.0.1" + is-type@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/is-type/-/is-type-0.0.1.tgz#f651d85c365d44955d14a51d8d7061f3f6b4779c" @@ -15824,6 +16284,11 @@ is-wsl@^1.1.0: resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= +is-wsl@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.1.1.tgz#4a1c152d429df3d441669498e2486d3596ebaf1d" + integrity sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog== + is-yarn-global@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" @@ -15924,7 +16389,7 @@ istanbul-lib-coverage@^2.0.0: resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.0.tgz#905e71212052ffb34f2eb008102230bff03940b5" integrity sha512-yMSw5xLIbdaxiVXHk3amfNM2WeBxLrwH/BCyZ9HvA/fylwziAIJOG2rKqWyLqEJqwKT725vxxqidv+SyynnGAA== -istanbul-lib-coverage@^2.0.1: +istanbul-lib-coverage@^2.0.1, istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== @@ -15949,6 +16414,19 @@ istanbul-lib-instrument@^2.2.0: istanbul-lib-coverage "^2.0.1" semver "^5.5.0" +istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630" + integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA== + dependencies: + "@babel/generator" "^7.4.0" + "@babel/parser" "^7.4.3" + "@babel/template" "^7.4.0" + "@babel/traverse" "^7.4.3" + "@babel/types" "^7.4.0" + istanbul-lib-coverage "^2.0.5" + semver "^6.0.0" + istanbul-lib-report@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.0.tgz#99c161979ec202f4a638abd8dc77fab8f9abce53" @@ -15958,6 +16436,15 @@ istanbul-lib-report@^2.0.0: make-dir "^1.3.0" supports-color "^5.4.0" +istanbul-lib-report@^2.0.4: + version "2.0.8" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33" + integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ== + dependencies: + istanbul-lib-coverage "^2.0.5" + make-dir "^2.1.0" + supports-color "^6.1.0" + istanbul-lib-source-maps@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-2.0.0.tgz#4f66403bdbf9f468ccfadd4557878077c26335ba" @@ -15969,6 +16456,17 @@ istanbul-lib-source-maps@^2.0.0: rimraf "^2.6.2" source-map "^0.6.1" +istanbul-lib-source-maps@^3.0.1: + version "3.0.6" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8" + integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^2.0.5" + make-dir "^2.1.0" + rimraf "^2.6.3" + source-map "^0.6.1" + istanbul-reports@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.0.tgz#c6c2867fa65f59eb7dcedb7f845dfc76aaee70f9" @@ -15976,6 +16474,13 @@ istanbul-reports@^1.5.0: dependencies: handlebars "^4.0.11" +istanbul-reports@^2.2.6: + version "2.2.7" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.7.tgz#5d939f6237d7b48393cc0959eab40cd4fd056931" + integrity sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg== + dependencies: + html-escaper "^2.0.0" + istextorbinary@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-1.0.2.tgz#ace19354d1a9a0173efeb1084ce0f87b0ad7decf" @@ -15997,6 +16502,11 @@ iterall@^1.1.3, iterall@^1.2.1: resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7" integrity sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA== +java-properties@^0.2.9: + version "0.2.10" + resolved "https://registry.yarnpkg.com/java-properties/-/java-properties-0.2.10.tgz#2551560c25fa1ad94d998218178f233ad9b18f60" + integrity sha512-CpKJh9VRNhS+XqZtg1UMejETGEiqwCGDC/uwPEEQwc2nfdbSm73SIE29TplG2gLYuBOOTNDqxzG6A9NtEPLt0w== + jazzicon@^1.2.0: version "1.5.0" resolved "https://registry.yarnpkg.com/jazzicon/-/jazzicon-1.5.0.tgz#d7f36b516023db39ee6eac117f4054e937b65e99" @@ -16011,6 +16521,360 @@ jed@1.1.1: resolved "https://registry.yarnpkg.com/jed/-/jed-1.1.1.tgz#7a549bbd9ffe1585b0cd0a191e203055bee574b4" integrity sha1-elSbvZ/+FYWwzQoZHiAwVb7ldLQ= +jest-changed-files@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.9.0.tgz#08d8c15eb79a7fa3fc98269bc14b451ee82f8039" + integrity sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg== + dependencies: + "@jest/types" "^24.9.0" + execa "^1.0.0" + throat "^4.0.0" + +jest-cli@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.9.0.tgz#ad2de62d07472d419c6abc301fc432b98b10d2af" + integrity sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg== + dependencies: + "@jest/core" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" + chalk "^2.0.1" + exit "^0.1.2" + import-local "^2.0.0" + is-ci "^2.0.0" + jest-config "^24.9.0" + jest-util "^24.9.0" + jest-validate "^24.9.0" + prompts "^2.0.1" + realpath-native "^1.1.0" + yargs "^13.3.0" + +jest-config@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.9.0.tgz#fb1bbc60c73a46af03590719efa4825e6e4dd1b5" + integrity sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ== + dependencies: + "@babel/core" "^7.1.0" + "@jest/test-sequencer" "^24.9.0" + "@jest/types" "^24.9.0" + babel-jest "^24.9.0" + chalk "^2.0.1" + glob "^7.1.1" + jest-environment-jsdom "^24.9.0" + jest-environment-node "^24.9.0" + jest-get-type "^24.9.0" + jest-jasmine2 "^24.9.0" + jest-regex-util "^24.3.0" + jest-resolve "^24.9.0" + jest-util "^24.9.0" + jest-validate "^24.9.0" + micromatch "^3.1.10" + pretty-format "^24.9.0" + realpath-native "^1.1.0" + +jest-diff@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da" + integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ== + dependencies: + chalk "^2.0.1" + diff-sequences "^24.9.0" + jest-get-type "^24.9.0" + pretty-format "^24.9.0" + +jest-docblock@^24.3.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.9.0.tgz#7970201802ba560e1c4092cc25cbedf5af5a8ce2" + integrity sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA== + dependencies: + detect-newline "^2.1.0" + +jest-each@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.9.0.tgz#eb2da602e2a610898dbc5f1f6df3ba86b55f8b05" + integrity sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog== + dependencies: + "@jest/types" "^24.9.0" + chalk "^2.0.1" + jest-get-type "^24.9.0" + jest-util "^24.9.0" + pretty-format "^24.9.0" + +jest-environment-jsdom@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz#4b0806c7fc94f95edb369a69cc2778eec2b7375b" + integrity sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA== + dependencies: + "@jest/environment" "^24.9.0" + "@jest/fake-timers" "^24.9.0" + "@jest/types" "^24.9.0" + jest-mock "^24.9.0" + jest-util "^24.9.0" + jsdom "^11.5.1" + +jest-environment-node@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.9.0.tgz#333d2d2796f9687f2aeebf0742b519f33c1cbfd3" + integrity sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA== + dependencies: + "@jest/environment" "^24.9.0" + "@jest/fake-timers" "^24.9.0" + "@jest/types" "^24.9.0" + jest-mock "^24.9.0" + jest-util "^24.9.0" + +jest-get-type@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e" + integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q== + +jest-haste-map@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.9.0.tgz#b38a5d64274934e21fa417ae9a9fbeb77ceaac7d" + integrity sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ== + dependencies: + "@jest/types" "^24.9.0" + anymatch "^2.0.0" + fb-watchman "^2.0.0" + graceful-fs "^4.1.15" + invariant "^2.2.4" + jest-serializer "^24.9.0" + jest-util "^24.9.0" + jest-worker "^24.9.0" + micromatch "^3.1.10" + sane "^4.0.3" + walker "^1.0.7" + optionalDependencies: + fsevents "^1.2.7" + +jest-jasmine2@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz#1f7b1bd3242c1774e62acabb3646d96afc3be6a0" + integrity sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw== + dependencies: + "@babel/traverse" "^7.1.0" + "@jest/environment" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" + chalk "^2.0.1" + co "^4.6.0" + expect "^24.9.0" + is-generator-fn "^2.0.0" + jest-each "^24.9.0" + jest-matcher-utils "^24.9.0" + jest-message-util "^24.9.0" + jest-runtime "^24.9.0" + jest-snapshot "^24.9.0" + jest-util "^24.9.0" + pretty-format "^24.9.0" + throat "^4.0.0" + +jest-leak-detector@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz#b665dea7c77100c5c4f7dfcb153b65cf07dcf96a" + integrity sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA== + dependencies: + jest-get-type "^24.9.0" + pretty-format "^24.9.0" + +jest-matcher-utils@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz#f5b3661d5e628dffe6dd65251dfdae0e87c3a073" + integrity sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA== + dependencies: + chalk "^2.0.1" + jest-diff "^24.9.0" + jest-get-type "^24.9.0" + pretty-format "^24.9.0" + +jest-message-util@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.9.0.tgz#527f54a1e380f5e202a8d1149b0ec872f43119e3" + integrity sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw== + dependencies: + "@babel/code-frame" "^7.0.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" + "@types/stack-utils" "^1.0.1" + chalk "^2.0.1" + micromatch "^3.1.10" + slash "^2.0.0" + stack-utils "^1.0.1" + +jest-mock@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.9.0.tgz#c22835541ee379b908673ad51087a2185c13f1c6" + integrity sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w== + dependencies: + "@jest/types" "^24.9.0" + +jest-pnp-resolver@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" + integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== + +jest-regex-util@^24.3.0, jest-regex-util@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.9.0.tgz#c13fb3380bde22bf6575432c493ea8fe37965636" + integrity sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA== + +jest-resolve-dependencies@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz#ad055198959c4cfba8a4f066c673a3f0786507ab" + integrity sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g== + dependencies: + "@jest/types" "^24.9.0" + jest-regex-util "^24.3.0" + jest-snapshot "^24.9.0" + +jest-resolve@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.9.0.tgz#dff04c7687af34c4dd7e524892d9cf77e5d17321" + integrity sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ== + dependencies: + "@jest/types" "^24.9.0" + browser-resolve "^1.11.3" + chalk "^2.0.1" + jest-pnp-resolver "^1.2.1" + realpath-native "^1.1.0" + +jest-runner@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.9.0.tgz#574fafdbd54455c2b34b4bdf4365a23857fcdf42" + integrity sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg== + dependencies: + "@jest/console" "^24.7.1" + "@jest/environment" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" + chalk "^2.4.2" + exit "^0.1.2" + graceful-fs "^4.1.15" + jest-config "^24.9.0" + jest-docblock "^24.3.0" + jest-haste-map "^24.9.0" + jest-jasmine2 "^24.9.0" + jest-leak-detector "^24.9.0" + jest-message-util "^24.9.0" + jest-resolve "^24.9.0" + jest-runtime "^24.9.0" + jest-util "^24.9.0" + jest-worker "^24.6.0" + source-map-support "^0.5.6" + throat "^4.0.0" + +jest-runtime@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.9.0.tgz#9f14583af6a4f7314a6a9d9f0226e1a781c8e4ac" + integrity sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw== + dependencies: + "@jest/console" "^24.7.1" + "@jest/environment" "^24.9.0" + "@jest/source-map" "^24.3.0" + "@jest/transform" "^24.9.0" + "@jest/types" "^24.9.0" + "@types/yargs" "^13.0.0" + chalk "^2.0.1" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.1.15" + jest-config "^24.9.0" + jest-haste-map "^24.9.0" + jest-message-util "^24.9.0" + jest-mock "^24.9.0" + jest-regex-util "^24.3.0" + jest-resolve "^24.9.0" + jest-snapshot "^24.9.0" + jest-util "^24.9.0" + jest-validate "^24.9.0" + realpath-native "^1.1.0" + slash "^2.0.0" + strip-bom "^3.0.0" + yargs "^13.3.0" + +jest-serializer@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.9.0.tgz#e6d7d7ef96d31e8b9079a714754c5d5c58288e73" + integrity sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ== + +jest-snapshot@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.9.0.tgz#ec8e9ca4f2ec0c5c87ae8f925cf97497b0e951ba" + integrity sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew== + dependencies: + "@babel/types" "^7.0.0" + "@jest/types" "^24.9.0" + chalk "^2.0.1" + expect "^24.9.0" + jest-diff "^24.9.0" + jest-get-type "^24.9.0" + jest-matcher-utils "^24.9.0" + jest-message-util "^24.9.0" + jest-resolve "^24.9.0" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + pretty-format "^24.9.0" + semver "^6.2.0" + +jest-util@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.9.0.tgz#7396814e48536d2e85a37de3e4c431d7cb140162" + integrity sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg== + dependencies: + "@jest/console" "^24.9.0" + "@jest/fake-timers" "^24.9.0" + "@jest/source-map" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" + callsites "^3.0.0" + chalk "^2.0.1" + graceful-fs "^4.1.15" + is-ci "^2.0.0" + mkdirp "^0.5.1" + slash "^2.0.0" + source-map "^0.6.0" + +jest-validate@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.9.0.tgz#0775c55360d173cd854e40180756d4ff52def8ab" + integrity sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ== + dependencies: + "@jest/types" "^24.9.0" + camelcase "^5.3.1" + chalk "^2.0.1" + jest-get-type "^24.9.0" + leven "^3.1.0" + pretty-format "^24.9.0" + +jest-watcher@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.9.0.tgz#4b56e5d1ceff005f5b88e528dc9afc8dd4ed2b3b" + integrity sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw== + dependencies: + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" + "@types/yargs" "^13.0.0" + ansi-escapes "^3.0.0" + chalk "^2.0.1" + jest-util "^24.9.0" + string-length "^2.0.0" + +jest-worker@^24.6.0, jest-worker@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5" + integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw== + dependencies: + merge-stream "^2.0.0" + supports-color "^6.1.0" + +jest@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-24.9.0.tgz#987d290c05a08b52c56188c1002e368edb007171" + integrity sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw== + dependencies: + import-local "^2.0.0" + jest-cli "^24.9.0" + jmespath@^0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" @@ -16179,6 +17043,38 @@ jsdom@^11.2.0: whatwg-url "^6.3.0" xml-name-validator "^2.0.1" +jsdom@^11.5.1: + version "11.12.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8" + integrity sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw== + dependencies: + abab "^2.0.0" + acorn "^5.5.3" + acorn-globals "^4.1.0" + array-equal "^1.0.0" + cssom ">= 0.3.2 < 0.4.0" + cssstyle "^1.0.0" + data-urls "^1.0.0" + domexception "^1.0.1" + escodegen "^1.9.1" + html-encoding-sniffer "^1.0.2" + left-pad "^1.3.0" + nwsapi "^2.0.7" + parse5 "4.0.0" + pn "^1.1.0" + request "^2.87.0" + request-promise-native "^1.0.5" + sax "^1.2.4" + symbol-tree "^3.2.2" + tough-cookie "^2.3.4" + w3c-hr-time "^1.0.1" + webidl-conversions "^4.0.2" + whatwg-encoding "^1.0.3" + whatwg-mimetype "^2.1.0" + whatwg-url "^6.4.1" + ws "^5.2.0" + xml-name-validator "^3.0.0" + jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" @@ -16310,7 +17206,7 @@ json-stringify-deterministic@^1.0.1: resolved "https://registry.yarnpkg.com/json-stringify-deterministic/-/json-stringify-deterministic-1.0.1.tgz#3334798c374d723d46f7ba0e47d6e5e5ac8511f9" integrity sha512-9Fg0OY3uyzozpvJ8TVbUk09PjzhT7O2Q5kEe30g6OrKhbA/Is92igcx0XDDX7E3yAwnIlUcYLRl+ZkVrBYVP7A== -json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: +json-stringify-safe@5.0.x, json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= @@ -16353,6 +17249,13 @@ json5@^2.1.0: dependencies: minimist "^1.2.0" +json5@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6" + integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ== + dependencies: + minimist "^1.2.0" + jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" @@ -16743,6 +17646,11 @@ klaw@^3.0.0: dependencies: graceful-fs "^4.1.9" +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + knex@^0.15.2: version "0.15.2" resolved "https://registry.yarnpkg.com/knex/-/knex-0.15.2.tgz#6059b87489605f4cc87599a6d2a9d265709e9340" @@ -16869,16 +17777,16 @@ lazy-cache@^1.0.3: resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= -lazy-universal-dotenv@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lazy-universal-dotenv/-/lazy-universal-dotenv-2.0.0.tgz#e015ad9f77be9ef811956d53ea9519b1c0ab0214" - integrity sha512-1Wi0zgZMfRLaRAK21g3odYuU+HE1d85Loe2tb44YhcNwIzhmD49mTPR9aKckpB9Q9Q9mA+hUMLI2xlkcCAe3yw== +lazy-universal-dotenv@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.1.tgz#a6c8938414bca426ab8c9463940da451a911db38" + integrity sha512-prXSYk799h3GY3iOWnC6ZigYzMPjxN2svgjJ9shk7oMadSNX3wXy0B6F32PMJv7qtMnrIbUxoEHzbutvxR2LBQ== dependencies: - "@babel/runtime" "^7.0.0" + "@babel/runtime" "^7.5.0" app-root-dir "^1.0.2" - core-js "^2.5.7" - dotenv "^6.0.0" - dotenv-expand "^4.2.0" + core-js "^3.0.4" + dotenv "^8.0.0" + dotenv-expand "^5.1.0" lazystream@^1.0.0: version "1.0.0" @@ -16925,6 +17833,11 @@ left-pad@^1.2.0: resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.2.0.tgz#d30a73c6b8201d8f7d8e7956ba9616087a68e0ee" integrity sha1-0wpzxrggHY99jnlWupYWCHpo4O4= +left-pad@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" + integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA== + length-prefixed-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/length-prefixed-stream/-/length-prefixed-stream-2.0.0.tgz#16e603c97aefb46f43ae4b5d22f1734ecd14ffce" @@ -17140,6 +18053,11 @@ leven@2.1.0, leven@^2.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -17588,6 +18506,11 @@ lil-uuid@^0.1.1: resolved "https://registry.yarnpkg.com/lil-uuid/-/lil-uuid-0.1.1.tgz#f9edcf23f00e42bf43f0f843d98d8b53f3341f16" integrity sha1-+e3PI/AOQr9D8PhD2Y2LU/M0HxY= +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + linked-list@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/linked-list/-/linked-list-0.1.0.tgz#798b0ff97d1b92a4fd08480f55aea4e9d49d37bf" @@ -17636,7 +18559,7 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" -loader-runner@^2.3.0: +loader-runner@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== @@ -17722,7 +18645,7 @@ lockfile-lint@^3.0.5: lockfile-lint-api "^5.0.4" yargs "^15.0.2" -lodash-es@^4.17.11, lodash-es@^4.2.1: +lodash-es@^4.2.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78" integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ== @@ -18176,13 +19099,13 @@ lowercase-keys@^2.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== -lowlight@~1.9.1: - version "1.9.2" - resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.9.2.tgz#0b9127e3cec2c3021b7795dd81005c709a42fdd1" - integrity sha512-Ek18ElVCf/wF/jEm1b92gTnigh94CtBNWiZ2ad+vTgW7cTmQxUY3I98BjHK68gZAJEWmybGBZgx9qv3QxLQB/Q== +lowlight@~1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.11.0.tgz#1304d83005126d4e8b1dc0f07981e9b689ec2efc" + integrity sha512-xrGGN6XLL7MbTMdPD6NfWPwY43SNkjf/d0mecSx/CW36fUZTjRHEq0/Cdug3TWKtRXLWi7iMl1eP0olYxj/a4A== dependencies: fault "^1.0.2" - highlight.js "~9.12.0" + highlight.js "~9.13.0" lpad-align@^1.0.1: version "1.1.2" @@ -18266,7 +19189,7 @@ make-dir@^1.0.0, make-dir@^1.2.0, make-dir@^1.3.0: dependencies: pify "^3.0.0" -make-dir@^2.0.0: +make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== @@ -18288,6 +19211,13 @@ make-iterator@^1.0.0: dependencies: kind-of "^6.0.2" +makeerror@1.0.x: + version "1.0.11" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" + integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= + dependencies: + tmpl "1.0.x" + mamacro@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" @@ -18371,15 +19301,6 @@ marked@^0.6.2: resolved "https://registry.yarnpkg.com/marked/-/marked-0.6.2.tgz#c574be8b545a8b48641456ca1dbe0e37b6dccc1a" integrity sha512-LqxwVH3P/rqKX4EKGz7+c2G9r98WeM/SW34ybhgNGhUQNKtf1GmmSkJ6cDGJ/t6tiyae49qRkpyTw2B9HOrgUA== -marksy@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/marksy/-/marksy-7.0.1.tgz#fb26f780ce56bf5ca48fc137efdef1f97dd4c7ef" - integrity sha512-tB4cQxIY7f8PWTcIouJO/V60rl9JVVOmCDjmukYVO7mdpGM1JWl4qIP98iDYItexSXZ0DkEqk6yXFxgdmZRMxA== - dependencies: - babel-standalone "^6.26.0" - he "^1.1.1" - marked "^0.6.2" - matchdep@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e" @@ -18549,7 +19470,7 @@ memoizerific@^1.11.3: dependencies: map-or-similar "^1.5.0" -memory-fs@^0.4.0, memory-fs@^0.4.1, memory-fs@~0.4.1: +memory-fs@^0.4.0, memory-fs@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= @@ -18557,6 +19478,11 @@ memory-fs@^0.4.0, memory-fs@^0.4.1, memory-fs@~0.4.1: errno "^0.1.3" readable-stream "^2.0.1" +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= + meow@^3.1.0, meow@^3.3.0, meow@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" @@ -18623,6 +19549,11 @@ merge-source-map@^1.1.0: dependencies: source-map "^0.6.1" +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + merge2@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" @@ -18717,7 +19648,7 @@ micromatch@^2.1.5, micromatch@^2.3.7: parse-glob "^3.0.4" regex-cache "^0.4.2" -micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -18815,11 +19746,16 @@ mime@^1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== -mime@^2.0.3, mime@^2.3.1, mime@^2.4.2: +mime@^2.3.1, mime@^2.4.2: version "2.4.3" resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.3.tgz#229687331e86f68924e6cb59e1cdd937f18275fe" integrity sha512-QgrPRJfE+riq5TPZMcHZOtm8c6K/yYrMbKIoRfapfiGLxS8OTeIfRhUGW5LU7MlRa52KOAGCfUNruqLrIBvWZw== +mime@^2.4.4: + version "2.4.4" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" + integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== + mimic-fn@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" @@ -18842,6 +19778,11 @@ min-document@^2.19.0: dependencies: dom-walk "^0.1.0" +min-indent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.0.tgz#cfc45c37e9ec0d8f0a0ec3dd4ef7f7c3abe39256" + integrity sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY= + mini-create-react-context@^0.3.0: version "0.3.2" resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.3.2.tgz#79fc598f283dd623da8e088b05db8cddab250189" @@ -18851,10 +19792,10 @@ mini-create-react-context@^0.3.0: gud "^1.0.0" tiny-warning "^1.0.2" -mini-css-extract-plugin@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.7.0.tgz#5ba8290fbb4179a43dd27cca444ba150bee743a0" - integrity sha512-RQIw6+7utTYn8DBGsf/LpRgZCJMpZt+kuawJ/fju0KiOL6nAaTBNmCJwS7HtwSCXfS47gCkmtBFS7HdsquhdxQ== +mini-css-extract-plugin@^0.8.0: + version "0.8.2" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.2.tgz#a875e169beb27c88af77dd962771c9eedc3da161" + integrity sha512-a3Y4of27Wz+mqK3qrcd3VhYz6cU0iW5x3Sgvqzbj+XmlrSizmvu8QQMl5oMYJjgHOC4iyt+w7l4umP+dQeW3bw== dependencies: loader-utils "^1.1.0" normalize-url "1.9.1" @@ -18911,6 +19852,27 @@ minimist@~0.0.1: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= +minipass-collect@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" + integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== + dependencies: + minipass "^3.0.0" + +minipass-flush@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== + dependencies: + minipass "^3.0.0" + +minipass-pipeline@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.2.tgz#3dcb6bb4a546e32969c7ad710f2c79a86abba93a" + integrity sha512-3JS5A2DKhD2g0Gg8x3yamO0pj7YeKGwVlDS90pF++kxptwx/F+B//roxf9SqYil5tQo65bijy+dAuAFZmYOouA== + dependencies: + minipass "^3.0.0" + minipass@^2.2.0, minipass@^2.2.1, minipass@^2.2.4, minipass@^2.3.4: version "2.3.5" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" @@ -18927,6 +19889,13 @@ minipass@^2.6.4: safe-buffer "^5.1.2" yallist "^3.0.0" +minipass@^3.0.0, minipass@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5" + integrity sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w== + dependencies: + yallist "^4.0.0" + minizlib@^1.1.0, minizlib@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" @@ -19058,6 +20027,11 @@ module-not-found-error@^1.0.0: resolved "https://registry.yarnpkg.com/module-not-found-error/-/module-not-found-error-1.0.1.tgz#cf8b4ff4f29640674d6cdd02b0e3bc523c2bbdc0" integrity sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA= +moment@^2.18.1: + version "2.24.0" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" + integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== + moo@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/moo/-/moo-0.4.3.tgz#3f847a26f31cf625a956a87f2b10fbc013bfd10e" @@ -19321,6 +20295,11 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + mz@^2.6.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -19449,16 +20428,11 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -neo-async@^2.5.0, neo-async@^2.6.0: +neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== -nested-object-assign@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/nested-object-assign/-/nested-object-assign-1.0.3.tgz#5aca69390d9affe5a612152b5f0843ae399ac597" - integrity sha512-kgq1CuvLyUcbcIuTiCA93cQ2IJFSlRwXcN+hLcb2qLJwC2qrePHGZZa7IipyWqaWF6tQjdax2pQnVxdq19Zzwg== - netmask@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/netmask/-/netmask-1.0.6.tgz#20297e89d86f6f6400f250d9f4f6b4c1945fcd35" @@ -19507,6 +20481,11 @@ nock@^9.0.14: qs "^6.5.1" semver "^5.3.0" +node-ask@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/node-ask/-/node-ask-1.0.1.tgz#caaa1076cc58e0364267a0903e3eadfac158396b" + integrity sha1-yqoQdsxY4DZCZ6CQPj6t+sFYOWs= + node-dir@^0.1.10: version "0.1.17" resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" @@ -19565,10 +20544,15 @@ node-gyp@^3.8.0: tar "^2.0.0" which "1" -node-libs-browser@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.0.tgz#c72f60d9d46de08a940dedbb25f3ffa2f9bbaa77" - integrity sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA== +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + +node-libs-browser@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== dependencies: assert "^1.1.1" browserify-zlib "^0.2.0" @@ -19580,7 +20564,7 @@ node-libs-browser@^2.0.0: events "^3.0.0" https-browserify "^1.0.0" os-browserify "^0.3.0" - path-browserify "0.0.0" + path-browserify "0.0.1" process "^0.11.10" punycode "^1.2.4" querystring-es3 "^0.2.0" @@ -19592,7 +20576,16 @@ node-libs-browser@^2.0.0: tty-browserify "0.0.0" url "^0.11.0" util "^0.11.0" - vm-browserify "0.0.4" + vm-browserify "^1.0.1" + +node-loggly-bulk@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/node-loggly-bulk/-/node-loggly-bulk-2.2.4.tgz#bdd8638d97c43ecf1e1831ca98b250968fa6dee9" + integrity sha512-DfhtsDfkSBU6Dp1zvK+H1MgHRcA2yb4z07ctyA6uo+bNwKtv1exhohN910zcWNkdSYq1TImCq+O+3bOTuYHvmQ== + dependencies: + json-stringify-safe "5.0.x" + moment "^2.18.1" + request ">=2.76.0 <3.0.0" node-modules-regexp@^1.0.0: version "1.0.0" @@ -19610,6 +20603,17 @@ node-notifier@^5.0.1: shellwords "^0.1.1" which "^1.3.0" +node-notifier@^5.4.2: + version "5.4.3" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.3.tgz#cb72daf94c93904098e28b9c590fd866e464bd50" + integrity sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q== + dependencies: + growly "^1.3.0" + is-wsl "^1.1.0" + semver "^5.5.0" + shellwords "^0.1.1" + which "^1.3.0" + node-pre-gyp@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz#db1f33215272f692cd38f03238e3e9b47c5dd054" @@ -19672,6 +20676,13 @@ node-releases@^1.1.29: dependencies: semver "^5.3.0" +node-releases@^1.1.46: + version "1.1.47" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.47.tgz#c59ef739a1fd7ecbd9f0b7cf5b7871e8a8b591e4" + integrity sha512-k4xjVPx5FpwBUj0Gw7uvFOTF4Ep8Hok1I6qjwL3pLfwe7Y0REQSAqOwwv9TWBCUtMHxcXfY4PgRLRozcChvTcA== + dependencies: + semver "^6.3.0" + node-sass@^4.12.0, node-sass@^4.8.3: version "4.12.0" resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.12.0.tgz#0914f531932380114a30cc5fa4fa63233a25f017" @@ -19795,7 +20806,7 @@ normalize-selector@^0.2.0: resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= -normalize-url@1.9.1, normalize-url@^1.0.0: +normalize-url@1.9.1, normalize-url@^1.0.0, normalize-url@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= @@ -19847,6 +20858,21 @@ npm-packlist@^1.1.6: ignore-walk "^3.0.1" npm-bundled "^1.0.1" +npm-run-all@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" + integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ== + dependencies: + ansi-styles "^3.2.1" + chalk "^2.4.1" + cross-spawn "^6.0.5" + memorystream "^0.3.1" + minimatch "^3.0.4" + pidtree "^0.3.0" + read-pkg "^3.0.0" + shell-quote "^1.6.1" + string.prototype.padend "^3.0.0" + npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -19919,6 +20945,11 @@ nwmatcher@^1.4.3: resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.4.tgz#2285631f34a95f0d0395cd900c96ed39b58f346e" integrity sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ== +nwsapi@^2.0.7: + version "2.2.0" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" + integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== + nyc@^13.0.0: version "13.0.0" resolved "https://registry.yarnpkg.com/nyc/-/nyc-13.0.0.tgz#e00c26e9bd33ab5e81ede992bbe49308485899b6" @@ -20118,6 +21149,14 @@ object.getownpropertydescriptors@^2.0.3: define-properties "^1.1.2" es-abstract "^1.5.1" +object.getownpropertydescriptors@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" + integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + object.map@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37" @@ -20229,18 +21268,18 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + only@~0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" integrity sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q= -open@^6.1.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/open/-/open-6.3.0.tgz#60d0b845ee38fae0631f5d739a21bd40e3d2a527" - integrity sha512-6AHdrJxPvAXIowO/aIaeHZ8CeMdDf7qCyRNq8NwJpinmCdXhz+NZR7ie1Too94lpciCDsG+qHGO9Mt0svA4OqA== - dependencies: - is-wsl "^1.1.0" - open@^6.3.0: version "6.4.0" resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" @@ -20248,6 +21287,13 @@ open@^6.3.0: dependencies: is-wsl "^1.1.0" +open@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/open/-/open-7.0.0.tgz#7e52999b14eb73f90f0f0807fe93897c4ae73ec9" + integrity sha512-K6EKzYqnwQzk+/dzJAQSBORub3xlBTxMz+ntpZpH/LyCa1o6KjXhuN+2npAaI9jaSmU3R1Q8NWf4KUWcyytGsQ== + dependencies: + is-wsl "^2.1.0" + opencollective-postinstall@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89" @@ -20258,6 +21304,11 @@ opener@~1.4.0: resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8" integrity sha1-XG2ixdflgx6P+jlklQ+NZnSskLg= +openurl@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/openurl/-/openurl-1.1.1.tgz#3875b4b0ef7a52c156f0db41d4609dbb0f94b387" + integrity sha1-OHW0sO96UsFW8NtB1GCduw+Us4c= + opn@5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.4.0.tgz#cb545e7aab78562beb11aa3bfabc7042e1761035" @@ -20504,7 +21555,7 @@ os-locale@^2.0.0: lcid "^1.0.0" mem "^1.1.0" -os-locale@^3.0.0: +os-locale@^3.0.0, os-locale@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== @@ -20651,6 +21702,13 @@ p-map@^2.0.0: resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + p-map@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.1.1.tgz#05f5e4ae97a068371bc2a5cc86bfbdbc19c4ae7a" @@ -20776,7 +21834,7 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" -param-case@2.1.x: +param-case@2.1.x, param-case@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= @@ -20808,6 +21866,16 @@ parse-asn1@^5.0.0: evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" +parse-domain@^2.0.0: + version "2.3.4" + resolved "https://registry.yarnpkg.com/parse-domain/-/parse-domain-2.3.4.tgz#acf46caab0f1b5412b95cdc01a74ba793db15a0d" + integrity sha512-LlFJJVTry4DD3Xa76CsVNP6MIu3JZ8GXd5HEEp38KSDGBCVsnccagAJ5YLy7uEEabvwtauQEQPcvXWgUGkJbMA== + dependencies: + got "^8.3.2" + jest "^24.9.0" + mkdirp "^0.5.1" + npm-run-all "^4.1.5" + parse-entities@^1.0.2, parse-entities@^1.1.0, parse-entities@^1.1.2: version "1.2.2" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.2.tgz#c31bf0f653b6661354f8973559cb86dd1d5edf50" @@ -20862,11 +21930,49 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-json@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" + integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + lines-and-columns "^1.1.6" + parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= +parse-path@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-3.0.4.tgz#a48b7b529da41f34d9d1428602a39b29fc7180e4" + integrity sha512-wP70vtwv2DyrM2YoA7ZHVv4zIXa4P7dGgHlj+VwyXNDduLLVJ7NMY1zsFxjUUJ3DAwJLupGb1H5gMDDiNlJaxw== + dependencies: + is-ssh "^1.3.0" + protocols "^1.4.0" + +parse-repo@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/parse-repo/-/parse-repo-1.0.4.tgz#74b91d2cb8675d11b99976a0065f6ce17fa1bcc8" + integrity sha1-dLkdLLhnXRG5mXagBl9s4X+hvMg= + +parse-url@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-3.0.2.tgz#602787a7063a795d72b8673197505e72f60610be" + integrity sha1-YCeHpwY6eV1yuGcxl1BecvYGEL4= + dependencies: + is-ssh "^1.3.0" + normalize-url "^1.9.1" + parse-path "^3.0.1" + protocols "^1.4.0" + +parse5@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" + integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA== + parse5@^3.0.1, parse5@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" @@ -20908,7 +22014,12 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -path-browserify@0.0.0, path-browserify@~0.0.0: +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== + +path-browserify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo= @@ -21185,6 +22296,11 @@ picomatch@^2.0.5: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA== +pidtree@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.0.tgz#f6fada10fccc9f99bf50e90d0b23d72c9ebc2e6b" + integrity sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg== + pify@^2.0.0, pify@^2.2.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -21232,6 +22348,19 @@ pino-std-serializers@^2.3.0: resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-2.4.2.tgz#cb5e3e58c358b26f88969d7e619ae54bdfcc1ae1" integrity sha512-WaL504dO8eGs+vrK+j4BuQQq6GLKeCCcHaMB2ItygzVURcL1CycwNEUHTD/lHFHs/NL5qAz2UKrjYWXKSf4aMQ== +pino@4.10.2: + version "4.10.2" + resolved "https://registry.yarnpkg.com/pino/-/pino-4.10.2.tgz#77e93cdfa1cdb58f688cbb0abaebe67eb2f315f4" + integrity sha512-hNNDgOju2UvK4iKqXR3ZwEutoOujBRN9jfQgty/X4B3q1QOqpWqvmVn+GT/a20o8Jw5Wd7VkGJAdgFQg55a+mw== + dependencies: + chalk "^2.3.0" + fast-json-parse "^1.0.0" + fast-safe-stringify "^1.2.1" + flatstr "^1.0.4" + pump "^1.0.3" + quick-format-unescaped "^1.1.1" + split2 "^2.2.0" + pino@5.13.3, pino@~5.13.0: version "5.13.3" resolved "https://registry.yarnpkg.com/pino/-/pino-5.13.3.tgz#26cd6f69b4bd03d6408af28eddcd9313687f143d" @@ -21256,7 +22385,7 @@ pino@^5.12.3: quick-format-unescaped "^3.0.2" sonic-boom "^0.7.5" -pirates@^4.0.0: +pirates@^4.0.0, pirates@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== @@ -21336,11 +22465,18 @@ pluralize@^7.0.0: resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== -pn@^1.0.0: +pn@^1.0.0, pn@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== +pnp-webpack-plugin@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.5.0.tgz#62a1cd3068f46d564bb33c56eb250e4d586676eb" + integrity sha512-jd9olUr9D7do+RN8Wspzhpxhgp1n6Vd0NtQ4SFkmIACZoEL1nkyAdW9Ygrinjec0vgDcWjscFQQ1gDW8rsfKTg== + dependencies: + ts-pnp "^1.1.2" + po2json@0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/po2json/-/po2json-0.4.5.tgz#47bb2952da32d58a1be2f256a598eebc0b745118" @@ -21474,6 +22610,16 @@ postcss-modules-local-by-default@^2.0.6: postcss-selector-parser "^6.0.0" postcss-value-parser "^3.3.1" +postcss-modules-local-by-default@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz#e8a6561be914aaf3c052876377524ca90dbb7915" + integrity sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ== + dependencies: + icss-utils "^4.1.1" + postcss "^7.0.16" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.0" + postcss-modules-scope@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz#ad3f5bf7856114f6fcab901b0502e2a2bc39d4eb" @@ -21482,6 +22628,14 @@ postcss-modules-scope@^2.1.0: postcss "^7.0.6" postcss-selector-parser "^6.0.0" +postcss-modules-scope@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.1.1.tgz#33d4fc946602eb5e9355c4165d68a10727689dba" + integrity sha512-OXRUPecnHCg8b9xWvldG/jUpRIGPNRka0r4D4j0ESUU2/5IOnpsjfPPmDprM3Ih8CgZ8FXjWqaniK5v4rWt3oQ== + dependencies: + postcss "^7.0.6" + postcss-selector-parser "^6.0.0" + postcss-modules-values@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz#479b46dc0c5ca3dc7fa5270851836b9ec7152f64" @@ -21490,6 +22644,14 @@ postcss-modules-values@^2.0.0: icss-replace-symbols "^1.1.0" postcss "^7.0.6" +postcss-modules-values@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" + integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== + dependencies: + icss-utils "^4.0.0" + postcss "^7.0.6" + postcss-reporter@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-6.0.1.tgz#7c055120060a97c8837b4e48215661aafb74245f" @@ -21536,7 +22698,7 @@ postcss-selector-parser@^3.1.0: indexes-of "^1.0.1" uniq "^1.0.1" -postcss-selector-parser@^6.0.0: +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== @@ -21560,7 +22722,7 @@ postcss-value-parser@^3.3.1: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.0.0: +postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9" integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ== @@ -21601,6 +22763,15 @@ postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.5, postcss@^7.0.6 source-map "^0.6.1" supports-color "^6.1.0" +postcss@^7.0.23, postcss@^7.0.26: + version "7.0.26" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.26.tgz#5ed615cfcab35ba9bbb82414a4fa88ea10429587" + integrity sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + postmsg-rpc@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/postmsg-rpc/-/postmsg-rpc-2.4.0.tgz#4e2daf6851852364696debd5d6bf6936d1424cdf" @@ -21659,6 +22830,16 @@ pretty-error@^2.1.1: renderkid "^2.0.1" utila "~0.4" +pretty-format@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9" + integrity sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA== + dependencies: + "@jest/types" "^24.9.0" + ansi-regex "^4.0.0" + ansi-styles "^3.2.0" + react-is "^16.8.4" + pretty-hrtime@^1.0.0, pretty-hrtime@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" @@ -21725,6 +22906,14 @@ progress-stream@^1.1.0: speedometer "~0.1.2" through2 "~0.2.3" +progress-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/progress-stream/-/progress-stream-2.0.0.tgz#fac63a0b3d11deacbb0969abcc93b214bce19ed5" + integrity sha1-+sY6Cz0R3qy7CWmrzJOyFLzhntU= + dependencies: + speedometer "~1.0.0" + through2 "~2.0.3" + progress@2.0.0, progress@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" @@ -21735,7 +22924,7 @@ progress@^1.1.8: resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74= -progress@^2.0.1: +progress@^2.0.1, progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -21832,6 +23021,14 @@ promisify-es6@^1.0.3: resolved "https://registry.yarnpkg.com/promisify-es6/-/promisify-es6-1.0.3.tgz#b012668c4df3c965ce13daac2b3a4d1726a96346" integrity sha512-N9iVG+CGJsI4b4ZGazjwLnxErD2d9Pe4DPvvXSxYA9tFNu8ymXME4Qs5HIQ0LMJpNM7zj+m0NlNnNeqFpKzqnA== +prompts@^2.0.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.0.tgz#a444e968fa4cc7e86689a74050685ac8006c4cc4" + integrity sha512-NfbbPPg/74fT7wk2XYQ7hAIp9zJyZp5Fu19iRbORqqy1BhtrkZ0fPafBU+7bmn8ie69DpT0R6QpJIN2oisYjJg== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.3" + prop-types-exact@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/prop-types-exact/-/prop-types-exact-1.2.0.tgz#825d6be46094663848237e3925a98c6e944e9869" @@ -21890,6 +23087,11 @@ protocol-buffers-schema@^3.3.1: resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.3.2.tgz#00434f608b4e8df54c59e070efeefc37fb4bb859" integrity sha512-Xdayp8sB/mU+sUV4G7ws8xtYMGdQnxbeIfLjyO9TZZRJdztBGhlmbI5x1qcY4TG5hBkIKGnc28i7nXxaugu88w== +protocols@^1.1.0, protocols@^1.4.0: + version "1.4.7" + resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.7.tgz#95f788a4f0e979b291ffefcf5636ad113d037d32" + integrity sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg== + protons@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/protons/-/protons-1.0.1.tgz#1c107144c07fc2d1cb8b6cb76451e6a938237676" @@ -21951,6 +23153,11 @@ psl@^1.1.24: resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== +psl@^1.1.28: + version "1.7.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" + integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ== + public-encrypt@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6" @@ -22181,7 +23388,7 @@ pull-ws@hugomrdias/pull-ws#fix/bundle-size: safe-buffer "^5.1.1" ws "^1.1.0" -pump@^1.0.0: +pump@^1.0.0, pump@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw== @@ -22300,6 +23507,13 @@ querystringify@^2.1.1: resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== +quick-format-unescaped@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-1.1.2.tgz#0ca581de3174becef25ac3c2e8956342381db698" + integrity sha1-DKWB3jF0vs7yWsPC6JVjQjgdtpg= + dependencies: + fast-safe-stringify "^1.0.8" + quick-format-unescaped@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-3.0.2.tgz#0137e94d8fb37ffeb70040535111c378e75396fb" @@ -22349,11 +23563,6 @@ radgrad-jsdoc-template@^1.1.3: resolved "https://registry.yarnpkg.com/radgrad-jsdoc-template/-/radgrad-jsdoc-template-1.1.3.tgz#89672ec71b8fbc88281e48b75f89b3b4b965b541" integrity sha512-yk1XB6NlrP6JIr3xHzCrNwCmkONNgqM+sZxFAdmTU/CsaT7N/lns2/Wfa048li3wrao5b6KwYrdu6KgiGh9nIQ== -raf-schd@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.1.tgz#e72f29a96de260dead719f34c29e56fdc1c1473e" - integrity sha512-/QTXV4+Tf81CmJgTZac47N63ZzKmaVe+1cQX/grCFeLrs4Mcc6oq+KJfbF3tFjeS1NF91lmTvgmwYjk02UTo9A== - raf@^3.1.0, raf@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575" @@ -22477,13 +23686,13 @@ raw-body@~1.1.0: bytes "1" string_decoder "0.10" -raw-loader@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-2.0.0.tgz#e2813d9e1e3f80d1bbade5ad082e809679e20c26" - integrity sha512-kZnO5MoIyrojfrPWqrhFNLZemIAX8edMOCp++yC5RKxzFB3m92DqKNhKlU6+FvpOhWtvyh3jOaD7J6/9tpdIKg== +raw-loader@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-3.1.0.tgz#5e9d399a5a222cc0de18f42c3bc5e49677532b3f" + integrity sha512-lzUVMuJ06HF4rYveaz9Tv0WRlUMxJ0Y1hgSkkgg+50iEdaI0TthyEDe08KIHb0XsF6rn8WYTqPCaGTZg3sX+qA== dependencies: loader-utils "^1.1.0" - schema-utils "^1.0.0" + schema-utils "^2.0.1" rc@^1.0.1, rc@^1.1.6, rc@^1.2.1, rc@^1.2.7, rc@^1.2.8: version "1.2.8" @@ -22495,22 +23704,12 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.1, rc@^1.2.7, rc@^1.2.8: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-addons-create-fragment@^15.6.2: - version "15.6.2" - resolved "https://registry.yarnpkg.com/react-addons-create-fragment/-/react-addons-create-fragment-15.6.2.tgz#a394de7c2c7becd6b5475ba1b97ac472ce7c74f8" - integrity sha1-o5TefCx77Na1R1uhuXrEcs58dPg= - dependencies: - fbjs "^0.8.4" - loose-envify "^1.3.1" - object-assign "^4.1.0" - -react-clientside-effect@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.0.tgz#db823695f75e9616a5e4dd6d908e5ea627fb2516" - integrity sha512-cVIsGG7SNHsQsCP4+fw7KFUB0HiYiU8hbvL640XaLCbZ31aK8/lj0qOKJ2K+xRjuQz/IM4Q4qclI0aEqTtcXtA== +react-clientside-effect@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.2.tgz#6212fb0e07b204e714581dd51992603d1accc837" + integrity sha512-nRmoyxeok5PBO6ytPvSjKp9xwXg9xagoTK1mMjwnQxqM9Hd7MNPl+LS1bOSOe+CV2+4fnEquc7H/S8QD3q697A== dependencies: "@babel/runtime" "^7.0.0" - shallowequal "^1.1.0" react-color@^2.17.0: version "2.17.3" @@ -22596,18 +23795,19 @@ react-dnd@^3.0.2: prop-types "^15.5.10" shallowequal "^1.0.2" -react-docgen@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/react-docgen/-/react-docgen-4.1.1.tgz#8fef0212dbf14733e09edecef1de6b224d87219e" - integrity sha512-o1wdswIxbgJRI4pckskE7qumiFyqkbvCO++TylEDOo2RbMiueIOg8YzKU4X9++r0DjrbXePw/LHnh81GRBTWRw== +react-docgen@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/react-docgen/-/react-docgen-5.1.0.tgz#8e69f1d2e9153c535c20162ea1b85878b059b474" + integrity sha512-buAVMVqDEtvC7+VRDRlA9udS9cO9jFfb7yxRvKNYR9MXS0MJwaIe7OjSEydNzH9oH7LND3whDE+koFDUBtF3zA== dependencies: - "@babel/core" "^7.0.0" - "@babel/runtime" "^7.0.0" + "@babel/core" "^7.7.5" + "@babel/runtime" "^7.7.6" + ast-types "^0.13.2" async "^2.1.4" commander "^2.19.0" doctrine "^3.0.0" node-dir "^0.1.10" - recast "^0.17.3" + strip-indent "^3.0.0" react-dom@^16.12.0: version "16.12.0" @@ -22629,32 +23829,14 @@ react-dom@^16.8.3: prop-types "^15.6.2" scheduler "^0.17.0" -react-dom@^16.8.4: - version "16.8.6" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f" - integrity sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.13.6" - -react-draggable@^3.1.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-3.3.0.tgz#2ed7ea3f92e7d742d747f9e6324860606cd4d997" - integrity sha512-U7/jD0tAW4T0S7DCPK0kkKLyL0z61sC/eqU+NUfDjnq+JtBKaYKDHpsK2wazctiA4alEzCXUnzkREoxppOySVw== +react-draggable@^4.0.3: + version "4.2.0" + resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.2.0.tgz#40cc5209082ca7d613104bf6daf31372cc0e1114" + integrity sha512-5wFq//gEoeTYprnd4ze8GrFc+Rbnx+9RkOMR3vk4EbWxj02U6L6T3yrlKeiw4X5CtjD2ma2+b3WujghcXNRzkw== dependencies: classnames "^2.2.5" prop-types "^15.6.0" -react-element-to-jsx-string@^14.0.2: - version "14.0.2" - resolved "https://registry.yarnpkg.com/react-element-to-jsx-string/-/react-element-to-jsx-string-14.0.2.tgz#586d248bb2416855aa6ac3881e18726832c146d2" - integrity sha512-eYcPUg3FJisgAb8q3sSdce8F/xMZD/iFEjMZYnkE3b7gPi5OamGr2Hst/1pE72mzn7//dfYPXb+UqPK2xdSGsg== - dependencies: - is-plain-object "2.0.4" - stringify-object "3.2.2" - react-error-overlay@^5.1.6: version "5.1.6" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-5.1.6.tgz#0cd73407c5d141f9638ae1e0c63e7b2bf7e9929d" @@ -22675,15 +23857,17 @@ react-fast-compare@2.0.4: resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== -react-focus-lock@^1.18.3: - version "1.19.1" - resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-1.19.1.tgz#2f3429793edaefe2d077121f973ce5a3c7a0651a" - integrity sha512-TPpfiack1/nF4uttySfpxPk4rGZTLXlaZl7ncZg/ELAk24Iq2B1UUaUioID8H8dneUXqznT83JTNDHDj+kwryw== +react-focus-lock@^2.1.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.2.1.tgz#1d12887416925dc53481914b7cedd39494a3b24a" + integrity sha512-47g0xYcCTZccdzKRGufepY8oZ3W1Qg+2hn6u9SHZ0zUB6uz/4K4xJe7yYFNZ1qT6m+2JDm82F6QgKeBTbjW4PQ== dependencies: "@babel/runtime" "^7.0.0" - focus-lock "^0.6.3" + focus-lock "^0.6.6" prop-types "^15.6.2" - react-clientside-effect "^1.2.0" + react-clientside-effect "^1.2.2" + use-callback-ref "^1.2.1" + use-sidecar "^1.0.1" react-helmet-async@^1.0.2: version "1.0.2" @@ -22696,10 +23880,10 @@ react-helmet-async@^1.0.2: react-fast-compare "2.0.4" shallowequal "1.1.0" -react-hotkeys@2.0.0-pre4: - version "2.0.0-pre4" - resolved "https://registry.yarnpkg.com/react-hotkeys/-/react-hotkeys-2.0.0-pre4.tgz#a1c248a51bdba4282c36bf3204f80d58abc73333" - integrity sha512-oa+UncSWyOwMK3GExt+oELXaR7T3ItgcMolsupQFdKvwkEhVAluJd5rYczsRSQpQlVkdNoHG46De2NUeuS+88Q== +react-hotkeys@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/react-hotkeys/-/react-hotkeys-2.0.0.tgz#a7719c7340cbba888b0e9184f806a9ec0ac2c53f" + integrity sha512-3n3OU8vLX/pfcJrR3xJ1zlww6KS1kEJt0Whxc4FiGV+MJrQ1mYSYI3qS/11d2MJDFm8IhOXMTFQirfu6AVOF6Q== dependencies: prop-types "^15.6.1" @@ -22730,14 +23914,15 @@ react-inspector@^2.3.0: babel-runtime "^6.26.0" is-dom "^1.0.9" -react-inspector@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/react-inspector/-/react-inspector-3.0.2.tgz#c530a06101f562475537e47df428e1d7aff16ed8" - integrity sha512-PSR8xDoGFN8R3LKmq1NT+hBBwhxjd9Qwz8yKY+5NXY/CHpxXHm01CVabxzI7zFwFav/M3JoC/Z0Ro2kSX6Ef2Q== +react-inspector@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/react-inspector/-/react-inspector-4.0.0.tgz#ad73200ca18452aff333df2e2791be4544c422a9" + integrity sha512-heh4THBeJg0HLYO/3VBAOaFPkdEHoTZq9VFgP4rOzGw/jyqdVd5spfXSl3LNB1fwrwaWef75Q1hCuwlY4GaKjQ== dependencies: babel-runtime "^6.26.0" is-dom "^1.0.9" prop-types "^15.6.1" + storybook-chromatic "^2.2.2" react-is@^16.10.2, react-is@^16.6.0, react-is@^16.8.6, react-is@^16.9.0: version "16.12.0" @@ -22823,17 +24008,6 @@ react-redux@^7.1.3: prop-types "^15.7.2" react-is "^16.9.0" -react-resize-detector@^4.0.5: - version "4.1.4" - resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-4.1.4.tgz#1f89c8bc4c62251e15de14ee926b1b04fd5fee80" - integrity sha512-aceA2+5BtNjcbnmF0PzxPsBZhvM1rPKWWglxcx1TUIQI3Lng4DtB2ipLJ3o0w2LAbCbtWCFyO3EctikJzTowNQ== - dependencies: - lodash "^4.17.11" - lodash-es "^4.17.11" - prop-types "^15.7.2" - raf-schd "^4.0.0" - resize-observer-polyfill "^1.5.1" - react-router-dom@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.1.2.tgz#06701b834352f44d37fbb6311f870f84c76b9c18" @@ -22882,7 +24056,7 @@ react-select@^1.0.0: prop-types "^15.5.8" react-input-autosize "^2.1.0" -react-select@^3.0.0: +react-select@^3.0.8: version "3.0.8" resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.0.8.tgz#06ff764e29db843bcec439ef13e196865242e0c1" integrity sha512-v9LpOhckLlRmXN5A6/mGGEft4FMrfaBFTGAnuPHcUgVId7Je42kTq9y0Z+Ye5z8/j0XDT3zUqza8gaRaI1PZIg== @@ -22903,14 +24077,24 @@ react-simple-file-input@^2.0.0: dependencies: prop-types "^15.5.7" -react-syntax-highlighter@^8.0.1: - version "8.1.0" - resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-8.1.0.tgz#59103ff17a828a27ed7c8f035ae2558f09b6b78c" - integrity sha512-G2bkZxmF3VOa4atEdXIDSfwwCqjw6ZQX5znfTaHcErA1WqHIS0o6DaSCDKFPVaOMXQEB9Hf1UySYQvuJmV8CXg== +react-sizeme@^2.6.7: + version "2.6.12" + resolved "https://registry.yarnpkg.com/react-sizeme/-/react-sizeme-2.6.12.tgz#ed207be5476f4a85bf364e92042520499455453e" + integrity sha512-tL4sCgfmvapYRZ1FO2VmBmjPVzzqgHA7kI8lSJ6JS6L78jXFNRdOZFpXyK6P1NBZvKPPCZxReNgzZNUajAerZw== dependencies: - babel-runtime "^6.18.0" - highlight.js "~9.12.0" - lowlight "~1.9.1" + element-resize-detector "^1.2.1" + invariant "^2.2.4" + shallowequal "^1.1.0" + throttle-debounce "^2.1.0" + +react-syntax-highlighter@^11.0.2: + version "11.0.2" + resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-11.0.2.tgz#4e3f376e752b20d2f54e4c55652fd663149e4029" + integrity sha512-kqmpM2OH5OodInbEADKARwccwSQWBfZi0970l5Jhp4h39q9Q65C4frNcnd6uHE5pR00W8pOWj9HDRntj2G4Rww== + dependencies: + "@babel/runtime" "^7.3.1" + highlight.js "~9.13.0" + lowlight "~1.11.0" prismjs "^1.8.4" refractor "^2.4.1" @@ -22987,16 +24171,6 @@ react@^16.12.0: object-assign "^4.1.1" prop-types "^15.6.2" -react@^16.7.0, react@^16.8.4: - version "16.8.6" - resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe" - integrity sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.13.6" - react@^16.8.3: version "16.11.0" resolved "https://registry.yarnpkg.com/react/-/react-16.11.0.tgz#d294545fe62299ccee83363599bf904e4a07fdbb" @@ -23078,6 +24252,14 @@ read-pkg-up@^3.0.0: find-up "^2.0.0" read-pkg "^3.0.0" +read-pkg-up@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" + integrity sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA== + dependencies: + find-up "^3.0.0" + read-pkg "^3.0.0" + read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" @@ -23207,6 +24389,13 @@ readline2@^1.0.1: is-fullwidth-code-point "^1.0.0" mute-stream "0.0.5" +realpath-native@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c" + integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA== + dependencies: + util.promisify "^1.0.0" + recast@^0.14.7: version "0.14.7" resolved "https://registry.yarnpkg.com/recast/-/recast-0.14.7.tgz#4f1497c2b5826d42a66e8e3c9d80c512983ff61d" @@ -23217,16 +24406,6 @@ recast@^0.14.7: private "~0.1.5" source-map "~0.6.1" -recast@^0.17.3: - version "0.17.6" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.17.6.tgz#64ae98d0d2dfb10ff92ff5fb9ffb7371823b69fa" - integrity sha512-yoQRMRrK1lszNtbkGyM4kN45AwylV5hMiuEveUBlxytUViWevjvX6w+tzJt1LH4cfUhWt4NZvy3ThIhu6+m5wQ== - dependencies: - ast-types "0.12.4" - esprima "~4.0.0" - private "^0.1.8" - source-map "~0.6.1" - receptacle@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/receptacle/-/receptacle-1.3.2.tgz#a7994c7efafc7a01d0e2041839dab6c4951360d2" @@ -23263,18 +24442,6 @@ recompose@^0.25.0: react-lifecycles-compat "^3.0.2" symbol-observable "^1.0.4" -recompose@^0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/recompose/-/recompose-0.30.0.tgz#82773641b3927e8c7d24a0d87d65aeeba18aabd0" - integrity sha512-ZTrzzUDa9AqUIhRk4KmVFihH0rapdCSMFXjhHbNrjAWxBuUD/guYlyysMnuHjlZC/KRiOKRtB4jf96yYSkKE8w== - dependencies: - "@babel/runtime" "^7.0.0" - change-emitter "^0.1.2" - fbjs "^0.8.1" - hoist-non-react-statics "^2.3.1" - react-lifecycles-compat "^3.0.2" - symbol-observable "^1.0.4" - recursive-readdir@2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" @@ -23390,7 +24557,7 @@ regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== -regenerator-runtime@0.13.3: +regenerator-runtime@0.13.3, regenerator-runtime@^0.13.3: version "0.13.3" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== @@ -23405,7 +24572,7 @@ regenerator-runtime@^0.11.0, regenerator-runtime@^0.11.1: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regenerator-runtime@^0.12.0, regenerator-runtime@^0.12.1: +regenerator-runtime@^0.12.0: version "0.12.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== @@ -23470,6 +24637,14 @@ regexp.prototype.flags@^1.2.0: dependencies: define-properties "^1.1.2" +regexp.prototype.flags@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" + integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + regexpp@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" @@ -23778,6 +24953,13 @@ request-promise-core@1.1.1: dependencies: lodash "^4.13.1" +request-promise-core@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" + integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ== + dependencies: + lodash "^4.17.15" + request-promise-native@^1.0.3: version "1.0.5" resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.5.tgz#5281770f68e0c9719e5163fd3fab482215f4fda5" @@ -23787,33 +24969,16 @@ request-promise-native@^1.0.3: stealthy-require "^1.1.0" tough-cookie ">=2.3.3" -request@^2.45.0, request@^2.81.0, request@^2.83.0: - version "2.87.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" - integrity sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw== +request-promise-native@^1.0.5: + version "1.0.8" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" + integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" + request-promise-core "1.1.3" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" -request@^2.79.0, request@^2.85.0, request@^2.87.0, request@^2.88.0, request@~2.88.0: +"request@>=2.76.0 <3.0.0", request@^2.79.0, request@^2.85.0, request@^2.87.0, request@^2.88.0, request@~2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== @@ -23839,6 +25004,32 @@ request@^2.79.0, request@^2.85.0, request@^2.87.0, request@^2.88.0, request@~2.8 tunnel-agent "^0.6.0" uuid "^3.3.2" +request@^2.45.0, request@^2.81.0, request@^2.83.0: + version "2.87.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + integrity sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -23889,6 +25080,13 @@ resize-observer-polyfill@^1.5.1: resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== +resolve-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= + dependencies: + resolve-from "^3.0.0" + resolve-dir@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-0.1.1.tgz#b219259a5602fac5c5c496ad894a6e8cc430261e" @@ -24035,6 +25233,14 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + resumer@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" @@ -24052,7 +25258,7 @@ retimer@^2.0.0: resolved "https://registry.yarnpkg.com/retimer/-/retimer-2.0.0.tgz#e8bd68c5e5a8ec2f49ccb5c636db84c04063bbca" integrity sha512-KLXY85WkEq2V2bKex/LOO1ViXVn2KGYe4PYysAdYdjmraYIUsVkXu8O4am+8+5UbaaGl1qho4aqAAPHNQ4GSbg== -retry@^0.12.0: +retry@0.12.0, retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= @@ -24094,7 +25300,7 @@ rimraf@2.6.3, rimraf@^2.6.1, rimraf@~2.6.2: dependencies: glob "^7.1.3" -rimraf@^2.6.3: +rimraf@^2.6.3, rimraf@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -24160,6 +25366,11 @@ rst-selector-parser@^2.2.3: lodash.flattendeep "^4.4.0" nearley "^2.7.10" +rsvp@^4.8.4: + version "4.8.5" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" + integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== + rtlcss@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-2.4.0.tgz#482ea28f2b9fe06dd0ab3057997be9af13da84c1" @@ -24238,6 +25449,13 @@ rxjs@^6.3.3, rxjs@^6.4.0: dependencies: tslib "^1.9.0" +rxjs@^6.5.3: + version "6.5.4" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" + integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== + dependencies: + tslib "^1.9.0" + safe-buffer@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -24287,6 +25505,21 @@ samsam@1.x: resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" integrity sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg== +sane@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" + integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== + dependencies: + "@cnakazawa/watch" "^1.0.3" + anymatch "^2.0.0" + capture-exit "^2.0.0" + exec-sh "^0.3.2" + execa "^1.0.0" + fb-watchman "^2.0.0" + micromatch "^3.1.4" + minimist "^1.1.1" + walker "~1.0.5" + sanitize-filename@^1.6.1: version "1.6.2" resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.2.tgz#01b4fc8809f14e9d22761fe70380fe7f3f902185" @@ -24385,14 +25618,6 @@ sc-uws@^10.148.2: resolved "https://registry.yarnpkg.com/sc-uws/-/sc-uws-10.148.2.tgz#929823c8ece2ab4efa17468a4eea2eac05a85ad8" integrity sha512-wGXiwsORev5O3OOewsAYi1WVyMeNFMQ4bw/Qg/6g0C0J9vsEs8xnxf19hovAAQrOq6sMVrcxCNa2k1rBiDsDzw== -scheduler@^0.13.6: - version "0.13.6" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.6.tgz#466a4ec332467b31a91b9bf74e5347072e4cd889" - integrity sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler@^0.17.0: version "0.17.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.17.0.tgz#7c9c673e4ec781fac853927916d1c426b6f3ddfe" @@ -24426,6 +25651,14 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" +schema-utils@^2.0.1, schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6.1, schema-utils@^2.6.4: + version "2.6.4" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.4.tgz#a27efbf6e4e78689d91872ee3ccfa57d7bdd0f53" + integrity sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ== + dependencies: + ajv "^6.10.2" + ajv-keywords "^3.4.1" + scroll@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/scroll/-/scroll-2.0.3.tgz#0951b785544205fd17753bc3d294738ba16fc2ab" @@ -24574,7 +25807,7 @@ semver@6.2.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.2.0.tgz#4d813d9590aaf8a9192693d6c85b9344de5901db" integrity sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A== -semver@6.3.0, semver@^6.1.1, semver@^6.2.0: +semver@6.3.0, semver@^6.1.1, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -24618,10 +25851,10 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" -serialize-javascript@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65" - integrity sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA== +serialize-javascript@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" + integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== serve-favicon@^2.5.0: version "2.5.0" @@ -24849,7 +26082,7 @@ shelljs@^0.7.5: interpret "^1.0.0" rechoir "^0.6.2" -shelljs@^0.8.3: +shelljs@^0.8.1, shelljs@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097" integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A== @@ -24870,6 +26103,14 @@ shortid@^2.2.8: dependencies: nanoid "^2.0.0" +side-channel@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.2.tgz#df5d1abadb4e4bf4af1cd8852bf132d2f7876947" + integrity sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA== + dependencies: + es-abstract "^1.17.0-next.1" + object-inspect "^1.7.0" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" @@ -24953,6 +26194,11 @@ sinon@^5.0.0: supports-color "^4.4.0" type-detect "^4.0.5" +sisteransi@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.4.tgz#386713f1ef688c7c0304dc4c0632898941cad2e3" + integrity sha512-/ekMoM4NJ59ivGSfKapeG+FWtrmWvA1p6FBZwXrqojw90vJu8lBmrTxCMuBCydKtkaUe2zt4PlxeTKpjwMbyig== + slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" @@ -25269,7 +26515,7 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.1: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@0.5.12, source-map-support@^0.5.1, source-map-support@^0.5.11, source-map-support@^0.5.9, source-map-support@~0.5.10, source-map-support@~0.5.4: +source-map-support@0.5.12, source-map-support@^0.5.1, source-map-support@^0.5.11, source-map-support@^0.5.9, source-map-support@~0.5.4: version "0.5.12" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== @@ -25300,6 +26546,14 @@ source-map-support@^0.4.15: dependencies: source-map "^0.5.6" +source-map-support@^0.5.6: + version "0.5.16" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" + integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" @@ -25398,6 +26652,11 @@ speedometer@~0.1.2: resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-0.1.4.tgz#9876dbd2a169d3115402d48e6ea6329c8816a50d" integrity sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0= +speedometer@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-1.0.0.tgz#cd671cb06752c22bca3370e2f334440be4fc62e2" + integrity sha1-zWccsGdSwivKM3Di8zREC+T8YuI= + split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" @@ -25405,6 +26664,13 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" +split2@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-2.2.0.tgz#186b2575bcf83e85b7d18465756238ee4ee42493" + integrity sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw== + dependencies: + through2 "^2.0.2" + split2@^3.0.0, split2@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/split2/-/split2-3.1.1.tgz#c51f18f3e06a8c4469aaab487687d8d956160bb6" @@ -25476,6 +26742,14 @@ ssri@^6.0.1: dependencies: figgy-pudding "^3.5.1" +ssri@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-7.1.0.tgz#92c241bf6de82365b5c7fb4bd76e975522e1294d" + integrity sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g== + dependencies: + figgy-pudding "^3.5.1" + minipass "^3.1.1" + stable@^0.1.8, stable@~0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" @@ -25486,6 +26760,11 @@ stack-trace@0.0.10, stack-trace@0.0.x: resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= +stack-utils@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" + integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== + state-toggle@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.2.tgz#75e93a61944116b4959d665c8db2d243631d6ddc" @@ -25543,7 +26822,7 @@ stdout-stream@^1.4.0: dependencies: readable-stream "^2.0.1" -stealthy-require@^1.1.0: +stealthy-require@^1.1.0, stealthy-require@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= @@ -25563,6 +26842,35 @@ store@^2.0.12: resolved "https://registry.yarnpkg.com/store/-/store-2.0.12.tgz#8c534e2a0b831f72b75fc5f1119857c44ef5d593" integrity sha1-jFNOKguDH3K3X8XxEZhXxE711ZM= +storybook-chromatic@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/storybook-chromatic/-/storybook-chromatic-2.2.2.tgz#eade5178f334d6dd173dbe980c902ae90e727cb0" + integrity sha512-n79eX0MQEHzDCnXqgOjvDOQ1xfBOTyQHy1RNxEMQvZolfAle8YVS0NnRpcW0xh/Ye621Iote3dwFI3uQmlcqPw== + dependencies: + "@babel/runtime" "^7.3.1" + "@chromaui/localtunnel" "1.10.1" + async-retry "^1.1.4" + commander "^2.9.0" + debug "^3.0.1" + denodeify "^1.2.1" + env-ci "^2.1.0" + fake-tag "^1.0.0" + jsdom "^11.5.1" + jsonfile "^4.0.0" + minimatch "^3.0.4" + node-ask "^1.0.1" + node-fetch "^2.6.0" + node-loggly-bulk "^2.2.4" + param-case "^2.1.1" + pino "4.10.2" + progress "^2.0.3" + progress-stream "^2.0.0" + semver "^6.2.0" + strip-color "^0.1.0" + tmp "^0.1.0" + tree-kill "^1.1.0" + uuid "^3.3.2" + stream-browserify@^2.0.0, stream-browserify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" @@ -25684,6 +26992,14 @@ string-convert@^0.2.0: resolved "https://registry.yarnpkg.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97" integrity sha1-aYLMMEn7tM2F+LJFaLnZvznu/5c= +string-length@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" + integrity sha1-1A27aGo6zpYMHP/KVivyxF+DY+0= + dependencies: + astral-regex "^1.0.0" + strip-ansi "^4.0.0" + string-template@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" @@ -25715,7 +27031,7 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0, string-width@^4.2.0: +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== @@ -25735,6 +27051,18 @@ string.prototype.matchall@^3.0.1: has-symbols "^1.0.0" regexp.prototype.flags "^1.2.0" +"string.prototype.matchall@^4.0.0 || ^3.0.1": + version "4.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz#48bb510326fb9fdeb6a33ceaa81a6ea04ef7648e" + integrity sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0" + has-symbols "^1.0.1" + internal-slot "^1.0.2" + regexp.prototype.flags "^1.3.0" + side-channel "^1.0.2" + string.prototype.padend@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz#f3aaef7c1719f170c5eab1c32bf780d96e21f2f0" @@ -25779,6 +27107,14 @@ string.prototype.trimleft@^2.0.0, string.prototype.trimleft@^2.1.0: define-properties "^1.1.3" function-bind "^1.1.1" +string.prototype.trimleft@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" + integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + string.prototype.trimright@^2.0.0, string.prototype.trimright@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" @@ -25787,6 +27123,14 @@ string.prototype.trimright@^2.0.0, string.prototype.trimright@^2.1.0: define-properties "^1.1.3" function-bind "^1.1.1" +string.prototype.trimright@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9" + integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + string_decoder@0.10, string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" @@ -25823,7 +27167,7 @@ stringify-entities@^1.0.1: is-alphanumerical "^1.0.0" is-hexadecimal "^1.0.0" -stringify-object@3.2.2, stringify-object@^3.0.0: +stringify-object@^3.0.0: version "3.2.2" resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.2.2.tgz#9853052e5a88fb605a44cd27445aa257ad7ffbcd" integrity sha512-O696NF21oLiDy8PhpWu8AEqoZHw++QW6mUv0UvKZe8gWSdSvMXkiLufK7OmnP27Dro4GU5kb9U7JIO0mBuCRQg== @@ -25905,6 +27249,11 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= +strip-color@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/strip-color/-/strip-color-0.1.0.tgz#106f65d3d3e6a2d9401cac0eb0ce8b8a702b4f7b" + integrity sha1-EG9l09PmotlAHKwOsM6LinArT3s= + strip-dirs@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" @@ -25936,6 +27285,13 @@ strip-indent@^2.0.0: resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + strip-json-comments@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" @@ -25971,13 +27327,13 @@ style-loader@^0.21.0: loader-utils "^1.1.0" schema-utils "^0.4.5" -style-loader@^0.23.1: - version "0.23.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.1.tgz#cb9154606f3e771ab6c4ab637026a1049174d925" - integrity sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg== +style-loader@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.1.3.tgz#9e826e69c683c4d9bf9db924f85e9abb30d5e200" + integrity sha512-rlkH7X/22yuwFYK357fMN/BxYOorfnfq0eD7+vqlemSK4wEcejFF1dg4zxP0euBW8NrYx2WZzZ8PPFevr7D+Kw== dependencies: - loader-utils "^1.1.0" - schema-utils "^1.0.0" + loader-utils "^1.2.3" + schema-utils "^2.6.4" style-search@^0.1.0: version "0.1.0" @@ -26159,6 +27515,13 @@ supports-color@^6.1.0: dependencies: has-flag "^3.0.0" +supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + sver-compat@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz#3cf87dfeb4d07b4a3f14827bc186b3fd0c645cd8" @@ -26259,6 +27622,11 @@ symbol-tree@^3.2.1: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" integrity sha1-rifbOPZgp64uHDt9G8KQgZuFGeY= +symbol-tree@^3.2.2: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + symbol.prototype.description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/symbol.prototype.description/-/symbol.prototype.description-1.0.0.tgz#6e355660eb1e44ca8ad53a68fdb72ef131ca4b12" @@ -26331,7 +27699,7 @@ tap-parser@^7.0.0: js-yaml "^3.2.7" minipass "^2.2.0" -tapable@^1.0.0, tapable@^1.1.0: +tapable@^1.0.0, tapable@^1.1.0, tapable@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== @@ -26466,29 +27834,16 @@ tdigest@^0.1.1: dependencies: bintrees "1.0.1" -telejson@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/telejson/-/telejson-2.2.1.tgz#d9ee7e7eba0c81d9378257342fde7142a03787e2" - integrity sha512-JtFAnITek+Z9t+uQjVl4Fxur9Z3Bi3flytBLc3KZVXmMUHLXdtAxiP0g8IBkHvKn1kQIYZC57IG0jjGH1s64HQ== - dependencies: - global "^4.3.2" - is-function "^1.0.1" - is-regex "^1.0.4" - is-symbol "^1.0.2" - isobject "^3.0.1" - lodash.get "^4.4.2" - memoizerific "^1.11.3" - -telejson@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/telejson/-/telejson-3.1.0.tgz#c648479afe0d8edd90aeaf478b0b8a2fe9f59513" - integrity sha512-mhiVy+xp2atri1bzSzdy/gVGXlOhibaoZ092AUq5xhnrZGdzhF0fLaOduHJQghkro+qmjYMwhsOL9CkD2zTicg== +telejson@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/telejson/-/telejson-3.3.0.tgz#6d814f3c0d254d5c4770085aad063e266b56ad03" + integrity sha512-er08AylQ+LEbDLp1GRezORZu5wKOHaBczF6oYJtgC3Idv10qZ8A3p6ffT+J5BzDKkV9MqBvu8HAKiIIOp6KJ2w== dependencies: "@types/is-function" "^1.0.0" global "^4.4.0" is-function "^1.0.1" is-regex "^1.0.4" - is-symbol "^1.0.2" + is-symbol "^1.0.3" isobject "^4.0.0" lodash "^4.17.15" memoizerific "^1.11.3" @@ -26520,30 +27875,48 @@ term-size@^1.2.0: dependencies: execa "^0.7.0" -terser-webpack-plugin@^1.1.0, terser-webpack-plugin@^1.2.4: - version "1.3.0" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz#69aa22426299f4b5b3775cbed8cb2c5d419aa1d4" - integrity sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg== +term-size@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.1.1.tgz#f81ec25854af91a480d2f9d0c77ffcb26594ed1a" + integrity sha512-UqvQSch04R+69g4RDhrslmGvGL3ucDRX/U+snYW0Mab4uCAyKSndUksaoqlJ81QKSpRnIsuOYQCbC2ZWx2896A== + +terser-webpack-plugin@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" + integrity sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA== dependencies: - cacache "^11.3.2" - find-cache-dir "^2.0.0" + cacache "^12.0.2" + find-cache-dir "^2.1.0" is-wsl "^1.1.0" - loader-utils "^1.2.3" schema-utils "^1.0.0" - serialize-javascript "^1.7.0" + serialize-javascript "^2.1.2" source-map "^0.6.1" - terser "^4.0.0" - webpack-sources "^1.3.0" + terser "^4.1.2" + webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.0.0.tgz#ef356f6f359a963e2cc675517f21c1c382877374" - integrity sha512-dOapGTU0hETFl1tCo4t56FN+2jffoKyER9qBGoUFyZ6y7WLoKT0bF+lAYi6B6YsILcGF3q1C2FBh8QcKSCgkgA== +terser-webpack-plugin@^2.1.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.2.tgz#6d3d1b0590c8f729bfbaeb7fb2528b8b62db4c74" + integrity sha512-SmvB/6gtEPv+CJ88MH5zDOsZdKXPS/Uzv2//e90+wM1IHFUhsguPKEILgzqrM1nQ4acRXN/SV4Obr55SXC+0oA== + dependencies: + cacache "^13.0.1" + find-cache-dir "^3.2.0" + jest-worker "^24.9.0" + schema-utils "^2.6.1" + serialize-javascript "^2.1.2" + source-map "^0.6.1" + terser "^4.4.3" + webpack-sources "^1.4.3" + +terser@^4.1.2, terser@^4.4.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.3.tgz#e33aa42461ced5238d352d2df2a67f21921f8d87" + integrity sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ== dependencies: - commander "^2.19.0" + commander "^2.20.0" source-map "~0.6.1" - source-map-support "~0.5.10" + source-map-support "~0.5.12" terser@^4.1.4: version "4.3.1" @@ -26564,6 +27937,16 @@ test-exclude@^4.2.2: read-pkg-up "^3.0.0" require-main-filename "^1.0.1" +test-exclude@^5.2.3: + version "5.2.3" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" + integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g== + dependencies: + glob "^7.1.3" + minimatch "^3.0.4" + read-pkg-up "^4.0.0" + require-main-filename "^2.0.0" + testem@^2.16.0: version "2.16.0" resolved "https://registry.yarnpkg.com/testem/-/testem-2.16.0.tgz#da2682f3e02459212b8670b88f9d7cd4d4b0aebb" @@ -26642,6 +28025,16 @@ thenify-all@^1.0.0, thenify-all@^1.6.0: dependencies: any-promise "^1.0.0" +throat@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" + integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= + +throttle-debounce@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.1.0.tgz#257e648f0a56bd9e54fe0f132c4ab8611df4e1d5" + integrity sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg== + throttleit@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf" @@ -26683,7 +28076,7 @@ through2@^1.1.1: readable-stream ">=1.1.13-1 <1.2.0-0" xtend ">=4.0.0 <4.1.0-0" -through2@^2.0.5: +through2@^2.0.2, through2@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== @@ -26852,13 +28245,18 @@ tmp@0.0.33, tmp@0.0.x, tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" -tmp@0.1.0: +tmp@0.1.0, tmp@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== dependencies: rimraf "^2.6.3" +tmpl@1.0.x: + version "1.0.4" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" + integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= + to-absolute-glob@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" @@ -26958,6 +28356,14 @@ tough-cookie@>=2.3.3, tough-cookie@^2.3.3, tough-cookie@~2.3.3: dependencies: punycode "^1.4.1" +tough-cookie@^2.3.4: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" @@ -27048,6 +28454,11 @@ ts-custom-error@^2.2.1: resolved "https://registry.yarnpkg.com/ts-custom-error/-/ts-custom-error-2.2.1.tgz#47086fbc34df5c7c2d4fba8c92d8767662066951" integrity sha512-lHKZtU+PXkVuap6nlFZybIAFLUO8B3jbCs1VynBL8AUSAHfeG6HpztcBTDRp5I+fN5820N9kGg+eTIvr+le2yg== +ts-dedent@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-1.1.1.tgz#68fad040d7dbd53a90f545b450702340e17d18f3" + integrity sha512-UGTRZu1evMw4uTPyYF66/KFd22XiU+jMaIuHrkIHQ2GivAXVlLV0v/vHrpOuTRf9BmpNHi/SO7Vd0rLu0y57jg== + ts-invariant@^0.4.0: version "0.4.4" resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.4.4.tgz#97a523518688f93aafad01b0e80eb803eb2abd86" @@ -27055,6 +28466,11 @@ ts-invariant@^0.4.0: dependencies: tslib "^1.9.3" +ts-pnp@^1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.5.tgz#840e0739c89fce5f3abd9037bb091dbff16d9dec" + integrity sha512-ti7OGMOUOzo66wLF3liskw6YQIaSsBgc4GOAlWRnIEj8htCxJUxskanMUoJOD6MDCRAXo36goXJZch+nOS0VMA== + tslib@^1.9.0, tslib@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" @@ -27137,6 +28553,11 @@ type-fest@^0.3.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + type-is@^1.6.16, type-is@~1.6.17, type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -27308,6 +28729,11 @@ undertaker@^1.2.1: object.reduce "^1.0.0" undertaker-registry "^1.0.0" +unfetch@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.1.0.tgz#6ec2dd0de887e58a4dee83a050ded80ffc4137db" + integrity sha512-crP/n3eAPUJxZXM9T80/yv0YhkTEx2K1D3h7D1AJM6fzsWZrxdyRuLN0JH/dkZh1LNH8LxCnBzoPFCPbb2iGpg== + unherit@^1.0.4: version "1.1.2" resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.2.tgz#14f1f397253ee4ec95cec167762e77df83678449" @@ -27578,14 +29004,14 @@ url-join@^2.0.5: resolved "https://registry.yarnpkg.com/url-join/-/url-join-2.0.5.tgz#5af22f18c052a000a48d7b82c5e9c2e2feeda728" integrity sha1-WvIvGMBSoACkjXuCxenC4v7tpyg= -url-loader@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-1.1.2.tgz#b971d191b83af693c5e3fea4064be9e1f2d7f8d8" - integrity sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg== +url-loader@^2.0.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-2.3.0.tgz#e0e2ef658f003efb8ca41b0f3ffbf76bab88658b" + integrity sha512-goSdg8VY+7nPZKUEChZSEtW5gjbS66USIGCeSJ1OVOJ7Yfuh/36YxCwMi5HVEJh6mqUYOoy3NJ0vlOMrWsSHog== dependencies: - loader-utils "^1.1.0" - mime "^2.0.3" - schema-utils "^1.0.0" + loader-utils "^1.2.3" + mime "^2.4.4" + schema-utils "^2.5.0" url-parse-lax@^1.0.0: version "1.0.0" @@ -27635,6 +29061,19 @@ ursa-optional@~0.9.10: bindings "^1.3.0" nan "^2.11.1" +use-callback-ref@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.2.1.tgz#898759ccb9e14be6c7a860abafa3ffbd826c89bb" + integrity sha512-C3nvxh0ZpaOxs9RCnWwAJ+7bJPwQI8LHF71LzbQ3BvzH5XkdtlkMadqElGevg5bYBDFip4sAnD4m06zAKebg1w== + +use-sidecar@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.0.2.tgz#e72f582a75842f7de4ef8becd6235a4720ad8af6" + integrity sha512-287RZny6m5KNMTb/Kq9gmjafi7lQL0YHO1lYolU6+tY1h9+Z3uCtkJJ3OSOq3INwYf2hBryCcDh4520AhJibMA== + dependencies: + detect-node "^2.0.4" + tslib "^1.9.3" + use@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/use/-/use-3.1.0.tgz#14716bf03fdfefd03040aef58d8b4b85f3a7c544" @@ -27690,6 +29129,16 @@ util.promisify@1.0.0, util.promisify@~1.0.0: define-properties "^1.1.2" object.getownpropertydescriptors "^2.0.3" +util.promisify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" + integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.2" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.0" + util@0.10.3, util@^0.10.3, util@~0.10.1: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" @@ -27966,23 +29415,28 @@ vlq@^0.2.2: resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow== -vm-browserify@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM= - dependencies: - indexof "0.0.1" - vm-browserify@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019" integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw== +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + void-elements@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= +w3c-hr-time@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" + integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU= + dependencies: + browser-process-hrtime "^0.1.2" + walk-sync@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-0.3.1.tgz#558a16aeac8c0db59c028b73c66f397684ece465" @@ -27991,6 +29445,13 @@ walk-sync@0.3.1: ensure-posix-path "^1.0.0" matcher-collection "^1.0.0" +walker@^1.0.7, walker@~1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" + integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= + dependencies: + makeerror "1.0.x" + warning@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" @@ -28018,7 +29479,7 @@ watchify@^3.11.1: through2 "^2.0.0" xtend "^4.0.0" -watchpack@^1.5.0: +watchpack@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== @@ -28398,7 +29859,7 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" -webpack-sources@^1.1.0, webpack-sources@^1.3.0: +webpack-sources@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA== @@ -28406,35 +29867,49 @@ webpack-sources@^1.1.0, webpack-sources@^1.3.0: source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^4.28.0, webpack@^4.32.0: - version "4.33.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.33.0.tgz#c30fc4307db432e5c5e3333aaa7c16a15a3b277e" - integrity sha512-ggWMb0B2QUuYso6FPZKUohOgfm+Z0sVFs8WwWuSH1IAvkWs428VDNmOlAxvHGTB9Dm/qOB/qtE5cRx5y01clxw== +webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack-virtual-modules@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.2.1.tgz#8ab73d4df0fd37ed27bb8d823bc60ea7266c8bf7" + integrity sha512-0PWBlxyt4uGDofooIEanWhhyBOHdd+lr7QpYNDLC7/yc5lqJT8zlc04MTIBnKj+c2BlQNNuwE5er/Tg4wowHzA== + dependencies: + debug "^3.0.0" + +webpack@^4.33.0, webpack@^4.38.0: + version "4.41.5" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.5.tgz#3210f1886bce5310e62bb97204d18c263341b77c" + integrity sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw== dependencies: "@webassemblyjs/ast" "1.8.5" "@webassemblyjs/helper-module-context" "1.8.5" "@webassemblyjs/wasm-edit" "1.8.5" "@webassemblyjs/wasm-parser" "1.8.5" - acorn "^6.0.5" - acorn-dynamic-import "^4.0.0" - ajv "^6.1.0" - ajv-keywords "^3.1.0" - chrome-trace-event "^1.0.0" + acorn "^6.2.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" enhanced-resolve "^4.1.0" - eslint-scope "^4.0.0" + eslint-scope "^4.0.3" json-parse-better-errors "^1.0.2" - loader-runner "^2.3.0" - loader-utils "^1.1.0" - memory-fs "~0.4.1" - micromatch "^3.1.8" - mkdirp "~0.5.0" - neo-async "^2.5.0" - node-libs-browser "^2.0.0" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.1" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" schema-utils "^1.0.0" - tapable "^1.1.0" - terser-webpack-plugin "^1.1.0" - watchpack "^1.5.0" - webpack-sources "^1.3.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.3" + watchpack "^1.6.0" + webpack-sources "^1.4.1" "webrtcsupport@github:ipfs/webrtcsupport": version "2.2.0" @@ -28481,6 +29956,13 @@ whatwg-encoding@^1.0.1: dependencies: iconv-lite "0.4.19" +whatwg-encoding@^1.0.3: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + whatwg-fetch@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" @@ -28496,6 +29978,11 @@ whatwg-fetch@^3.0.0: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== +whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + whatwg-url@7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.0.0.tgz#fde926fa54a599f3adf82dff25a9f7be02dc6edd" @@ -28514,6 +30001,24 @@ whatwg-url@^6.3.0: tr46 "^1.0.0" webidl-conversions "^4.0.1" +whatwg-url@^6.4.1: + version "6.5.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8" + integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" + +whatwg-url@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" + integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" + which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" @@ -28552,6 +30057,13 @@ widest-line@^2.0.0: dependencies: string-width "^2.1.1" +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + wif@^2.0.1, wif@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/wif/-/wif-2.0.6.tgz#08d3f52056c66679299726fade0d432ae74b4704" @@ -28626,6 +30138,15 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +write-file-atomic@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.1.tgz#d0b05463c188ae804396fd5ab2a370062af87529" + integrity sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + write-file-atomic@^1.1.4: version "1.3.4" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" @@ -28689,7 +30210,7 @@ ws@^3.0.0, ws@~3.3.1: safe-buffer "~5.1.0" ultron "~1.1.0" -ws@^5.1.1: +ws@^5.1.1, ws@^5.2.0: version "5.2.2" resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA== @@ -28767,6 +30288,11 @@ xml-name-validator@^2.0.1: resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" integrity sha1-TYuPHszTQZqjYgYb7O9RXh5VljU= +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + xml2js@^0.4.19: version "0.4.23" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" @@ -28857,6 +30383,18 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@^1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.7.2.tgz#f26aabf738590ab61efaca502358e48dc9f348b2" + integrity sha512-qXROVp90sb83XtAoqE8bP9RwAkTTZbugRUTm5YeFCBfNRPEp2YzTeqWiz7m5OORHzEvrA/qcGS8hp/E+MMROYw== + dependencies: + "@babel/runtime" "^7.6.3" + yargs-parser@^10.0.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" @@ -28949,6 +30487,43 @@ yargs@14.0.0, yargs@^14.0.0, yargs@~14.0.0: y18n "^4.0.0" yargs-parser "^13.1.1" +yargs@6.6.0, yargs@^6.5.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" + integrity sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg= + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^4.2.0" + +yargs@^11.0.0: + version "11.1.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.1.tgz#5052efe3446a4df5ed669c995886cc0f13702766" + integrity sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw== + dependencies: + cliui "^4.0.0" + decamelize "^1.1.1" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^3.1.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^9.0.2" + yargs@^12.0.1: version "12.0.5" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" @@ -28967,7 +30542,7 @@ yargs@^12.0.1: y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" -yargs@^13.2.2, yargs@^13.2.4: +yargs@^13.2.2, yargs@^13.2.4, yargs@^13.3.0: version "13.3.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== @@ -29000,25 +30575,6 @@ yargs@^15.0.2: y18n "^4.0.0" yargs-parser "^16.1.0" -yargs@^6.5.0: - version "6.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" - integrity sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg= - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^4.2.0" - yargs@^7.0.0, yargs@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" From 60f6fd00086af0a96a34d3a9b00d698614781b6b Mon Sep 17 00:00:00 2001 From: ryanml Date: Mon, 27 Jan 2020 04:54:21 -0800 Subject: [PATCH 180/689] Fixing broken JSON import help link (#7910) --- ui/app/pages/create-account/import-account/json.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/pages/create-account/import-account/json.js b/ui/app/pages/create-account/import-account/json.js index 46a14c1a9..5e5671d31 100644 --- a/ui/app/pages/create-account/import-account/json.js +++ b/ui/app/pages/create-account/import-account/json.js @@ -9,7 +9,7 @@ import { DEFAULT_ROUTE } from '../../../helpers/constants/routes' import { getMetaMaskAccounts } from '../../../selectors/selectors' import Button from '../../../components/ui/button' -const HELP_LINK = 'https://metamask.zendesk.com/hc/en-us/articles/360015489351-Importing-Accounts' +const HELP_LINK = 'https://metamask.zendesk.com/hc/en-us/articles/360015489331-Importing-an-Account' class JsonImportSubview extends Component { state = { From d3bce9c59529497212c1e531234c1128ddf54302 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 27 Jan 2020 11:06:31 -0330 Subject: [PATCH 181/689] Remove xtend from the dependencies list (#7902) --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 689b24f50..54a37fa30 100644 --- a/package.json +++ b/package.json @@ -184,8 +184,7 @@ "textarea-caret": "^3.0.1", "valid-url": "^1.0.9", "web3": "^0.20.7", - "web3-stream-provider": "^4.0.0", - "xtend": "^4.0.1" + "web3-stream-provider": "^4.0.0" }, "devDependencies": { "@babel/core": "^7.5.5", From feffd4f79ce96061050048bf937048e8c76abc9b Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 27 Jan 2020 11:09:17 -0400 Subject: [PATCH 182/689] Update `classnames` to `v2.2.6` (#7906) This patch update includes a bug fix for ES6 imports. The bug doesn't affect our use of this module, but it ensures that we can safely use the `dedupe` and `bind` APIs as ES6 imports if we decide to. --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 54a37fa30..161b41edc 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "bn.js": "^4.11.7", "browserify-derequire": "^0.9.4", "c3": "^0.6.7", - "classnames": "^2.2.5", + "classnames": "^2.2.6", "clone": "^2.1.2", "content-hash": "^2.5.0", "copy-to-clipboard": "^3.0.8", diff --git a/yarn.lock b/yarn.lock index f3f4e8385..8cd3bdc6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7039,10 +7039,10 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@^2.2.4, classnames@^2.2.5: - version "2.2.5" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" - integrity sha1-+zgB1FNGdknvNgPH1hoCvRKb3m0= +classnames@^2.2.4, classnames@^2.2.5, classnames@^2.2.6: + version "2.2.6" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" + integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== clean-css@4.2.x: version "4.2.1" From 1d73d90a1a8fe834d3d41e6cb8131be83fe2ba3a Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 27 Jan 2020 11:15:37 -0400 Subject: [PATCH 183/689] Replace bluebird with Node.js API for unhandled rejections (#7904) Unhandled rejections are now caught using built-in Node.js APIs instead of with `bluebird`. `bluebird` was added as a production dependency but was only used for this purpose. The code responsible for catching unhandled rejection in the browser was removed, as this test helper is never run in the browser. Additionally, unhandled rejections are tracked over the course of all tests, and result in a non-zero exit code if they remain at the end. This was done because it is possible for errors to trigger the `uncaughtRejection` event but then still be handled later on. This is uncommon, and doesn't seem to happen in our test suite. But if it does in the future, it'll be logged but won't result in a non-zero exit code. --- package.json | 1 - test/helper.js | 56 +++++++++++++++++++------------------------------- 2 files changed, 21 insertions(+), 36 deletions(-) diff --git a/package.json b/package.json index 161b41edc..2c28f734a 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,6 @@ "await-semaphore": "^0.1.1", "bignumber.js": "^4.1.0", "bip39": "^2.2.0", - "bluebird": "^3.5.0", "bn.js": "^4.11.7", "browserify-derequire": "^0.9.4", "c3": "^0.6.7", diff --git a/test/helper.js b/test/helper.js index 0b8508d1d..7d0df1745 100644 --- a/test/helper.js +++ b/test/helper.js @@ -7,9 +7,28 @@ import log from 'loglevel' nock.disableNetConnect() nock.enableNetConnect('localhost') +// catch rejections that are still unhandled when tests exit +const unhandledRejections = new Map() +process.on('unhandledRejection', (reason, promise) => { + console.log('Unhandled rejection:', reason) + unhandledRejections.set(promise, reason) +}) +process.on('rejectionHandled', (promise) => { + console.log(`handled: ${unhandledRejections.get(promise)}`) + unhandledRejections.delete(promise) +}) + +process.on('exit', () => { + if (unhandledRejections.size > 0) { + console.error(`Found ${unhandledRejections.size} unhandled rejections:`) + for (const reason of unhandledRejections.values()) { + console.error('Unhandled rejection: ', reason) + } + process.exit(1) + } +}) + Enzyme.configure({ adapter: new Adapter() }) -// disallow promises from swallowing errors -enableFailureOnUnhandledPromiseRejection() // ganache server const server = Ganache.server() @@ -39,36 +58,3 @@ if (!window.crypto) { if (!window.crypto.getRandomValues) { window.crypto.getRandomValues = require('polyfill-crypto.getrandomvalues') } - -function enableFailureOnUnhandledPromiseRejection () { - // overwrite node's promise with the stricter Bluebird promise - global.Promise = require('bluebird') - - // modified from https://github.com/mochajs/mocha/issues/1926#issuecomment-180842722 - - // rethrow unhandledRejections - if (typeof process !== 'undefined') { - process.on('unhandledRejection', function (reason) { - throw reason - }) - } else if (typeof window !== 'undefined') { - // 2016-02-01: No browsers support this natively, however bluebird, when.js, - // and probably other libraries do. - if (typeof window.addEventListener === 'function') { - window.addEventListener('unhandledrejection', function (evt) { - throw evt.detail.reason - }) - } else { - const oldOHR = window.onunhandledrejection - window.onunhandledrejection = function (evt) { - if (typeof oldOHR === 'function') { - oldOHR.apply(this, arguments) - } - throw evt.detail.reason - } - } - } else if (typeof console !== 'undefined' && - typeof (console.error || console.log) === 'function') { - (console.error || console.log)('Unhandled rejections will be ignored!') - } -} From 6ae93b1ec0dee25a249230ca02f1bd09e63de4bd Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 27 Jan 2020 12:31:55 -0400 Subject: [PATCH 184/689] Comment out `storybook-deploy` step (#7913) The Storybook deploy step is currently broken because it's using the wrong source branch (`master` instead of `develop`), and because the key that CircleCI is setup with doesn't have write access to the repo. While I expect we'll get these two problems fixed soon, this ensures that we at least have passing builds on `develop` in the meantime. --- .circleci/config.yml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8f2aad2e7..7eba4e7b8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -83,12 +83,12 @@ workflows: - prep-build # - prep-docs - all-tests-pass - - job-publish-storybook: - filters: - branches: - only: develop - requires: - - prep-deps + # - job-publish-storybook: + # filters: + # branches: + # only: develop + # requires: + # - prep-deps - coveralls-upload: requires: - test-unit @@ -355,16 +355,16 @@ jobs: # git config --global user.name "metamaskbot" && # git config --global user.email "admin@metamask.io" && # yarn publish-docs - job-publish-storybook: - docker: - - image: circleci/node:10.17-browsers - steps: - - checkout - - attach_workspace: - at: . - - run: - name: storybook:deploy - command: yarn storybook:deploy + # job-publish-storybook: + # docker: + # - image: circleci/node:10.17-browsers + # steps: + # - checkout + # - attach_workspace: + # at: . + # - run: + # name: storybook:deploy + # command: yarn storybook:deploy test-unit: docker: From 583b404e02192f87d33b1bb81358ca4e24295354 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 27 Jan 2020 12:45:48 -0400 Subject: [PATCH 185/689] Switch to full lodash package, and update lodash (#7907) * Update lodash All versions of the full `lodash` package have been updated to 4.17.15. The only exception is v4.17.14 which is pinned by `ganache-core`. * Switch to using `lodash` instead of per-method packages We have the full lodash package _ten times_ as a production transitive dependency, so including per-method packages is not saving space (it might instead result in slightly more space being used). --- gulpfile.js | 2 +- package.json | 6 ++---- .../app/account-menu/account-menu.component.js | 2 +- .../advanced-gas-inputs.component.js | 2 +- .../confirm-seed-phrase.component.js | 2 +- .../send-amount-row/send-amount-row.component.js | 2 +- ui/app/pages/send/send.component.js | 2 +- .../add-contact/add-contact.component.js | 2 +- yarn.lock | 11 +++-------- 9 files changed, 12 insertions(+), 19 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index b21eecda9..4a7c3a471 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -9,7 +9,7 @@ const watch = require('gulp-watch') const sourcemaps = require('gulp-sourcemaps') const jsoneditor = require('gulp-json-editor') const zip = require('gulp-zip') -const assign = require('lodash.assign') +const { assign } = require('lodash') const livereload = require('gulp-livereload') const del = require('del') const manifest = require('./app/manifest.json') diff --git a/package.json b/package.json index 2c28f734a..9d9bdd9d9 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "generate:migration": "./development/generate-migration.sh" }, "resolutions": { - "3box/ipfs/ipld-zcash/zcash-bitcore-lib/lodash": "^4.17.12", + "3box/ipfs/ipld-zcash/zcash-bitcore-lib/lodash": "^4.17.15", "pubnub/superagent-proxy": "^2.0.0" }, "dependencies": { @@ -127,8 +127,7 @@ "json-rpc-engine": "^5.1.6", "json-rpc-middleware-stream": "^2.1.1", "jsonschema": "^1.2.4", - "lodash.debounce": "^4.0.8", - "lodash.shuffle": "^4.2.0", + "lodash": "^4.17.15", "loglevel": "^1.4.1", "luxon": "^1.8.2", "metamask-inpage-provider": "^4.0.3", @@ -267,7 +266,6 @@ "karma-qunit": "^1.2.1", "koa": "^2.7.0", "lockfile-lint": "^3.0.5", - "lodash.assign": "^4.0.6", "mocha": "^5.0.0", "mocha-eslint": "^4.0.0", "mocha-jsdom": "^1.1.0", diff --git a/ui/app/components/app/account-menu/account-menu.component.js b/ui/app/components/app/account-menu/account-menu.component.js index 5ac9814de..523aaea9d 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/app/components/app/account-menu/account-menu.component.js @@ -1,6 +1,6 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' -import debounce from 'lodash.debounce' +import { debounce } from 'lodash' import Fuse from 'fuse.js' import InputAdornment from '@material-ui/core/InputAdornment' diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js b/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js index b881db6e5..9c3432e5c 100644 --- a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js +++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js @@ -1,7 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' -import debounce from 'lodash.debounce' +import { debounce } from 'lodash' export default class AdvancedGasInputs extends Component { static contextTypes = { diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js index 6642e1e7d..2b6d5ceee 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' -import shuffle from 'lodash.shuffle' +import { shuffle } from 'lodash' import Button from '../../../../components/ui/button' import { INITIALIZE_END_OF_FLOW_ROUTE, diff --git a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js b/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js index d6fd5f02d..bc4eea6af 100644 --- a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js +++ b/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js @@ -1,6 +1,6 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' -import debounce from 'lodash.debounce' +import { debounce } from 'lodash' import SendRowWrapper from '../send-row-wrapper' import AmountMaxButton from './amount-max-button' import UserPreferencedCurrencyInput from '../../../../components/app/user-preferenced-currency-input' diff --git a/ui/app/pages/send/send.component.js b/ui/app/pages/send/send.component.js index 3507c1cf1..f9e2e0643 100644 --- a/ui/app/pages/send/send.component.js +++ b/ui/app/pages/send/send.component.js @@ -6,7 +6,7 @@ import { getToAddressForGasUpdate, doesAmountErrorRequireUpdate, } from './send.utils' -import debounce from 'lodash.debounce' +import { debounce } from 'lodash' import { getToWarningObject, getToErrorObject } from './send-content/add-recipient/add-recipient' import SendHeader from './send-header' import AddRecipient from './send-content/add-recipient' diff --git a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js index 6411883c3..cd55eb656 100644 --- a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js +++ b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js @@ -6,7 +6,7 @@ import { CONTACT_LIST_ROUTE } from '../../../../helpers/constants/routes' import { isValidAddress, isValidENSAddress } from '../../../../helpers/utils/util' import EnsInput from '../../../send/send-content/add-recipient/ens-input' import PageContainerFooter from '../../../../components/ui/page-container/page-container-footer' -import debounce from 'lodash.debounce' +import { debounce } from 'lodash' export default class AddContact extends PureComponent { diff --git a/yarn.lock b/yarn.lock index 8cd3bdc6a..f67d4ef5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18734,7 +18734,7 @@ lodash.assign@^3.0.0: lodash._createassigner "^3.0.0" lodash.keys "^3.0.0" -lodash.assign@^4.0.1, lodash.assign@^4.0.6, lodash.assign@^4.2.0: +lodash.assign@^4.0.1, lodash.assign@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= @@ -18913,11 +18913,6 @@ lodash.restparam@^3.0.0: resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= -lodash.shuffle@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.shuffle/-/lodash.shuffle-4.2.0.tgz#145b5053cf875f6f5c2a33f48b6e9948c6ec7b4b" - integrity sha1-FFtQU8+HX29cKjP0i26ZSMbse0s= - lodash.some@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" @@ -18966,12 +18961,12 @@ lodash.uniqby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" integrity sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI= -lodash@4.17.14, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.8.0, lodash@~4.17.10, lodash@~4.17.2, lodash@~4.17.4: +lodash@4.17.14: version "4.17.14" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== -lodash@=3.10.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15: +lodash@=3.10.1, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.8.0, lodash@~4.17.10, lodash@~4.17.2, lodash@~4.17.4: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== From 491675d50e3b8442df8c81d61180ea0c99355066 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 27 Jan 2020 12:47:33 -0400 Subject: [PATCH 186/689] Update `c3` and `d3` (#7905) This updates include a number of bug fixes. The two charts we use these libraries for appear unaffected. --- package.json | 4 ++-- yarn.lock | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 9d9bdd9d9..c8c5a9e1f 100644 --- a/package.json +++ b/package.json @@ -78,13 +78,13 @@ "bip39": "^2.2.0", "bn.js": "^4.11.7", "browserify-derequire": "^0.9.4", - "c3": "^0.6.7", + "c3": "^0.7.10", "classnames": "^2.2.6", "clone": "^2.1.2", "content-hash": "^2.5.0", "copy-to-clipboard": "^3.0.8", "currency-formatter": "^1.4.2", - "d3": "^5.7.0", + "d3": "^5.15.0", "debounce": "1.1.0", "debounce-stream": "^2.0.0", "deep-extend": "^0.5.1", diff --git a/yarn.lock b/yarn.lock index f67d4ef5a..9ad1a668d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6445,12 +6445,12 @@ bytewise@~1.1.0: bytewise-core "^1.2.2" typewise "^1.0.3" -c3@^0.6.7: - version "0.6.10" - resolved "https://registry.yarnpkg.com/c3/-/c3-0.6.10.tgz#465f9bc5fbafb58c33c8ed641b0ec9717b158452" - integrity sha512-8HjpD1eSma75HI66hLQ+jD5KEvUMhSiiKfovQlyJk+Wxa1ebRL7Smxgu3ybBHkv9khe9m94TJRHpZ9Svcjo40w== +c3@^0.7.10: + version "0.7.12" + resolved "https://registry.yarnpkg.com/c3/-/c3-0.7.12.tgz#ad6205703bab9c2cbedc0223ba7fb2aabc31e94b" + integrity sha512-8gXyKMr9oM171aRGCOqezwEbWwEtIKmEkyvdfgH4oIunSsiTVWyw9Cz6os78LkYPRLMbHDgKcjkQh4EPCrRupQ== dependencies: - d3 "^5.0.0" + d3 "^5.8.0" cacache@^12.0.2: version "12.0.3" @@ -8408,10 +8408,10 @@ d3-zoom@1: d3-selection "1" d3-transition "1" -d3@^5.0.0, d3@^5.7.0: - version "5.7.0" - resolved "https://registry.yarnpkg.com/d3/-/d3-5.7.0.tgz#f189d338bdde62acf02f308918e0ec34dd7568f9" - integrity sha512-8KEIfx+dFm8PlbJN9PI0suazrZ41QcaAufsKE9PRcqYPWLngHIyWJZX96n6IQKePGgeSu0l7rtlueSSNq8Zc3g== +d3@^5.15.0, d3@^5.8.0: + version "5.15.0" + resolved "https://registry.yarnpkg.com/d3/-/d3-5.15.0.tgz#ffd44958e6a3cb8a59a84429c45429b8bca5677a" + integrity sha512-C+E80SL2nLLtmykZ6klwYj5rPqB5nlfN5LdWEAVdWPppqTD8taoJi2PxLZjPeYT8FFRR2yucXq+kBlOnnvZeLg== dependencies: d3-array "1" d3-axis "1" From f2a719a70ce207c341bd0470197c71672a298da5 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 27 Jan 2020 14:01:09 -0400 Subject: [PATCH 187/689] Replace `deep-extend` with `merge` from `lodash` (#7908) The `merge` function from `deep-extend` is at least mostly equivalent to `merge` from `lodash` - certainly in how we're using it. --- app/scripts/migrations/009.js | 2 +- app/scripts/migrations/010.js | 2 +- package.json | 1 - yarn.lock | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/scripts/migrations/009.js b/app/scripts/migrations/009.js index 2d359fb68..103321522 100644 --- a/app/scripts/migrations/009.js +++ b/app/scripts/migrations/009.js @@ -6,7 +6,7 @@ This migration breaks out the CurrencyController substate */ -import merge from 'deep-extend' +import { merge } from 'lodash' import clone from 'clone' diff --git a/app/scripts/migrations/010.js b/app/scripts/migrations/010.js index cc92a5f81..b97dd04d9 100644 --- a/app/scripts/migrations/010.js +++ b/app/scripts/migrations/010.js @@ -6,7 +6,7 @@ This migration breaks out the ShapeShiftController substate */ -import merge from 'deep-extend' +import { merge } from 'lodash' import clone from 'clone' diff --git a/package.json b/package.json index c8c5a9e1f..5e42d0e5c 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,6 @@ "d3": "^5.15.0", "debounce": "1.1.0", "debounce-stream": "^2.0.0", - "deep-extend": "^0.5.1", "deep-freeze-strict": "1.1.1", "detect-node": "^2.0.3", "dnode": "^1.2.2", diff --git a/yarn.lock b/yarn.lock index 9ad1a668d..267a45849 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8734,7 +8734,7 @@ deep-equal@^1.0.0, deep-equal@^1.0.1, deep-equal@~1.0.1: resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= -deep-extend@^0.5.0, deep-extend@^0.5.1: +deep-extend@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.1.tgz#b894a9dd90d3023fbf1c55a394fb858eb2066f1f" integrity sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w== From b75f81295367001e253576eba1b14579099c93e8 Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Mon, 27 Jan 2020 14:42:03 -0800 Subject: [PATCH 188/689] Improve LoginPerSite UX/devX and permissions logging (#7649) Update accounts permission history on accountsChanged Create PermissionsLogController Fix permissions activity log pruning Add selectors, background hooks for better UX Make selected account the first account returned Use enums for store keys in log controller Add last selected address history to PreferencesController --- app/scripts/controllers/permissions/enums.js | 72 ++++ app/scripts/controllers/permissions/index.js | 124 ++++-- .../permissions/loggerMiddleware.js | 168 -------- .../permissions/permissions-safe-methods.json | 51 --- .../controllers/permissions/permissionsLog.js | 405 ++++++++++++++++++ .../permissions/restrictedMethods.js | 2 +- app/scripts/controllers/preferences.js | 52 +++ app/scripts/metamask-controller.js | 19 +- package.json | 2 +- .../account-menu/account-menu.container.js | 16 +- ui/app/selectors/permissions.js | 48 +++ ui/app/selectors/selectors.js | 19 + ui/app/store/actions.js | 3 + yarn.lock | 8 +- 14 files changed, 724 insertions(+), 265 deletions(-) create mode 100644 app/scripts/controllers/permissions/enums.js delete mode 100644 app/scripts/controllers/permissions/loggerMiddleware.js delete mode 100644 app/scripts/controllers/permissions/permissions-safe-methods.json create mode 100644 app/scripts/controllers/permissions/permissionsLog.js create mode 100644 ui/app/selectors/permissions.js diff --git a/app/scripts/controllers/permissions/enums.js b/app/scripts/controllers/permissions/enums.js new file mode 100644 index 000000000..1e68eddbe --- /dev/null +++ b/app/scripts/controllers/permissions/enums.js @@ -0,0 +1,72 @@ + +export const WALLET_PREFIX = 'wallet_' + +export const HISTORY_STORE_KEY = 'permissionsHistory' + +export const LOG_STORE_KEY = 'permissionsLog' + +export const METADATA_STORE_KEY = 'domainMetadata' + +export const CAVEAT_NAMES = { + exposedAccounts: 'exposedAccounts', +} + +export const NOTIFICATION_NAMES = { + accountsChanged: 'wallet_accountsChanged', +} + +export const LOG_IGNORE_METHODS = [ + 'wallet_sendDomainMetadata', +] + +export const SAFE_METHODS = [ + 'web3_sha3', + 'net_listening', + 'net_peerCount', + 'net_version', + 'eth_blockNumber', + 'eth_call', + 'eth_chainId', + 'eth_coinbase', + 'eth_estimateGas', + 'eth_gasPrice', + 'eth_getBalance', + 'eth_getBlockByHash', + 'eth_getBlockByNumber', + 'eth_getBlockTransactionCountByHash', + 'eth_getBlockTransactionCountByNumber', + 'eth_getCode', + 'eth_getFilterChanges', + 'eth_getFilterLogs', + 'eth_getLogs', + 'eth_getStorageAt', + 'eth_getTransactionByBlockHashAndIndex', + 'eth_getTransactionByBlockNumberAndIndex', + 'eth_getTransactionByHash', + 'eth_getTransactionCount', + 'eth_getTransactionReceipt', + 'eth_getUncleByBlockHashAndIndex', + 'eth_getUncleByBlockNumberAndIndex', + 'eth_getUncleCountByBlockHash', + 'eth_getUncleCountByBlockNumber', + 'eth_getWork', + 'eth_hashrate', + 'eth_mining', + 'eth_newBlockFilter', + 'eth_newFilter', + 'eth_newPendingTransactionFilter', + 'eth_protocolVersion', + 'eth_sendRawTransaction', + 'eth_sendTransaction', + 'eth_sign', + 'personal_sign', + 'eth_signTypedData', + 'eth_signTypedData_v1', + 'eth_signTypedData_v3', + 'eth_submitHashrate', + 'eth_submitWork', + 'eth_syncing', + 'eth_uninstallFilter', + 'metamask_watchAsset', + 'wallet_watchAsset', +] diff --git a/app/scripts/controllers/permissions/index.js b/app/scripts/controllers/permissions/index.js index 5b7a1318f..ec45d9b2e 100644 --- a/app/scripts/controllers/permissions/index.js +++ b/app/scripts/controllers/permissions/index.js @@ -4,42 +4,46 @@ import ObservableStore from 'obs-store' import log from 'loglevel' import { CapabilitiesController as RpcCap } from 'rpc-cap' import { ethErrors } from 'eth-json-rpc-errors' + import getRestrictedMethods from './restrictedMethods' import createMethodMiddleware from './methodMiddleware' -import createLoggerMiddleware from './loggerMiddleware' +import PermissionsLogController from './permissionsLog' // Methods that do not require any permissions to use: -import SAFE_METHODS from './permissions-safe-methods.json' - -// some constants -const METADATA_STORE_KEY = 'domainMetadata' -const LOG_STORE_KEY = 'permissionsLog' -const HISTORY_STORE_KEY = 'permissionsHistory' -const WALLET_METHOD_PREFIX = 'wallet_' -const ACCOUNTS_CHANGED_NOTIFICATION = 'wallet_accountsChanged' - -export const CAVEAT_NAMES = { - exposedAccounts: 'exposedAccounts', -} +import { + SAFE_METHODS, // methods that do not require any permissions to use + WALLET_PREFIX, + METADATA_STORE_KEY, + LOG_STORE_KEY, + HISTORY_STORE_KEY, + CAVEAT_NAMES, + NOTIFICATION_NAMES, +} from './enums' export class PermissionsController { constructor ( { - platform, notifyDomain, notifyAllDomains, keyringController, + platform, notifyDomain, notifyAllDomains, getKeyringAccounts, } = {}, restoredPermissions = {}, restoredState = {}) { + this.store = new ObservableStore({ [METADATA_STORE_KEY]: restoredState[METADATA_STORE_KEY] || {}, [LOG_STORE_KEY]: restoredState[LOG_STORE_KEY] || [], [HISTORY_STORE_KEY]: restoredState[HISTORY_STORE_KEY] || {}, }) - this.notifyDomain = notifyDomain + + this._notifyDomain = notifyDomain this.notifyAllDomains = notifyAllDomains - this.keyringController = keyringController + this.getKeyringAccounts = getKeyringAccounts this._platform = platform this._restrictedMethods = getRestrictedMethods(this) + this.permissionsLogController = new PermissionsLogController({ + restrictedMethods: Object.keys(this._restrictedMethods), + store: this.store, + }) this._initializePermissions(restoredPermissions) } @@ -56,14 +60,7 @@ export class PermissionsController { const engine = new JsonRpcEngine() - engine.push(createLoggerMiddleware({ - walletPrefix: WALLET_METHOD_PREFIX, - restrictedMethods: Object.keys(this._restrictedMethods), - ignoreMethods: [ 'wallet_sendDomainMetadata' ], - store: this.store, - logStoreKey: LOG_STORE_KEY, - historyStoreKey: HISTORY_STORE_KEY, - })) + engine.push(this.permissionsLogController.createMiddleware()) engine.push(createMethodMiddleware({ store: this.store, @@ -107,7 +104,7 @@ export class PermissionsController { } /** - * Submits a permissions request to rpc-cap. Internal use only. + * Submits a permissions request to rpc-cap. Internal, background use only. * * @param {string} origin - The origin string. * @param {IRequestedPermissions} permissions - The requested permissions. @@ -222,22 +219,26 @@ export class PermissionsController { } /** - * Update the accounts exposed to the given origin. + * Update the accounts exposed to the given origin. Changes the eth_accounts + * permissions and emits accountsChanged. + * At least one account must be exposed. If no accounts are to be exposed, the + * eth_accounts permissions should be removed completely. + * * Throws error if the update fails. * * @param {string} origin - The origin to change the exposed accounts for. * @param {string[]} accounts - The new account(s) to expose. */ - async updateExposedAccounts (origin, accounts) { + async updatePermittedAccounts (origin, accounts) { - await this.validateExposedAccounts(accounts) + await this.validatePermittedAccounts(accounts) this.permissions.updateCaveatFor( origin, 'eth_accounts', CAVEAT_NAMES.exposedAccounts, accounts ) this.notifyDomain(origin, { - method: ACCOUNTS_CHANGED_NOTIFICATION, + method: NOTIFICATION_NAMES.accountsChanged, result: accounts, }) } @@ -255,7 +256,7 @@ export class PermissionsController { if (ethAccounts) { - await this.validateExposedAccounts(accounts) + await this.validatePermittedAccounts(accounts) if (!ethAccounts.caveats) { ethAccounts.caveats = [] @@ -282,14 +283,14 @@ export class PermissionsController { * * @param {string[]} accounts - An array of addresses. */ - async validateExposedAccounts (accounts) { + async validatePermittedAccounts (accounts) { if (!Array.isArray(accounts) || accounts.length === 0) { throw new Error('Must provide non-empty array of account(s).') } // assert accounts exist - const allAccounts = await this.keyringController.getAccounts() + const allAccounts = await this.getKeyringAccounts() accounts.forEach(acc => { if (!allAccounts.includes(acc)) { throw new Error(`Unknown account: ${acc}`) @@ -297,6 +298,29 @@ export class PermissionsController { }) } + notifyDomain (origin, payload) { + + // if the accounts changed from the perspective of the dapp, + // update "last seen" time for the origin and account(s) + // exception: no accounts -> no times to update + if ( + payload.method === NOTIFICATION_NAMES.accountsChanged && + Array.isArray(payload.result) + ) { + this.permissionsLogController.updateAccountsHistory( + origin, payload.result + ) + } + + this._notifyDomain(origin, payload) + + // NOTE: + // we don't check for accounts changing in the notifyAllDomains case, + // because the log only records when accounts were last seen, + // and the accounts only change for all domains at once when permissions + // are removed + } + /** * Removes the given permissions for the given domain. * @param {Object} domains { origin: [permissions] } @@ -312,7 +336,7 @@ export class PermissionsController { if (methodName === 'eth_accounts') { this.notifyDomain( origin, - { method: ACCOUNTS_CHANGED_NOTIFICATION, result: [] } + { method: NOTIFICATION_NAMES.accountsChanged, result: [] } ) } @@ -322,13 +346,41 @@ export class PermissionsController { }) } + /** + * When a new account is selected in the UI for 'origin', emit accountsChanged + * to 'origin' if the selected account is permitted. + * @param {string} origin - The origin. + * @param {string} account - The newly selected account's address. + */ + async handleNewAccountSelected (origin, account) { + + const permittedAccounts = await this.getAccounts(origin) + + // do nothing if the account is not permitted for the origin, or + // if it's already first in the array of permitted accounts + if ( + !account || !permittedAccounts.includes(account) || + permittedAccounts[0] === account + ) { + return + } + + const newPermittedAccounts = [account].concat( + permittedAccounts.filter(_account => _account !== account) + ) + + // update permitted accounts to ensure that accounts are returned + // in the same order every time + this.updatePermittedAccounts(origin, newPermittedAccounts) + } + /** * Removes all known domains and their related permissions. */ clearPermissions () { this.permissions.clearDomains() this.notifyAllDomains({ - method: ACCOUNTS_CHANGED_NOTIFICATION, + method: NOTIFICATION_NAMES.accountsChanged, result: [], }) } @@ -352,7 +404,7 @@ export class PermissionsController { safeMethods: SAFE_METHODS, // optional prefix for internal methods - methodPrefix: WALLET_METHOD_PREFIX, + methodPrefix: WALLET_PREFIX, restrictedMethods: this._restrictedMethods, @@ -379,5 +431,5 @@ export class PermissionsController { } export function addInternalMethodPrefix (method) { - return WALLET_METHOD_PREFIX + method + return WALLET_PREFIX + method } diff --git a/app/scripts/controllers/permissions/loggerMiddleware.js b/app/scripts/controllers/permissions/loggerMiddleware.js deleted file mode 100644 index 3c9325442..000000000 --- a/app/scripts/controllers/permissions/loggerMiddleware.js +++ /dev/null @@ -1,168 +0,0 @@ -import clone from 'clone' -import { isValidAddress } from 'ethereumjs-util' - -const LOG_LIMIT = 100 - -/** - * Create middleware for logging requests and responses to restricted and - * permissions-related methods. - */ -export default function createLoggerMiddleware ({ - walletPrefix, restrictedMethods, store, logStoreKey, historyStoreKey, ignoreMethods, -}) { - return (req, res, next, _end) => { - let activityEntry, requestedMethods - const { origin, method } = req - const isInternal = method.startsWith(walletPrefix) - if ((isInternal || restrictedMethods.includes(method)) && !ignoreMethods.includes(method)) { - activityEntry = logActivity(req, isInternal) - if (method === `${walletPrefix}requestPermissions`) { - requestedMethods = getRequestedMethods(req) - } - } else if (method === 'eth_requestAccounts') { - activityEntry = logActivity(req, isInternal) - requestedMethods = [ 'eth_accounts' ] - } else { - return next() - } - - next(cb => { - const time = Date.now() - addResponse(activityEntry, res, time) - if (!res.error && requestedMethods) { - logHistory(requestedMethods, origin, res.result, time, method === 'eth_requestAccounts') - } - cb() - }) - } - - function logActivity (request, isInternal) { - const activityEntry = { - id: request.id, - method: request.method, - methodType: isInternal ? 'internal' : 'restricted', - origin: request.origin, - request: cloneObj(request), - requestTime: Date.now(), - response: null, - responseTime: null, - success: null, - } - commitActivity(activityEntry) - return activityEntry - } - - function addResponse (activityEntry, response, time) { - if (!response) { - return - } - activityEntry.response = cloneObj(response) - activityEntry.responseTime = time - activityEntry.success = !response.error - } - - function commitActivity (entry) { - const logs = store.getState()[logStoreKey] - if (logs.length > LOG_LIMIT - 2) { - logs.pop() - } - logs.push(entry) - store.updateState({ [logStoreKey]: logs }) - } - - function getRequestedMethods (request) { - if ( - !request.params || - typeof request.params[0] !== 'object' || - Array.isArray(request.params[0]) - ) { - return null - } - return Object.keys(request.params[0]) - } - - function logHistory (requestedMethods, origin, result, time, isEthRequestAccounts) { - let accounts, entries - if (isEthRequestAccounts) { - accounts = result - const accountToTimeMap = accounts.reduce((acc, account) => ({ ...acc, [account]: time }), {}) - entries = { 'eth_accounts': { accounts: accountToTimeMap, lastApproved: time } } - } else { - entries = result - ? result - .map(perm => { - if (perm.parentCapability === 'eth_accounts') { - accounts = getAccountsFromPermission(perm) - } - return perm.parentCapability - }) - .reduce((acc, m) => { - if (requestedMethods.includes(m)) { - if (m === 'eth_accounts') { - const accountToTimeMap = accounts.reduce((acc, account) => ({ ...acc, [account]: time }), {}) - acc[m] = { lastApproved: time, accounts: accountToTimeMap } - } else { - acc[m] = { lastApproved: time } - } - } - return acc - }, {}) - : {} - } - - if (Object.keys(entries).length > 0) { - commitHistory(origin, entries) - } - } - - function commitHistory (origin, entries) { - const history = store.getState()[historyStoreKey] || {} - const newOriginHistory = { - ...history[origin], - ...entries, - } - - if (history[origin] && history[origin]['eth_accounts'] && entries['eth_accounts']) { - newOriginHistory['eth_accounts'] = { - lastApproved: entries['eth_accounts'].lastApproved, - accounts: { - ...history[origin]['eth_accounts'].accounts, - ...entries['eth_accounts'].accounts, - }, - } - } - - history[origin] = newOriginHistory - - store.updateState({ [historyStoreKey]: history }) - } -} - -// the call to clone is set to disallow circular references -// we attempt cloning at a depth of 3 and 2, then return a -// shallow copy of the object -function cloneObj (obj) { - for (let i = 3; i > 1; i--) { - try { - return clone(obj, false, i) - } catch (_) {} - } - return { ...obj } -} - -function getAccountsFromPermission (perm) { - if (perm.parentCapability !== 'eth_accounts' || !perm.caveats) { - return [] - } - const accounts = {} - for (const c of perm.caveats) { - if (c.type === 'filterResponse' && Array.isArray(c.value)) { - for (const v of c.value) { - if (isValidAddress(v)) { - accounts[v] = true - } - } - } - } - return Object.keys(accounts) -} diff --git a/app/scripts/controllers/permissions/permissions-safe-methods.json b/app/scripts/controllers/permissions/permissions-safe-methods.json deleted file mode 100644 index 780a52ede..000000000 --- a/app/scripts/controllers/permissions/permissions-safe-methods.json +++ /dev/null @@ -1,51 +0,0 @@ -[ - "web3_sha3", - "net_listening", - "net_peerCount", - "net_version", - "eth_blockNumber", - "eth_call", - "eth_chainId", - "eth_coinbase", - "eth_estimateGas", - "eth_gasPrice", - "eth_getBalance", - "eth_getBlockByHash", - "eth_getBlockByNumber", - "eth_getBlockTransactionCountByHash", - "eth_getBlockTransactionCountByNumber", - "eth_getCode", - "eth_getFilterChanges", - "eth_getFilterLogs", - "eth_getLogs", - "eth_getStorageAt", - "eth_getTransactionByBlockHashAndIndex", - "eth_getTransactionByBlockNumberAndIndex", - "eth_getTransactionByHash", - "eth_getTransactionCount", - "eth_getTransactionReceipt", - "eth_getUncleByBlockHashAndIndex", - "eth_getUncleByBlockNumberAndIndex", - "eth_getUncleCountByBlockHash", - "eth_getUncleCountByBlockNumber", - "eth_getWork", - "eth_hashrate", - "eth_mining", - "eth_newBlockFilter", - "eth_newFilter", - "eth_newPendingTransactionFilter", - "eth_protocolVersion", - "eth_sendRawTransaction", - "eth_sendTransaction", - "eth_sign", - "personal_sign", - "eth_signTypedData", - "eth_signTypedData_v1", - "eth_signTypedData_v3", - "eth_submitHashrate", - "eth_submitWork", - "eth_syncing", - "eth_uninstallFilter", - "wallet_watchAsset", - "metamask_watchAsset" -] diff --git a/app/scripts/controllers/permissions/permissionsLog.js b/app/scripts/controllers/permissions/permissionsLog.js new file mode 100644 index 000000000..caa369a2e --- /dev/null +++ b/app/scripts/controllers/permissions/permissionsLog.js @@ -0,0 +1,405 @@ + +import clone from 'clone' +import { isValidAddress } from 'ethereumjs-util' +import { + CAVEAT_NAMES, + HISTORY_STORE_KEY, + LOG_STORE_KEY, + LOG_IGNORE_METHODS, + WALLET_PREFIX, +} from './enums' + +const LOG_LIMIT = 100 + +/** + * Controller with middleware for logging requests and responses to restricted + * and permissions-related methods. + */ +export default class PermissionsLogController { + + constructor ({ restrictedMethods, store }) { + this.restrictedMethods = restrictedMethods + this.store = store + } + + /** + * Get the activity log. + * + * @returns {Array} - The activity log. + */ + getActivityLog () { + return this.store.getState()[LOG_STORE_KEY] || [] + } + + /** + * Update the activity log. + * + * @param {Array} logs - The new activity log array. + */ + updateActivityLog (logs) { + this.store.updateState({ [LOG_STORE_KEY]: logs }) + } + + /** + * Get the permissions history log. + * + * @returns {Object} - The permissions history log. + */ + getHistory () { + return this.store.getState()[HISTORY_STORE_KEY] || {} + } + + /** + * Update the permissions history log. + * + * @param {Object} history - The new permissions history log object. + */ + updateHistory (history) { + this.store.updateState({ [HISTORY_STORE_KEY]: history }) + } + + /** + * Updates the exposed account history for the given origin. + * Sets the 'last seen' time to Date.now() for the given accounts. + * + * @param {string} origin - The origin that the accounts are exposed to. + * @param {Array} accounts - The accounts. + */ + updateAccountsHistory (origin, accounts) { + + if (accounts.length === 0) { + return + } + + const accountToTimeMap = getAccountToTimeMap(accounts, Date.now()) + + this.commitNewHistory(origin, { + eth_accounts: { + accounts: accountToTimeMap, + }, + }) + } + + /** + * Create a permissions log middleware. + * + * @returns {JsonRpcEngineMiddleware} - The permissions log middleware. + */ + createMiddleware () { + return (req, res, next, _end) => { + + let requestedMethods + const { origin, method, id: requestId } = req + const isInternal = method.startsWith(WALLET_PREFIX) + + // we only log certain methods + if ( + !LOG_IGNORE_METHODS.includes(method) && + (isInternal || this.restrictedMethods.includes(method)) + ) { + + this.logActivityRequest(req, isInternal) + + if (method === `${WALLET_PREFIX}requestPermissions`) { + // get the corresponding methods from the requested permissions + requestedMethods = this.getRequestedMethods(req) + } + } else if (method === 'eth_requestAccounts') { + + // eth_requestAccounts is a special case; we need to extract the accounts + // from it + this.logActivityRequest(req, isInternal) + requestedMethods = [ 'eth_accounts' ] + } else { + // no-op + return next() + } + + // call next with a return handler for capturing the response + next(cb => { + + const time = Date.now() + this.logActivityResponse(requestId, res, time) + + if (!res.error && requestedMethods) { + // any permissions or accounts changes will be recorded on the response, + // so we only log permissions history here + this.logPermissionsHistory( + requestedMethods, origin, res.result, time, + method === 'eth_requestAccounts', + ) + } + cb() + }) + } + } + + /** + * Creates and commits an activity log entry, without response data. + * + * @param {Object} request - The request object. + * @param {boolean} isInternal - Whether the request is internal. + */ + logActivityRequest (request, isInternal) { + const activityEntry = { + id: request.id, + method: request.method, + methodType: isInternal ? 'internal' : 'restricted', + origin: request.origin, + request: cloneObj(request), + requestTime: Date.now(), + response: null, + responseTime: null, + success: null, + } + this.commitNewActivity(activityEntry) + } + + /** + * Adds response data to an existing activity log entry and re-commits it. + * + * @param {string} id - The original request id. + * @param {Object} response - The response object. + * @param {number} time - Output from Date.now() + */ + logActivityResponse (id, response, time) { + + if (!id || !response) { + return + } + + const logs = this.getActivityLog() + const index = getLastIndexOfObjectArray(logs, 'id', id) + if (index === -1) { + return + } + + const entry = logs[index] + entry.response = cloneObj(response) + entry.responseTime = time + entry.success = !response.error + + this.updateActivityLog(logs) + } + + /** + * Commit a new entry to the activity log. + * Removes the oldest entry from the log if it exceeds the log limit. + * + * @param {Object} entry - The activity log entry. + */ + commitNewActivity (entry) { + + const logs = this.getActivityLog() + + // add new entry to end of log + logs.push(entry) + + // remove oldest log if exceeding size limit + if (logs.length > LOG_LIMIT) { + logs.shift() + } + + this.updateActivityLog(logs) + } + + /** + * Create new permissions history log entries, if any, and commit them. + * + * @param {Array} requestedMethods - The method names corresponding to the requested permissions. + * @param {string} origin - The origin of the permissions request. + * @param {Array { + + if (perm.parentCapability === 'eth_accounts') { + accounts = this.getAccountsFromPermission(perm) + } + + return perm.parentCapability + }) + .reduce((acc, method) => { + + if (requestedMethods.includes(method)) { + + if (method === 'eth_accounts') { + + const accountToTimeMap = getAccountToTimeMap(accounts, time) + + acc[method] = { + lastApproved: time, + accounts: accountToTimeMap, + } + } else { + acc[method] = { lastApproved: time } + } + } + + return acc + }, {}) + : {} // no result (e.g. in case of error), no log + } + + if (Object.keys(newEntries).length > 0) { + this.commitNewHistory(origin, newEntries) + } + } + + /** + * Commit new entries to the permissions history log. + * Merges the history for the given origin, overwriting existing entries + * with the same key (permission name). + * + * @param {string} origin - The requesting origin. + * @param {Object} newEntries - The new entries to commit. + */ + commitNewHistory (origin, newEntries) { + + // a simple merge updates most permissions + const history = this.getHistory() + const newOriginHistory = { + ...history[origin], + ...newEntries, + } + + // eth_accounts requires special handling, because of information + // we store about the accounts + const existingEthAccountsEntry = ( + history[origin] && history[origin]['eth_accounts'] + ) + const newEthAccountsEntry = newEntries['eth_accounts'] + if (existingEthAccountsEntry && newEthAccountsEntry) { + + // we may intend to update just the accounts, not the permission + // itself + const lastApproved = ( + newEthAccountsEntry.lastApproved || + existingEthAccountsEntry.lastApproved + ) + + // merge old and new eth_accounts history entries + newOriginHistory['eth_accounts'] = { + lastApproved, + accounts: { + ...existingEthAccountsEntry.accounts, + ...newEthAccountsEntry.accounts, + }, + } + } + + history[origin] = newOriginHistory + + this.updateHistory(history) + } + + /** + * Get all requested methods from a permissions request. + * + * @param {Object} request - The request object. + * @returns {Array} - The names of the requested permissions. + */ + getRequestedMethods (request) { + if ( + !request.params || + typeof request.params[0] !== 'object' || + Array.isArray(request.params[0]) + ) { + return null + } + return Object.keys(request.params[0]) + } + + /** + * Get the permitted accounts from an eth_accounts permissions object. + * Returns an empty array if the permission is not eth_accounts. + * + * @param {Object} perm - The permissions object. + * @returns {Array} - The permitted accounts. + */ + getAccountsFromPermission (perm) { + + if (perm.parentCapability !== 'eth_accounts' || !perm.caveats) { + return [] + } + + const accounts = {} + for (const caveat of perm.caveats) { + + if ( + caveat.name === CAVEAT_NAMES.exposedAccounts && + Array.isArray(caveat.value) + ) { + + for (const value of caveat.value) { + if (isValidAddress(value)) { + accounts[value] = true + } + } + } + } + return Object.keys(accounts) + } +} + +// helper functions + +// the call to clone is set to disallow circular references +// we attempt cloning at a depth of 3 and 2, then return a +// shallow copy of the object +function cloneObj (obj) { + + for (let i = 3; i > 1; i--) { + try { + return clone(obj, false, i) + } catch (_) {} + } + return { ...obj } +} + +function getAccountToTimeMap (accounts, time) { + return accounts.reduce( + (acc, account) => ({ ...acc, [account]: time }), {} + ) +} + +function getLastIndexOfObjectArray (array, key, value) { + + if (Array.isArray(array) && array.length > 0) { + + for (let i = array.length - 1; i >= 0; i--) { + + if (typeof array[i] !== 'object') { + throw new Error(`Encountered non-Object element at index ${i}`) + } + + if (array[i][key] === value) { + return i + } + } + } + return -1 +} diff --git a/app/scripts/controllers/permissions/restrictedMethods.js b/app/scripts/controllers/permissions/restrictedMethods.js index 14d38b05c..b77336cfe 100644 --- a/app/scripts/controllers/permissions/restrictedMethods.js +++ b/app/scripts/controllers/permissions/restrictedMethods.js @@ -4,7 +4,7 @@ export default function getRestrictedMethods (permissionsController) { 'eth_accounts': { description: 'View the address of the selected account', method: (_, res, __, end) => { - permissionsController.keyringController.getAccounts() + permissionsController.getKeyringAccounts() .then((accounts) => { res.result = accounts end() diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 76bb242f2..e9a10ebce 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -61,6 +61,8 @@ class PreferencesController { // ENS decentralized website resolution ipfsGateway: 'ipfs.dweb.link', + + lastSelectedAddressByOrigin: {}, }, opts.initState) this.diagnostics = opts.diagnostics @@ -369,6 +371,56 @@ class PreferencesController { return this.store.getState().selectedAddress } + /** + * Update the last selected address for the given origin. + * + * @param {string} origin - The origin for which the address was selected. + * @param {string} address - The new selected address. + */ + setLastSelectedAddress (origin, address) { + + const { lastSelectedAddressByOrigin } = this.store.getState() + + // only update state if it's necessary + if (lastSelectedAddressByOrigin[origin] !== address) { + lastSelectedAddressByOrigin[origin] = address + this.store.updateState({ lastSelectedAddressByOrigin }) + } + } + + /** + * Remove the selected address history for the given origin. + * + * @param {Array} origins - The origin to remove the last selected address for. + */ + removeLastSelectedAddressesFor (origins) { + + if ( + !Array.isArray(origins) || + (origins.length > 0 && typeof origins[0] !== 'string') + ) { + throw new Error('Expected array of strings') + } + + if (origins.length === 0) { + return + } + + const { lastSelectedAddressByOrigin } = this.store.getState() + + origins.forEach(origin => { + delete lastSelectedAddressByOrigin[origin] + }) + this.store.updateState({ lastSelectedAddressByOrigin }) + } + + /** + * Clears the selected address history. + */ + clearLastSelectedAddressHistory () { + this.store.updateState({ lastSelectedAddressByOrigin: {} }) + } + /** * Contains data about tokens users add to their account. * @typedef {Object} AddedToken diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 6ce3e05be..9dc8f0b2c 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -205,7 +205,7 @@ export default class MetamaskController extends EventEmitter { this.keyringController.memStore.subscribe((s) => this._onKeyringControllerUpdate(s)) this.permissionsController = new PermissionsController({ - keyringController: this.keyringController, + getKeyringAccounts: this.keyringController.getAccounts.bind(this.keyringController), platform: opts.platform, notifyDomain: this.notifyConnections.bind(this), notifyAllDomains: this.notifyAllConnections.bind(this), @@ -490,6 +490,8 @@ export default class MetamaskController extends EventEmitter { setPreference: nodeify(preferencesController.setPreference, preferencesController), completeOnboarding: nodeify(preferencesController.completeOnboarding, preferencesController), addKnownMethodData: nodeify(preferencesController.addKnownMethodData, preferencesController), + clearLastSelectedAddressHistory: nodeify(preferencesController.clearLastSelectedAddressHistory, preferencesController), + removeLastSelectedAddressesFor: nodeify(preferencesController.removeLastSelectedAddressesFor, preferencesController), // BlacklistController whitelistPhishingDomain: this.whitelistPhishingDomain.bind(this), @@ -557,8 +559,9 @@ export default class MetamaskController extends EventEmitter { getApprovedAccounts: nodeify(permissionsController.getAccounts.bind(permissionsController)), rejectPermissionsRequest: nodeify(permissionsController.rejectPermissionsRequest, permissionsController), removePermissionsFor: permissionsController.removePermissionsFor.bind(permissionsController), - updateExposedAccounts: nodeify(permissionsController.updateExposedAccounts, permissionsController), + updatePermittedAccounts: nodeify(permissionsController.updatePermittedAccounts, permissionsController), legacyExposeAccounts: nodeify(permissionsController.legacyExposeAccounts, permissionsController), + handleNewAccountSelected: nodeify(this.handleNewAccountSelected, this), getRequestAccountTabIds: (cb) => cb(null, this.getRequestAccountTabIds()), getOpenMetamaskTabsIds: (cb) => cb(null, this.getOpenMetamaskTabsIds()), @@ -1020,6 +1023,18 @@ export default class MetamaskController extends EventEmitter { await this.preferencesController.setSelectedAddress(accounts[0]) } + /** + * Handle when a new account is selected for the given origin in the UI. + * Stores the address by origin and notifies external providers associated + * with the origin. + * @param {string} origin - The origin for which the address was selected. + * @param {string} address - The new selected address. + */ + async handleNewAccountSelected (origin, address) { + this.permissionsController.handleNewAccountSelected(origin, address) + this.preferencesController.setLastSelectedAddress(origin, address) + } + // --------------------------------------------------------------------------- // Identity Management (signature operations) diff --git a/package.json b/package.json index 5e42d0e5c..c056d1053 100644 --- a/package.json +++ b/package.json @@ -172,7 +172,7 @@ "redux-logger": "^3.0.6", "redux-thunk": "^2.2.0", "reselect": "^3.0.1", - "rpc-cap": "^1.0.1", + "rpc-cap": "^1.0.3", "safe-event-emitter": "^1.0.1", "safe-json-stringify": "^1.2.0", "single-call-balance-checker-abi": "^1.0.0", diff --git a/ui/app/components/app/account-menu/account-menu.container.js b/ui/app/components/app/account-menu/account-menu.container.js index 206afb176..7bc62603e 100644 --- a/ui/app/components/app/account-menu/account-menu.container.js +++ b/ui/app/components/app/account-menu/account-menu.container.js @@ -15,6 +15,8 @@ import { getMetaMaskKeyrings, getOriginOfCurrentTab, getSelectedAddress, + // getLastSelectedAddress, + // getPermittedAccounts, } from '../../../selectors/selectors' import AccountMenu from './account-menu.component' @@ -26,12 +28,22 @@ const SHOW_SEARCH_ACCOUNTS_MIN_COUNT = 5 function mapStateToProps (state) { const { metamask: { isAccountMenuOpen } } = state const accounts = getMetaMaskAccountsOrdered(state) + const origin = getOriginOfCurrentTab(state) + const selectedAddress = getSelectedAddress(state) + + /** + * TODO:LoginPerSite:ui + * - propagate the relevant props below after computing them + */ + // const lastSelectedAddress = getLastSelectedAddress(state, origin) + // const permittedAccounts = getPermittedAccounts(state, origin) + // const selectedAccountIsPermitted = permittedAccounts.includes(selectedAddress) return { isAccountMenuOpen, addressConnectedDomainMap: getAddressConnectedDomainMap(state), - originOfCurrentTab: getOriginOfCurrentTab(state), - selectedAddress: getSelectedAddress(state), + originOfCurrentTab: origin, + selectedAddress: selectedAddress, keyrings: getMetaMaskKeyrings(state), accounts, shouldShowAccountsSearch: accounts.length >= SHOW_SEARCH_ACCOUNTS_MIN_COUNT, diff --git a/ui/app/selectors/permissions.js b/ui/app/selectors/permissions.js new file mode 100644 index 000000000..9399934a9 --- /dev/null +++ b/ui/app/selectors/permissions.js @@ -0,0 +1,48 @@ + +import { createSelector } from 'reselect' +import { + CAVEAT_NAMES, +} from '../../../app/scripts/controllers/permissions/enums' + +const permissionsSelector = (state, origin) => { + return origin && state.metamask.domains && state.metamask.domains[origin] +} + +// all permissions for the origin probably too expensive for deep equality check +const accountsPermissionSelector = createSelector( + permissionsSelector, + (domain = {}) => { + + return ( + Array.isArray(domain.permissions) + ? domain.permissions.find( + perm => perm.parentCapability === 'eth_accounts' + ) + : {} + ) + } +) + +/** + * Selects the permitted accounts from an eth_accounts permission. + * Expects input from accountsPermissionsSelector. + * @returns - An empty array or an array of accounts. + */ +export const getPermittedAccounts = createSelector( + accountsPermissionSelector, // deep equal check performed on this output + (accountsPermission = {}) => { + + const accountsCaveat = ( + Array.isArray(accountsPermission.caveats) && + accountsPermission.caveats.find( + c => c.name === CAVEAT_NAMES.exposedAccounts + ) + ) + + return ( + accountsCaveat && Array.isArray(accountsCaveat.value) + ? accountsCaveat.value + : [] + ) + } +) diff --git a/ui/app/selectors/selectors.js b/ui/app/selectors/selectors.js index 410e09520..045eaf43a 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/app/selectors/selectors.js @@ -12,6 +12,10 @@ import { getOriginFromUrl, } from '../helpers/utils/util' +import { getPermittedAccounts } from './permissions' + +export { getPermittedAccounts } from './permissions' + export function getNetworkIdentifier (state) { const { metamask: { provider: { type, nickname, rpcTarget } } } = state @@ -87,6 +91,21 @@ export function getSelectedAddress (state) { return selectedAddress } +function lastSelectedAddressSelector (state, origin) { + return state.metamask.lastSelectedAddressByOrigin[origin] || null +} + +// not using reselect here since the returns are contingent; +// we have no reasons to recompute the permitted accounts if there +// exists a lastSelectedAddress +export function getLastSelectedAddress (state, origin) { + return ( + lastSelectedAddressSelector(state, origin) || + getPermittedAccounts(state, origin)[0] || // always returns array + getSelectedAddress(state) + ) +} + export function getSelectedIdentity (state) { const selectedAddress = getSelectedAddress(state) const identities = state.metamask.identities diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 6123bfecb..01f4ea842 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -1235,6 +1235,7 @@ export function showAccountDetail (address) { if (err) { return dispatch(displayWarning(err.message)) } + background.handleNewAccountSelected(origin, address) dispatch(updateTokens(tokens)) dispatch({ type: actionConstants.SHOW_ACCOUNT_DETAIL, @@ -2208,6 +2209,7 @@ export function legacyExposeAccounts (origin, accounts) { export function removePermissionsFor (domains) { return () => { background.removePermissionsFor(domains) + background.removeLastSelectedAddressesFor(Object.keys(domains)) } } @@ -2217,6 +2219,7 @@ export function removePermissionsFor (domains) { export function clearPermissions () { return () => { background.clearPermissions() + background.clearLastSelectedAddressHistory() } } diff --git a/yarn.lock b/yarn.lock index 267a45849..a13a1d6c8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25323,10 +25323,10 @@ rn-host-detect@^1.1.5: resolved "https://registry.yarnpkg.com/rn-host-detect/-/rn-host-detect-1.1.5.tgz#fbecb982b73932f34529e97932b9a63e58d8deb6" integrity sha512-ufk2dFT3QeP9HyZ/xTuMtW27KnFy815CYitJMqQm+pgG3ZAtHBsrU8nXizNKkqXGy3bQmhEoloVbrfbvMJMqkg== -rpc-cap@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/rpc-cap/-/rpc-cap-1.0.1.tgz#c19f6651d9d003256c73831422e0bd60b4fa8b55" - integrity sha512-M75F5IfohYkwGvitWmstimP9OL+9h10m1ZRC2zCB1Nli4EPzL8n5re58xlrcOnwOO38FdSSPfcwcCzMuVT8K2g== +rpc-cap@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/rpc-cap/-/rpc-cap-1.0.3.tgz#c58f99ee97a92441f4310f407c0f40fecdbf0e78" + integrity sha512-6lheD7UU4IY+OpILTL65E5NQWFPfG1Igd/CAGbnMJY+3szmQ9mUrf4/3bbcvNhu64Q/KYfCstVhxJREmTeFLOg== dependencies: clone "^2.1.2" eth-json-rpc-errors "^2.0.0" From 07f429408860510a30620c629e19820302c9e847 Mon Sep 17 00:00:00 2001 From: Brandon Lucas <38222767+thebrandonlucas@users.noreply.github.com> Date: Tue, 28 Jan 2020 07:40:03 -0600 Subject: [PATCH 189/689] disable import button on Import Account screen for empty string/file (#7912) * disable import button on Import Account screen for empty string/file * use refs to access DOM for import-account --- CHANGELOG.md | 1 + .../create-account/import-account/json.js | 19 +++++++++++++++++-- .../import-account/private-key.js | 18 ++++++++++++++++-- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65b25c13d..f4bb4f3fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## Current Develop Branch +- [#7912](https://github.com/MetaMask/metamask-extension/pull/7912): Disable import button for empty string/file ## 7.7.0 Thu Nov 28 2019 - [#7004](https://github.com/MetaMask/metamask-extension/pull/7004): Connect distinct accounts per site diff --git a/ui/app/pages/create-account/import-account/json.js b/ui/app/pages/create-account/import-account/json.js index 5e5671d31..11af1b17d 100644 --- a/ui/app/pages/create-account/import-account/json.js +++ b/ui/app/pages/create-account/import-account/json.js @@ -14,10 +14,14 @@ const HELP_LINK = 'https://metamask.zendesk.com/hc/en-us/articles/360015489331-I class JsonImportSubview extends Component { state = { fileContents: '', + isEmpty: true, } + inputRef = React.createRef() + render () { const { error } = this.props + const enabled = !this.state.isEmpty && this.state.fileContents !== '' return (
    @@ -40,6 +44,8 @@ class JsonImportSubview extends Component { placeholder={this.context.t('enterPassword')} id="json-password-box" onKeyPress={this.createKeyringOnEnter.bind(this)} + onChange={() => this.checkInputEmpty()} + ref={this.inputRef} />
    @@ -90,8 +97,7 @@ class JsonImportSubview extends Component { return displayWarning(message) } - const passwordInput = document.getElementById('json-password-box') - const password = passwordInput.value + const password = this.inputRef.current.value importNewJsonAccount([ fileContents, password ]) .then(({ selectedAddress }) => { @@ -119,6 +125,15 @@ class JsonImportSubview extends Component { }) .catch(err => err && displayWarning(err.message || err)) } + + checkInputEmpty () { + const password = this.inputRef.current.value + let isEmpty = true + if (password !== '') { + isEmpty = false + } + this.setState({ isEmpty }) + } } JsonImportSubview.propTypes = { diff --git a/ui/app/pages/create-account/import-account/private-key.js b/ui/app/pages/create-account/import-account/private-key.js index 988c42e6b..c42755621 100644 --- a/ui/app/pages/create-account/import-account/private-key.js +++ b/ui/app/pages/create-account/import-account/private-key.js @@ -23,10 +23,12 @@ class PrivateKeyImportView extends Component { error: PropTypes.node, } + inputRef = React.createRef() + + state = { isEmpty: true } createNewKeychain () { - const input = document.getElementById('private-key-box') - const privateKey = input.value + const privateKey = this.inputRef.current.value const { importNewAccount, history, displayWarning, setSelectedAddress, firstAddress } = this.props importNewAccount('Private Key', [ privateKey ]) @@ -63,6 +65,15 @@ class PrivateKeyImportView extends Component { } } + checkInputEmpty () { + const privateKey = this.inputRef.current.value + let isEmpty = true + if (privateKey !== '') { + isEmpty = false + } + this.setState({ isEmpty }) + } + render () { const { error, displayWarning } = this.props @@ -77,6 +88,8 @@ class PrivateKeyImportView extends Component { type="password" id="private-key-box" onKeyPress={e => this.createKeyringOnEnter(e)} + onChange={() => this.checkInputEmpty()} + ref={this.inputRef} />
    @@ -96,6 +109,7 @@ class PrivateKeyImportView extends Component { large className="new-account-create-form__button" onClick={() => this.createNewKeychain()} + disabled={this.state.isEmpty} > {this.context.t('import')} From 7921196536c668c8f2cc780ad6a8a258a007fcbc Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 28 Jan 2020 09:42:07 -0400 Subject: [PATCH 190/689] Update data on Approve screen after updating custom spend limit (#7918) After updating the custom spend limit on the approve screen, the data for the transaction was not being updated. Instead it showed the original transaction data. The transaction data was being updated correctly in the final transaction though. The approve screen has been updated to ensure changes to the custom spend limit are reflected correctly in the data shown. --- .../confirm-approve/confirm-approve.component.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ui/app/pages/confirm-approve/confirm-approve.component.js b/ui/app/pages/confirm-approve/confirm-approve.component.js index 5dde59b8c..e9e343090 100644 --- a/ui/app/pages/confirm-approve/confirm-approve.component.js +++ b/ui/app/pages/confirm-approve/confirm-approve.component.js @@ -75,6 +75,10 @@ export default class ConfirmApprove extends Component { ? Number(calcTokenAmount(tokenTrackerBalance, decimals)).toPrecision(9) : '' + const customData = customPermissionAmount + ? getCustomTxParamsData(data, { customPermissionAmount, tokenAmount, decimals }) + : null + return ( showCustomizeGasModal(txData)} showEditApprovalPermissionModal={showEditApprovalPermissionModal} - data={data} + data={customData || data} toAddress={toAddress} currentCurrency={currentCurrency} ethTransactionTotal={ethTransactionTotal} @@ -102,10 +106,7 @@ export default class ConfirmApprove extends Component { /> )} hideSenderToRecipient - customTxParamsData={customPermissionAmount - ? getCustomTxParamsData(data, { customPermissionAmount, tokenAmount, decimals }) - : null - } + customTxParamsData={customData} {...restProps} /> ) From 507859830689e269fa87a6256bb6102071826976 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 28 Jan 2020 13:31:20 -0330 Subject: [PATCH 191/689] Remove usage of unlisted extend dependency (#7903) --- app/scripts/controllers/network/network.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index a0c19f1bd..de6deb863 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -11,7 +11,6 @@ import createInfuraClient from './createInfuraClient' import createJsonRpcClient from './createJsonRpcClient' import createLocalhostClient from './createLocalhostClient' import { createSwappableProxy, createEventEmitterProxy } from 'swappable-obj-proxy' -import extend from 'extend' const networks = { networkList: {} } @@ -218,7 +217,7 @@ export default class NetworkController extends EventEmitter { let settings = { network: chainId, } - settings = extend(settings, networks.networkList['rpc']) + settings = Object.assign(settings, networks.networkList['rpc']) this.networkConfig.putState(settings) this._setNetworkClient(networkClient) } From ffd24a2854f62e63629aae2594dbbb7012dbbb79 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 28 Jan 2020 13:02:49 -0400 Subject: [PATCH 192/689] Remove JSDoc tools (#7897) Our JSDoc documentation has not been updated in a very long time, and we don't use JSDoc in enough places for the docs to have been especially useful. The tools and scripts used to generate and publish these docs have been removed. References to this documentation have also been removed from the README. Hopefully once the TypeScript migration has made substantial progress, we can generate more useful documentation using something like TypeDoc. --- .circleci/config.yml | 25 ------ .gitignore | 1 - README.md | 4 - development/.jsdoc.json | 25 ------ package.json | 5 -- yarn.lock | 191 +--------------------------------------- 6 files changed, 3 insertions(+), 248 deletions(-) delete mode 100644 development/.jsdoc.json diff --git a/.circleci/config.yml b/.circleci/config.yml index 7eba4e7b8..9c50c1c49 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,9 +16,6 @@ workflows: - prep-build-test: requires: - prep-deps - # - prep-docs: - # requires: - # - prep-deps - prep-scss: requires: - prep-deps @@ -81,7 +78,6 @@ workflows: requires: - prep-deps - prep-build - # - prep-docs - all-tests-pass # - job-publish-storybook: # filters: @@ -162,21 +158,6 @@ jobs: paths: - dist-test - prep-docs: - docker: - - image: circleci/node:10.17-browsers - steps: - - checkout - - attach_workspace: - at: . - - run: - name: build:dist - command: yarn doc - - persist_to_workspace: - root: . - paths: - - docs/jsdocs - prep-scss: docker: - image: circleci/node:10.17-browsers @@ -349,12 +330,6 @@ jobs: - run: name: Create GitHub Pull Request to sync master with develop command: .circleci/scripts/release-create-master-pr - # - run: - # name: github gh-pages docs publish - # command: > - # git config --global user.name "metamaskbot" && - # git config --global user.email "admin@metamask.io" && - # yarn publish-docs # job-publish-storybook: # docker: # - image: circleci/node:10.17-browsers diff --git a/.gitignore b/.gitignore index 13d80684e..b99c21fd3 100644 --- a/.gitignore +++ b/.gitignore @@ -30,7 +30,6 @@ coverage/ dist builds/ builds.zip -docs/jsdocs development/bundle.js development/states.js diff --git a/README.md b/README.md index 662e31438..d2a029480 100644 --- a/README.md +++ b/README.md @@ -33,10 +33,6 @@ Uncompressed builds can be found in `/dist`, compressed builds can be found in ` ## Contributing -You can read [our internal docs here](https://metamask.github.io/metamask-extension/). - -You can re-generate the docs locally by running `yarn doc`, and contributors can update the hosted docs by running `yarn publish-docs`. - ### Running Tests Run tests with `yarn test`. diff --git a/development/.jsdoc.json b/development/.jsdoc.json deleted file mode 100644 index fd90bf89f..000000000 --- a/development/.jsdoc.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "tags": { - "allowUnknownTags": false - }, - "source": { - "include": "app/scripts/", - "includePattern": ".js$", - "excludePattern": "(node_modules/|docs)" - }, - "plugins": [ - "plugins/markdown" - ], - "opts": { - "template": "node_modules/radgrad-jsdoc-template/", - "encoding": "utf8", - "destination": "docs/jsdocs", - "recurse": true, - "verbose": true - }, - "templates": { - "cleverLinks": false, - "monospaceLinks": false - } -} - diff --git a/package.json b/package.json index c056d1053..2e21ece8d 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,6 @@ "scripts": { "start": "gulp dev:extension", "dist": "gulp dist", - "doc": "jsdoc -c development/.jsdoc.json", - "publish-docs": "gh-pages -d docs/jsdocs", "start:test": "gulp dev:test", "benchmark:chrome": "SELENIUM_BROWSER=chrome node test/e2e/benchmark.js", "benchmark:firefox": "SELENIUM_BROWSER=firefox node test/e2e/benchmark.js", @@ -233,7 +231,6 @@ "ganache-core": "2.8.0", "geckodriver": "^1.19.1", "get-port": "^5.1.0", - "gh-pages": "^1.2.0", "gulp": "^4.0.0", "gulp-autoprefixer": "^5.0.0", "gulp-babel": "^7.0.0", @@ -255,7 +252,6 @@ "gulp-zip": "^4.0.0", "http-server": "^0.11.1", "isomorphic-fetch": "^2.2.1", - "jsdoc": "^3.6.2", "jsdom": "^11.2.0", "jsdom-global": "^3.0.2", "karma": "^4.1.0", @@ -277,7 +273,6 @@ "proxyquire": "2.0.1", "qs": "^6.2.0", "qunitjs": "^2.4.1", - "radgrad-jsdoc-template": "^1.1.3", "react-devtools": "^4.4.0", "react-test-renderer": "^16.12.0", "read-installed": "^4.0.3", diff --git a/yarn.lock b/yarn.lock index a13a1d6c8..04a6d0bef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4457,13 +4457,6 @@ async@2.3.0: dependencies: lodash "^4.14.0" -async@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" - integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== - dependencies: - lodash "^4.17.10" - async@2.6.2, async@^2.6.1, async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" @@ -5823,11 +5816,6 @@ bluebird@^3.1.1, bluebird@^3.3.0, bluebird@^3.3.5, bluebird@^3.4.6, bluebird@^3. resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" integrity sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA== -bluebird@^3.5.4: - version "3.5.5" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" - integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== - bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -6711,13 +6699,6 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -catharsis@^0.8.10: - version "0.8.10" - resolved "https://registry.yarnpkg.com/catharsis/-/catharsis-0.8.10.tgz#364198c1fbf084ae17028ee33ec7db53ca942ee6" - integrity sha512-l2OUaz/3PU3MZylspVFJvwHCVfWyvcduPq4lv3AzZ2pJzZCo7kNKFNyatwujD7XgvGkNAE/Jhhbh2uARNwNkfw== - dependencies: - lodash "^4.17.11" - caw@^2.0.0, caw@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/caw/-/caw-2.0.1.tgz#6c3ca071fc194720883c2dc5da9b074bfc7e9e95" @@ -7400,11 +7381,6 @@ commander@2, commander@2.11.0, commander@^2.6.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== - commander@2.17.x: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" @@ -10168,11 +10144,6 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1 resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - escodegen@1.x.x, escodegen@^1.8.1, escodegen@~1.9.0: version "1.9.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.1.tgz#dbae17ef96c8e4bedb1356f4504fa4cc2f7cb7e2" @@ -12156,33 +12127,11 @@ filename-regex@^2.0.0: resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= -filename-reserved-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz#e61cf805f0de1c984567d0386dc5df50ee5af7e4" - integrity sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q= - filename-reserved-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" integrity sha1-q/c9+rc10EVECr/qLZHzieu/oik= -filenamify-url@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/filenamify-url/-/filenamify-url-1.0.0.tgz#b32bd81319ef5863b73078bed50f46a4f7975f50" - integrity sha1-syvYExnvWGO3MHi+1Q9GpPeXX1A= - dependencies: - filenamify "^1.0.0" - humanize-url "^1.0.0" - -filenamify@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-1.2.1.tgz#a9f2ffd11c503bed300015029272378f1f1365a5" - integrity sha1-qfL/0RxQO+0wABUCknI3jx8TZaU= - dependencies: - filename-reserved-regex "^1.0.0" - strip-outer "^1.0.0" - trim-repeated "^1.0.0" - filenamify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-2.1.0.tgz#88faf495fb1b47abfd612300002a16228c677ee9" @@ -12698,15 +12647,6 @@ fs-extra@^4.0.1, fs-extra@^4.0.2: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" - integrity sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" @@ -13132,19 +13072,6 @@ gettext-parser@1.1.0: dependencies: encoding "^0.1.11" -gh-pages@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/gh-pages/-/gh-pages-1.2.0.tgz#1acb92801078f7c038a167f447221d1496ccfbee" - integrity sha512-cGLYAvxtlQ1iTwAS4g7FreZPXoE/g62Fsxln2mmR19mgs4zZI+XJ+wVVUhBFCF/0+Nmvbq+abyTWue1m1BSnmg== - dependencies: - async "2.6.1" - commander "2.15.1" - filenamify-url "^1.0.0" - fs-extra "^5.0.0" - globby "^6.1.0" - graceful-fs "4.1.11" - rimraf "^2.6.2" - gifsicle@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/gifsicle/-/gifsicle-4.0.1.tgz#30e1e61e3ee4884ef702641b2e98a15c2127b2e2" @@ -13586,7 +13513,7 @@ got@^8.3.1, got@^8.3.2: url-parse-lax "^3.0.0" url-to-options "^1.0.1" -graceful-fs@4.1.11, graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: +graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= @@ -14537,14 +14464,6 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -humanize-url@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/humanize-url/-/humanize-url-1.0.1.tgz#f4ab99e0d288174ca4e1e50407c55fbae464efff" - integrity sha1-9KuZ4NKIF0yk4eUEB8VfuuRk7/8= - dependencies: - normalize-url "^1.0.0" - strip-url-auth "^1.0.0" - humble-localstorage@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/humble-localstorage/-/humble-localstorage-1.4.2.tgz#d05ab0d526c4edbddbf7c6a60df6ff5805283469" @@ -16966,13 +16885,6 @@ js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.2.5, js-yaml@^3.2.7, js-yaml@^3.5.1 argparse "^1.0.7" esprima "^4.0.0" -js2xmlparser@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js2xmlparser/-/js2xmlparser-4.0.0.tgz#ae14cc711b2892083eed6e219fbc993d858bc3a5" - integrity sha512-WuNgdZOXVmBk5kUPMcTcVUpbGRzLfNkv7+7APq7WiDihpXVKrgxo6wwRpRl9OQeEBgKCVk9mR7RbzrnNWC8oBw== - dependencies: - xmlcreate "^2.0.0" - jsan@^3.1.13: version "3.1.13" resolved "https://registry.yarnpkg.com/jsan/-/jsan-3.1.13.tgz#4de8c7bf8d1cfcd020c313d438f930cec4b91d86" @@ -16988,26 +16900,6 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -jsdoc@^3.6.2: - version "3.6.2" - resolved "https://registry.yarnpkg.com/jsdoc/-/jsdoc-3.6.2.tgz#ee289fc6ba9263b7e4eceb99921179fe1c31489a" - integrity sha512-S2vzg99C5+gb7FWlrK4TVdyzVPGGkdvpDkCEJH1JABi2PKzPeLu5/zZffcJUifgWUJqXWl41Hoc+MmuM2GukIg== - dependencies: - "@babel/parser" "^7.4.4" - bluebird "^3.5.4" - catharsis "^0.8.10" - escape-string-regexp "^2.0.0" - js2xmlparser "^4.0.0" - klaw "^3.0.0" - markdown-it "^8.4.2" - markdown-it-anchor "^5.0.2" - marked "^0.6.2" - mkdirp "^0.5.1" - requizzle "^0.2.2" - strip-json-comments "^3.0.1" - taffydb "2.6.2" - underscore "~1.9.1" - jsdom-global@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/jsdom-global/-/jsdom-global-3.0.2.tgz#6bd299c13b0c4626b2da2c0393cd4385d606acb9" @@ -17639,13 +17531,6 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" -klaw@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/klaw/-/klaw-3.0.0.tgz#b11bec9cf2492f06756d6e809ab73a2910259146" - integrity sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g== - dependencies: - graceful-fs "^4.1.9" - kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -18516,13 +18401,6 @@ linked-list@0.1.0: resolved "https://registry.yarnpkg.com/linked-list/-/linked-list-0.1.0.tgz#798b0ff97d1b92a4fd08480f55aea4e9d49d37bf" integrity sha1-eYsP+X0bkqT9CEgPVa6k6dSdN78= -linkify-it@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.1.0.tgz#c4caf38a6cd7ac2212ef3c7d2bde30a91561f9db" - integrity sha512-4REs8/062kV2DSHxNfq5183zrqXMl7WP0WzABH9IeJI+NLm429FgE1PDecltYfnOoFDFlZGh2T8PfZn0r+GTRg== - dependencies: - uc.micro "^1.0.1" - livereload-js@^2.3.0: version "2.4.0" resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-2.4.0.tgz#447c31cf1ea9ab52fc20db615c5ddf678f78009c" @@ -19262,22 +19140,6 @@ markdown-escapes@^1.0.0: resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.3.tgz#6155e10416efaafab665d466ce598216375195f5" integrity sha512-XUi5HJhhV5R74k8/0H2oCbCiYf/u4cO/rX8tnGkRvrqhsr5BRNU6Mg0yt/8UIx1iIS8220BNJsDb7XnILhLepw== -markdown-it-anchor@^5.0.2: - version "5.2.4" - resolved "https://registry.yarnpkg.com/markdown-it-anchor/-/markdown-it-anchor-5.2.4.tgz#d39306fe4c199705b4479d3036842cf34dcba24f" - integrity sha512-n8zCGjxA3T+Mx1pG8HEgbJbkB8JFUuRkeTZQuIM8iPY6oQ8sWOPRZJDFC9a/pNg2QkHEjjGkhBEl/RSyzaDZ3A== - -markdown-it@^8.4.2: - version "8.4.2" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54" - integrity sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ== - dependencies: - argparse "^1.0.7" - entities "~1.1.1" - linkify-it "^2.0.0" - mdurl "^1.0.1" - uc.micro "^1.0.5" - markdown-table@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" @@ -19291,11 +19153,6 @@ markdown-to-jsx@^6.9.1, markdown-to-jsx@^6.9.3: prop-types "^15.6.2" unquote "^1.1.0" -marked@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/marked/-/marked-0.6.2.tgz#c574be8b545a8b48641456ca1dbe0e37b6dccc1a" - integrity sha512-LqxwVH3P/rqKX4EKGz7+c2G9r98WeM/SW34ybhgNGhUQNKtf1GmmSkJ6cDGJ/t6tiyae49qRkpyTw2B9HOrgUA== - matchdep@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e" @@ -19380,11 +19237,6 @@ mdn-data@~1.1.0: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== -mdurl@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= - media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -20801,7 +20653,7 @@ normalize-selector@^0.2.0: resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= -normalize-url@1.9.1, normalize-url@^1.0.0, normalize-url@^1.9.1: +normalize-url@1.9.1, normalize-url@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= @@ -23553,11 +23405,6 @@ rabin-wasm@~0.0.4: node-fetch "^2.6.0" readable-stream "^2.0.4" -radgrad-jsdoc-template@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/radgrad-jsdoc-template/-/radgrad-jsdoc-template-1.1.3.tgz#89672ec71b8fbc88281e48b75f89b3b4b965b541" - integrity sha512-yk1XB6NlrP6JIr3xHzCrNwCmkONNgqM+sZxFAdmTU/CsaT7N/lns2/Wfa048li3wrao5b6KwYrdu6KgiGh9nIQ== - raf@^3.1.0, raf@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575" @@ -25058,13 +24905,6 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= -requizzle@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/requizzle/-/requizzle-0.2.2.tgz#df991c0cffbbbdde721504c1455f68f53f7c7bd1" - integrity sha512-oJ6y7JcUJkblRGhMByGNcszeLgU0qDxNKFCiUZR1XyzHyVsev+Mxb1tyygxLd1ORsKee1SA5BInFdUwY64GE/A== - dependencies: - lodash "^4.17.11" - reselect@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147" @@ -27297,11 +27137,6 @@ strip-json-comments@^2.0.0, strip-json-comments@^2.0.1, strip-json-comments@~2.0 resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= -strip-json-comments@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" - integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== - strip-outer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" @@ -27309,11 +27144,6 @@ strip-outer@^1.0.0: dependencies: escape-string-regexp "^1.0.2" -strip-url-auth@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-url-auth/-/strip-url-auth-1.0.1.tgz#22b0fa3a41385b33be3f331551bbb837fa0cd7ae" - integrity sha1-IrD6OkE4WzO+PzMVUbu4N/oM164= - style-loader@^0.21.0: version "0.21.0" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.21.0.tgz#68c52e5eb2afc9ca92b6274be277ee59aea3a852" @@ -27680,11 +27510,6 @@ table@^5.2.3: slice-ansi "^2.1.0" string-width "^3.0.0" -taffydb@2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.6.2.tgz#7cbcb64b5a141b6a2efc2c5d2c67b4e150b2a268" - integrity sha1-fLy2S1oUG2ou/CxdLGe04VCyomg= - tap-parser@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/tap-parser/-/tap-parser-7.0.0.tgz#54db35302fda2c2ccc21954ad3be22b2cba42721" @@ -28620,11 +28445,6 @@ ua-parser-js@^0.7.9: resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" integrity sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g== -uc.micro@^1.0.1, uc.micro@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" - integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== - uglify-js@3.4.x: version "3.4.10" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f" @@ -28689,7 +28509,7 @@ undeclared-identifiers@^1.1.2: simple-concat "^1.0.0" xtend "^4.0.1" -underscore@1.9.1, underscore@>=1.8.3, underscore@~1.9.1: +underscore@1.9.1, underscore@>=1.8.3: version "1.9.1" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== @@ -30301,11 +30121,6 @@ xmlbuilder@~11.0.0: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== -xmlcreate@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-2.0.1.tgz#2ec38bd7b708d213fd1a90e2431c4af9c09f6a52" - integrity sha512-MjGsXhKG8YjTKrDCXseFo3ClbMGvUD4en29H2Cev1dv4P/chlpw6KdYmlCWDkhosBVKRDjM836+3e3pm1cBNJA== - xmldom@^0.1.19: version "0.1.27" resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" From 99ceca3d25d2286d9a32de0bd757c72141b08e82 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 28 Jan 2020 20:08:55 -0400 Subject: [PATCH 193/689] Update jazzicon component (#7898) * Use ref instead of findDOMNode in jazzicon component The jazzicon component was using `findDOMNode` to get the DOM node for the main div returned by the component, which is generally not recommended. Instead a ref is now used. * Update Jazzicon to v2 This version drops the dependency upon `raphael`, and no longer uses the function `createSVGMatrix` which was causing unit tests to fail (because it's not supported by jsdom). --- package.json | 3 +- .../ui/jazzicon/jazzicon.component.js | 23 +++++-------- yarn.lock | 34 +++++-------------- 3 files changed, 18 insertions(+), 42 deletions(-) diff --git a/package.json b/package.json index 2e21ece8d..5ecb412cb 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,6 @@ "debounce": "1.1.0", "debounce-stream": "^2.0.0", "deep-freeze-strict": "1.1.1", - "detect-node": "^2.0.3", "dnode": "^1.2.2", "end-of-stream": "^1.1.0", "eth-block-tracker": "^4.4.2", @@ -120,7 +119,7 @@ "fuse.js": "^3.2.0", "gaba": "^1.9.3", "human-standard-token-abi": "^2.0.0", - "jazzicon": "^1.2.0", + "jazzicon": "^2.0.0", "json-rpc-engine": "^5.1.6", "json-rpc-middleware-stream": "^2.1.1", "jsonschema": "^1.2.4", diff --git a/ui/app/components/ui/jazzicon/jazzicon.component.js b/ui/app/components/ui/jazzicon/jazzicon.component.js index 6a1dcbc8a..24fb9f61e 100644 --- a/ui/app/components/ui/jazzicon/jazzicon.component.js +++ b/ui/app/components/ui/jazzicon/jazzicon.component.js @@ -1,7 +1,5 @@ -import React, { PureComponent } from 'react' +import React, { createRef, PureComponent } from 'react' import PropTypes from 'prop-types' -import isNode from 'detect-node' -import { findDOMNode } from 'react-dom' import jazzicon from 'jazzicon' import iconFactoryGenerator from '../../../../lib/icon-factory' @@ -23,38 +21,34 @@ export default class Jazzicon extends PureComponent { diameter: 46, } + container = createRef() + componentDidMount () { - if (!isNode) { - this.appendJazzicon() - } + this.appendJazzicon() } componentDidUpdate (prevProps) { const { address: prevAddress } = prevProps const { address } = this.props - if (!isNode && address !== prevAddress) { + if (address !== prevAddress) { this.removeExistingChildren() this.appendJazzicon() } } removeExistingChildren () { - // eslint-disable-next-line react/no-find-dom-node - const container = findDOMNode(this) - const { children } = container + const { children } = this.container.current for (let i = 0; i < children.length; i++) { - container.removeChild(children[i]) + this.container.current.removeChild(children[i]) } } appendJazzicon () { - // eslint-disable-next-line react/no-find-dom-node - const container = findDOMNode(this) const { address, diameter } = this.props const image = iconFactory.iconForAddress(address, diameter) - container.appendChild(image) + this.container.current.appendChild(image) } render () { @@ -63,6 +57,7 @@ export default class Jazzicon extends PureComponent { return (
    ) diff --git a/yarn.lock b/yarn.lock index 04a6d0bef..ca47f7d4e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7303,7 +7303,7 @@ color-support@^1.1.3: resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== -color@^0.11.1: +color@^0.11.3: version "0.11.4" resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" integrity sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q= @@ -9019,11 +9019,6 @@ detect-newline@2.X, detect-newline@^2.1.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I= -detect-node@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127" - integrity sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc= - detect-node@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" @@ -11429,11 +11424,6 @@ ethjs@^0.4.0: js-sha3 "0.5.5" number-to-bn "1.7.0" -eve-raphael@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/eve-raphael/-/eve-raphael-0.5.0.tgz#17c754b792beef3fa6684d79cf5a47c63c4cda30" - integrity sha1-F8dUt5K+7z+maE15z1pHxjxM2jA= - event-emitter@^0.3.5, event-emitter@~0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" @@ -16426,14 +16416,13 @@ java-properties@^0.2.9: resolved "https://registry.yarnpkg.com/java-properties/-/java-properties-0.2.10.tgz#2551560c25fa1ad94d998218178f233ad9b18f60" integrity sha512-CpKJh9VRNhS+XqZtg1UMejETGEiqwCGDC/uwPEEQwc2nfdbSm73SIE29TplG2gLYuBOOTNDqxzG6A9NtEPLt0w== -jazzicon@^1.2.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/jazzicon/-/jazzicon-1.5.0.tgz#d7f36b516023db39ee6eac117f4054e937b65e99" - integrity sha1-1/NrUWAj2znubqwRf0BU6Te2Xpk= +jazzicon@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/jazzicon/-/jazzicon-2.0.0.tgz#a45f10f330ad529d054264759a9e4817292bb440" + integrity sha1-pF8Q8zCtUp0FQmR1mp5IFykrtEA= dependencies: - color "^0.11.1" - mersenne-twister "^1.0.1" - raphael "^2.2.0" + color "^0.11.3" + mersenne-twister "^1.1.0" jed@1.1.1: version "1.1.1" @@ -19438,7 +19427,7 @@ merkle-patricia-tree@^3.0.0: rlp "^2.0.0" semaphore ">=1.0.1" -mersenne-twister@^1.0.1: +mersenne-twister@^1.0.1, mersenne-twister@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mersenne-twister/-/mersenne-twister-1.1.0.tgz#f916618ee43d7179efcf641bec4531eb9670978a" integrity sha1-+RZhjuQ9cXnvz2Qb7EUx65Zwl4o= @@ -23493,13 +23482,6 @@ range-parser@^1.2.0, range-parser@^1.2.1, range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raphael@^2.2.0: - version "2.2.7" - resolved "https://registry.yarnpkg.com/raphael/-/raphael-2.2.7.tgz#231b19141f8d086986d8faceb66f8b562ee2c810" - integrity sha1-IxsZFB+NCGmG2PrOtm+LVi7iyBA= - dependencies: - eve-raphael "0.5.0" - raw-body@2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" From cc78378b8e5b630cdaf3c5f4b3cacc793f95cc35 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 28 Jan 2020 22:49:32 -0400 Subject: [PATCH 194/689] Allow editing max spend limit (#7919) In the case where the initial spend limit for the `approve` function was set to the maximum amount, editing this value would result in the new limit being silently ignored. The transaction would be submitted with the original max spend limit. This occurred because function to generate the new custom data would look for the expected spend limit in the existing data, then bail if it was not found (and in these cases, it was never found). The reason the value was not found is that it was erroneously being converted to a `Number`. A JavaScript `Number` is not precise enough to represent larger spend limits, so it would give the wrong hex value (after rounding had taken place in the conversion to a floating-point number). The data string is now updated without relying upon the original token value; the new value is inserted after the `spender` argument instead, as the remainder of the `data` string is guaranteed to be the original limit. Additionally, the conversion to a `Number` is now omitted so that the custom spend limit is encoded correctly. Fixes #7915 --- .../edit-approval-permission.component.js | 9 ++-- .../confirm-approve-content.component.js | 2 +- .../confirm-approve.component.js | 12 ++--- .../confirm-approve.container.js | 2 +- .../confirm-approve/confirm-approve.util.js | 45 ++++++++++--------- 5 files changed, 38 insertions(+), 32 deletions(-) diff --git a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js index 661bbdefd..f7dad3a50 100644 --- a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js +++ b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js @@ -4,6 +4,7 @@ import Modal from '../../modal' import Identicon from '../../../ui/identicon' import TextField from '../../../ui/text-field' import classnames from 'classnames' +import BigNumber from 'bignumber.js' export default class EditApprovalPermission extends PureComponent { static propTypes = { @@ -61,7 +62,7 @@ export default class EditApprovalPermission extends PureComponent {
    { t('balance') }
    - {`${tokenBalance} ${tokenSymbol}`} + {`${Number(tokenBalance).toPrecision(9)} ${tokenSymbol}`}
    @@ -93,7 +94,7 @@ export default class EditApprovalPermission extends PureComponent { })} > { - tokenAmount < tokenBalance + (new BigNumber(tokenAmount)).lessThan(new BigNumber(tokenBalance)) ? t('proposedApprovalLimit') : t('unlimited') } @@ -102,7 +103,7 @@ export default class EditApprovalPermission extends PureComponent { { t('spendLimitRequestedBy', [origin]) }
    - {`${tokenAmount} ${tokenSymbol}`} + {`${Number(tokenAmount)} ${tokenSymbol}`}
    @@ -136,7 +137,7 @@ export default class EditApprovalPermission extends PureComponent { { this.setState({ customSpendLimit: event.target.value }) if (selectedOptionIsUnlimited) { diff --git a/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js b/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js index 0bccef7f9..673bfe415 100644 --- a/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js +++ b/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js @@ -103,7 +103,7 @@ export default class ConfirmApproveContent extends Component {
    { t('accessAndSpendNotice', [origin]) }
    { t('amountWithColon') }
    -
    { `${customTokenAmount || tokenAmount} ${tokenSymbol}` }
    +
    { `${Number(customTokenAmount || tokenAmount)} ${tokenSymbol}` }
    { t('toWithColon') }
    diff --git a/ui/app/pages/confirm-approve/confirm-approve.component.js b/ui/app/pages/confirm-approve/confirm-approve.component.js index e9e343090..bb7f6ceb2 100644 --- a/ui/app/pages/confirm-approve/confirm-approve.component.js +++ b/ui/app/pages/confirm-approve/confirm-approve.component.js @@ -15,7 +15,7 @@ export default class ConfirmApprove extends Component { static propTypes = { tokenAddress: PropTypes.string, toAddress: PropTypes.string, - tokenAmount: PropTypes.number, + tokenAmount: PropTypes.string, tokenSymbol: PropTypes.string, fiatTransactionTotal: PropTypes.string, ethTransactionTotal: PropTypes.string, @@ -33,7 +33,7 @@ export default class ConfirmApprove extends Component { } static defaultProps = { - tokenAmount: 0, + tokenAmount: '0', } state = { @@ -69,14 +69,14 @@ export default class ConfirmApprove extends Component { } = this.props const { customPermissionAmount } = this.state - const tokensText = `${tokenAmount} ${tokenSymbol}` + const tokensText = `${Number(tokenAmount)} ${tokenSymbol}` const tokenBalance = tokenTrackerBalance - ? Number(calcTokenAmount(tokenTrackerBalance, decimals)).toPrecision(9) + ? calcTokenAmount(tokenTrackerBalance, decimals).toString(10) : '' const customData = customPermissionAmount - ? getCustomTxParamsData(data, { customPermissionAmount, tokenAmount, decimals }) + ? getCustomTxParamsData(data, { customPermissionAmount, decimals }) : null return ( @@ -92,7 +92,7 @@ export default class ConfirmApprove extends Component { this.setState({ customPermissionAmount: newAmount }) }} customTokenAmount={String(customPermissionAmount)} - tokenAmount={String(tokenAmount)} + tokenAmount={tokenAmount} origin={origin} tokenSymbol={tokenSymbol} tokenBalance={tokenBalance} diff --git a/ui/app/pages/confirm-approve/confirm-approve.container.js b/ui/app/pages/confirm-approve/confirm-approve.container.js index cdd04f6ad..29fec2ff3 100644 --- a/ui/app/pages/confirm-approve/confirm-approve.container.js +++ b/ui/app/pages/confirm-approve/confirm-approve.container.js @@ -43,7 +43,7 @@ const mapStateToProps = (state, ownProps) => { const tokenData = getTokenData(data) const tokenValue = tokenData && getTokenValue(tokenData.params) const toAddress = tokenData && getTokenToAddress(tokenData.params) - const tokenAmount = tokenData && calcTokenAmount(tokenValue, decimals).toNumber() + const tokenAmount = tokenData && calcTokenAmount(tokenValue, decimals).toString(10) const contractExchangeRate = contractExchangeRateSelector(state) const { origin } = transaction diff --git a/ui/app/pages/confirm-approve/confirm-approve.util.js b/ui/app/pages/confirm-approve/confirm-approve.util.js index be77c65f9..0318c6bed 100644 --- a/ui/app/pages/confirm-approve/confirm-approve.util.js +++ b/ui/app/pages/confirm-approve/confirm-approve.util.js @@ -1,28 +1,33 @@ import { decimalToHex } from '../../helpers/utils/conversions.util' import { calcTokenValue } from '../../helpers/utils/token-util.js' +import { getTokenData } from '../../helpers/utils/transactions.util' -export function getCustomTxParamsData (data, { customPermissionAmount, tokenAmount, decimals }) { - if (customPermissionAmount) { - const tokenValue = decimalToHex(calcTokenValue(tokenAmount, decimals)) +export function getCustomTxParamsData (data, { customPermissionAmount, decimals }) { + const tokenData = getTokenData(data) - const re = new RegExp('(^.+)' + tokenValue + '$') - const matches = re.exec(data) - - if (!matches || !matches[1]) { - return data - } - let dataWithoutCurrentAmount = matches[1] - const customPermissionValue = decimalToHex(calcTokenValue(Number(customPermissionAmount), decimals)) + if (!tokenData) { + throw new Error('Invalid data') + } else if (tokenData.name !== 'approve') { + throw new Error(`Invalid data; should be 'approve' method, but instead is '${tokenData.name}'`) + } + let spender = tokenData.params[0].value + if (spender.startsWith('0x')) { + spender = spender.substring(2) + } + const [signature, tokenValue] = data.split(spender) - const differenceInLengths = customPermissionValue.length - tokenValue.length - const zeroModifier = dataWithoutCurrentAmount.length - differenceInLengths - if (differenceInLengths > 0) { - dataWithoutCurrentAmount = dataWithoutCurrentAmount.slice(0, zeroModifier) - } else if (differenceInLengths < 0) { - dataWithoutCurrentAmount = dataWithoutCurrentAmount.padEnd(zeroModifier, 0) - } + if (!signature || !tokenValue) { + throw new Error('Invalid data') + } else if (tokenValue.length !== 64) { + throw new Error('Invalid token value; should be exactly 64 hex digits long (u256)') + } - const customTxParamsData = dataWithoutCurrentAmount + customPermissionValue - return customTxParamsData + let customPermissionValue = decimalToHex(calcTokenValue(customPermissionAmount, decimals)) + if (customPermissionValue.length > 64) { + throw new Error('Custom value is larger than u256') } + + customPermissionValue = customPermissionValue.padStart(tokenValue.length, '0') + const customTxParamsData = `${signature}${spender}${customPermissionValue}` + return customTxParamsData } From b8cdc928f6141ea033b69905d74eab400c72df75 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 29 Jan 2020 12:12:49 -0400 Subject: [PATCH 195/689] Report errors in tests to `test-metamask` Sentry project (#7924) Previously, all errors encountered during testing or production were sent to the primary `metamask` Sentry project, whereas development errors were sent to `test-metamask` instead. This change ensures that errors encountered during tests are sent to `test-metamask` as well. --- app/scripts/lib/setupSentry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index 94fd870d8..f52258519 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -16,7 +16,7 @@ function setupSentry (opts) { // detect brave const isBrave = Boolean(window.chrome.ipcRenderer) - if (METAMASK_DEBUG) { + if (METAMASK_DEBUG || process.env.IN_TEST) { console.log('Setting up Sentry Remote Error Reporting: SENTRY_DSN_DEV') sentryTarget = SENTRY_DSN_DEV } else { From 4bb01a36eba73546bd63beb5cda0d536db5e15a9 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 13:36:10 -0330 Subject: [PATCH 196/689] Bump Node version to 10.18 (#7925) --- .circleci/config.yml | 44 ++++++++++++++++++++++---------------------- .nvmrc | 2 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9c50c1c49..1d17a5808 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -92,7 +92,7 @@ workflows: jobs: create_release_pull_request: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - run: @@ -104,7 +104,7 @@ jobs: prep-deps: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - run: @@ -123,7 +123,7 @@ jobs: prep-build: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: @@ -142,7 +142,7 @@ jobs: prep-build-test: docker: - - image: circleci/node:10.16-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: @@ -160,7 +160,7 @@ jobs: prep-scss: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: @@ -179,7 +179,7 @@ jobs: test-lint: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: @@ -193,7 +193,7 @@ jobs: test-lint-shellcheck: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - run: sudo apt-get install shellcheck @@ -203,7 +203,7 @@ jobs: test-lint-lockfile: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: @@ -214,7 +214,7 @@ jobs: test-deps: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: @@ -225,7 +225,7 @@ jobs: test-e2e-chrome: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: @@ -243,7 +243,7 @@ jobs: test-e2e-firefox: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - run: @@ -264,7 +264,7 @@ jobs: benchmark: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: @@ -285,7 +285,7 @@ jobs: job-publish-prerelease: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: @@ -315,7 +315,7 @@ jobs: job-publish-release: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: @@ -332,7 +332,7 @@ jobs: command: .circleci/scripts/release-create-master-pr # job-publish-storybook: # docker: - # - image: circleci/node:10.17-browsers + # - image: circleci/node:10.18-browsers # steps: # - checkout # - attach_workspace: @@ -343,7 +343,7 @@ jobs: test-unit: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: @@ -358,7 +358,7 @@ jobs: - coverage test-unit-global: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: @@ -368,7 +368,7 @@ jobs: command: yarn test:unit:global test-mozilla-lint: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: @@ -379,7 +379,7 @@ jobs: test-integration-flat-firefox: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: @@ -395,7 +395,7 @@ jobs: environment: browsers: '["Chrome"]' docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: @@ -406,7 +406,7 @@ jobs: all-tests-pass: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - run: name: All Tests Passed @@ -414,7 +414,7 @@ jobs: coveralls-upload: docker: - - image: circleci/node:10.17-browsers + - image: circleci/node:10.18-browsers steps: - checkout - attach_workspace: diff --git a/.nvmrc b/.nvmrc index c095bf0f4..1de6ab5e2 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v10.17.0 +v10.18.1 From 5904c91ebe4faf5feb9ad095e72848830b58e55b Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 13:36:31 -0330 Subject: [PATCH 197/689] Remove top-level symlinks (#7927) --- fonts | 1 - images | 1 - 2 files changed, 2 deletions(-) delete mode 120000 fonts delete mode 120000 images diff --git a/fonts b/fonts deleted file mode 120000 index 043d139a9..000000000 --- a/fonts +++ /dev/null @@ -1 +0,0 @@ -app/fonts \ No newline at end of file diff --git a/images b/images deleted file mode 120000 index 2a4dbe892..000000000 --- a/images +++ /dev/null @@ -1 +0,0 @@ -app/images \ No newline at end of file From 398a45bfdd3afc61d9227b832169adbad4a2ba14 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 29 Jan 2020 13:14:33 -0400 Subject: [PATCH 198/689] Replace `clone` dependency with `cloneDeep` from lodash (#7926) This was done to reduce the number of direct dependencies we have. It should be functionally equivalent. The bundle size should not change, as we use `clone` as a transitive dependency in a number of places. --- app/scripts/controllers/permissions/permissionsLog.js | 4 ++-- .../transactions/lib/tx-state-history-helper.js | 6 +++--- app/scripts/lib/getObjStructure.js | 4 ++-- app/scripts/migrations/002.js | 4 ++-- app/scripts/migrations/003.js | 4 ++-- app/scripts/migrations/004.js | 4 ++-- app/scripts/migrations/005.js | 4 ++-- app/scripts/migrations/006.js | 4 ++-- app/scripts/migrations/007.js | 4 ++-- app/scripts/migrations/008.js | 4 ++-- app/scripts/migrations/009.js | 6 ++---- app/scripts/migrations/010.js | 6 ++---- app/scripts/migrations/011.js | 4 ++-- app/scripts/migrations/012.js | 4 ++-- app/scripts/migrations/013.js | 4 ++-- app/scripts/migrations/014.js | 4 ++-- app/scripts/migrations/015.js | 4 ++-- app/scripts/migrations/016.js | 4 ++-- app/scripts/migrations/017.js | 4 ++-- app/scripts/migrations/018.js | 4 ++-- app/scripts/migrations/019.js | 4 ++-- app/scripts/migrations/020.js | 4 ++-- app/scripts/migrations/021.js | 4 ++-- app/scripts/migrations/022.js | 4 ++-- app/scripts/migrations/023.js | 4 ++-- app/scripts/migrations/024.js | 4 ++-- app/scripts/migrations/025.js | 4 ++-- app/scripts/migrations/026.js | 4 ++-- app/scripts/migrations/027.js | 4 ++-- app/scripts/migrations/028.js | 4 ++-- app/scripts/migrations/030.js | 4 ++-- app/scripts/migrations/031.js | 4 ++-- app/scripts/migrations/032.js | 4 ++-- app/scripts/migrations/033.js | 4 ++-- app/scripts/migrations/034.js | 4 ++-- app/scripts/migrations/035.js | 4 ++-- app/scripts/migrations/036.js | 4 ++-- app/scripts/migrations/037.js | 4 ++-- app/scripts/migrations/038.js | 4 ++-- app/scripts/migrations/039.js | 4 ++-- app/scripts/migrations/040.js | 4 ++-- app/scripts/migrations/041.js | 4 ++-- app/scripts/migrations/fail-tx.js | 4 ++-- app/scripts/migrations/template.js | 4 ++-- development/version-bump.js | 4 ++-- package.json | 1 - test/unit/app/controllers/metamask-controller-test.js | 4 ++-- test/unit/app/seed-phrase-verifier-test.js | 4 ++-- test/unit/migrations/migrator-test.js | 8 ++++---- test/unit/ui/app/actions.spec.js | 4 ++-- ui/app/ducks/index.js | 4 ++-- 51 files changed, 103 insertions(+), 108 deletions(-) diff --git a/app/scripts/controllers/permissions/permissionsLog.js b/app/scripts/controllers/permissions/permissionsLog.js index caa369a2e..7a9149a1c 100644 --- a/app/scripts/controllers/permissions/permissionsLog.js +++ b/app/scripts/controllers/permissions/permissionsLog.js @@ -1,5 +1,5 @@ -import clone from 'clone' +import { cloneDeep } from 'lodash' import { isValidAddress } from 'ethereumjs-util' import { CAVEAT_NAMES, @@ -374,7 +374,7 @@ function cloneObj (obj) { for (let i = 3; i > 1; i--) { try { - return clone(obj, false, i) + return cloneDeep(obj, false, i) } catch (_) {} } return { ...obj } diff --git a/app/scripts/controllers/transactions/lib/tx-state-history-helper.js b/app/scripts/controllers/transactions/lib/tx-state-history-helper.js index cd2e3e432..ef085afd9 100644 --- a/app/scripts/controllers/transactions/lib/tx-state-history-helper.js +++ b/app/scripts/controllers/transactions/lib/tx-state-history-helper.js @@ -1,5 +1,5 @@ import jsonDiffer from 'fast-json-patch' -import clone from 'clone' +import { cloneDeep } from 'lodash' /** @module*/ export default { @@ -57,7 +57,7 @@ function generateHistoryEntry (previousState, newState, note) { @returns {Object} */ function replayHistory (_shortHistory) { - const shortHistory = clone(_shortHistory) + const shortHistory = cloneDeep(_shortHistory) return shortHistory.reduce((val, entry) => jsonDiffer.applyPatch(val, entry).newDocument) } @@ -67,7 +67,7 @@ function replayHistory (_shortHistory) { */ function snapshotFromTxMeta (txMeta) { // create txMeta snapshot for history - const snapshot = clone(txMeta) + const snapshot = cloneDeep(txMeta) // dont include previous history in this snapshot delete snapshot.history return snapshot diff --git a/app/scripts/lib/getObjStructure.js b/app/scripts/lib/getObjStructure.js index 8cf620119..785eadc9b 100644 --- a/app/scripts/lib/getObjStructure.js +++ b/app/scripts/lib/getObjStructure.js @@ -1,4 +1,4 @@ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default getObjStructure @@ -24,7 +24,7 @@ export default getObjStructure * */ function getObjStructure (obj) { - const structure = clone(obj) + const structure = cloneDeep(obj) return deepMap(structure, (value) => { return value === null ? 'null' : typeof value }) diff --git a/app/scripts/migrations/002.js b/app/scripts/migrations/002.js index fd5816b76..ce172365a 100644 --- a/app/scripts/migrations/002.js +++ b/app/scripts/migrations/002.js @@ -1,13 +1,13 @@ const version = 2 -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { if (versionedData.data.config.provider.type === 'etherscan') { diff --git a/app/scripts/migrations/003.js b/app/scripts/migrations/003.js index 0bfe382be..15c9b2070 100644 --- a/app/scripts/migrations/003.js +++ b/app/scripts/migrations/003.js @@ -2,13 +2,13 @@ const version = 3 const oldTestRpc = 'https://rawtestrpc.metamask.io/' const newTestRpc = 'https://testrpc.metamask.io/' -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { if (versionedData.data.config.provider.rpcTarget === oldTestRpc) { diff --git a/app/scripts/migrations/004.js b/app/scripts/migrations/004.js index 5c1a5aaff..358cbbea7 100644 --- a/app/scripts/migrations/004.js +++ b/app/scripts/migrations/004.js @@ -1,12 +1,12 @@ const version = 4 -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (versionedData) { - const safeVersionedData = clone(versionedData) + const safeVersionedData = cloneDeep(versionedData) safeVersionedData.meta.version = version try { if (safeVersionedData.data.config.provider.type !== 'rpc') { diff --git a/app/scripts/migrations/005.js b/app/scripts/migrations/005.js index f468afcaa..05587c432 100644 --- a/app/scripts/migrations/005.js +++ b/app/scripts/migrations/005.js @@ -6,14 +6,14 @@ This migration moves state from the flat state trie into KeyringController subst */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/006.js b/app/scripts/migrations/006.js index 66a8e1605..b53015315 100644 --- a/app/scripts/migrations/006.js +++ b/app/scripts/migrations/006.js @@ -6,13 +6,13 @@ This migration moves KeyringController.selectedAddress to PreferencesController. */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/007.js b/app/scripts/migrations/007.js index 42539eae4..bacf005fa 100644 --- a/app/scripts/migrations/007.js +++ b/app/scripts/migrations/007.js @@ -6,13 +6,13 @@ This migration breaks out the TransactionManager substate */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/008.js b/app/scripts/migrations/008.js index c0e1ba56e..a4537ae9b 100644 --- a/app/scripts/migrations/008.js +++ b/app/scripts/migrations/008.js @@ -6,13 +6,13 @@ This migration breaks out the NoticeController substate */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/009.js b/app/scripts/migrations/009.js index 103321522..3fddf7aa9 100644 --- a/app/scripts/migrations/009.js +++ b/app/scripts/migrations/009.js @@ -6,15 +6,13 @@ This migration breaks out the CurrencyController substate */ -import { merge } from 'lodash' - -import clone from 'clone' +import { cloneDeep, merge } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/010.js b/app/scripts/migrations/010.js index b97dd04d9..c8dd42aaf 100644 --- a/app/scripts/migrations/010.js +++ b/app/scripts/migrations/010.js @@ -6,15 +6,13 @@ This migration breaks out the ShapeShiftController substate */ -import { merge } from 'lodash' - -import clone from 'clone' +import { cloneDeep, merge } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/011.js b/app/scripts/migrations/011.js index e845c0d21..d465bf5a6 100644 --- a/app/scripts/migrations/011.js +++ b/app/scripts/migrations/011.js @@ -6,13 +6,13 @@ This migration removes the discaimer state from our app, which was integrated in */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/012.js b/app/scripts/migrations/012.js index 8d532ed65..fc3ddc59c 100644 --- a/app/scripts/migrations/012.js +++ b/app/scripts/migrations/012.js @@ -6,13 +6,13 @@ This migration modifies our notices to delete their body after being read. */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/013.js b/app/scripts/migrations/013.js index a6f9fd414..433face72 100644 --- a/app/scripts/migrations/013.js +++ b/app/scripts/migrations/013.js @@ -6,13 +6,13 @@ This migration modifies the network config from ambiguous 'testnet' to explicit */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/014.js b/app/scripts/migrations/014.js index ebb86b057..e7a7b8c99 100644 --- a/app/scripts/migrations/014.js +++ b/app/scripts/migrations/014.js @@ -6,13 +6,13 @@ This migration removes provider from config and moves it too NetworkController. */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/015.js b/app/scripts/migrations/015.js index 76228b3c7..4ea61b7d1 100644 --- a/app/scripts/migrations/015.js +++ b/app/scripts/migrations/015.js @@ -7,13 +7,13 @@ to a 'failed' stated */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/016.js b/app/scripts/migrations/016.js index 16e27afa2..341658e06 100644 --- a/app/scripts/migrations/016.js +++ b/app/scripts/migrations/016.js @@ -7,13 +7,13 @@ to a 'failed' stated */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/017.js b/app/scripts/migrations/017.js index ffc3d02e5..e39d7855d 100644 --- a/app/scripts/migrations/017.js +++ b/app/scripts/migrations/017.js @@ -6,13 +6,13 @@ This migration sets transactions who were retried and marked as failed to submit */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/018.js b/app/scripts/migrations/018.js index 194c7fdcf..745ad4a88 100644 --- a/app/scripts/migrations/018.js +++ b/app/scripts/migrations/018.js @@ -6,7 +6,7 @@ This migration updates "transaction state history" to diffs style */ -import clone from 'clone' +import { cloneDeep } from 'lodash' import txStateHistoryHelper from '../controllers/transactions/lib/tx-state-history-helper' @@ -15,7 +15,7 @@ export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/019.js b/app/scripts/migrations/019.js index 9c7f35870..e87bdad62 100644 --- a/app/scripts/migrations/019.js +++ b/app/scripts/migrations/019.js @@ -8,13 +8,13 @@ whos nonce is too high */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/020.js b/app/scripts/migrations/020.js index ef0f6f4d5..eaf6dcbc0 100644 --- a/app/scripts/migrations/020.js +++ b/app/scripts/migrations/020.js @@ -8,13 +8,13 @@ so that we can version notices in the future. */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/021.js b/app/scripts/migrations/021.js index 174cde0d8..c57266f08 100644 --- a/app/scripts/migrations/021.js +++ b/app/scripts/migrations/021.js @@ -6,13 +6,13 @@ This migration removes the BlackListController from disk state */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/022.js b/app/scripts/migrations/022.js index 01e4132ac..b986a94f4 100644 --- a/app/scripts/migrations/022.js +++ b/app/scripts/migrations/022.js @@ -7,13 +7,13 @@ This migration adds submittedTime to the txMeta if it is not their */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/023.js b/app/scripts/migrations/023.js index 00fb8a075..af4ee8d45 100644 --- a/app/scripts/migrations/023.js +++ b/app/scripts/migrations/023.js @@ -7,13 +7,13 @@ This migration removes transactions that are no longer usefull down to 40 total */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/024.js b/app/scripts/migrations/024.js index 1c317ce23..569c817c2 100644 --- a/app/scripts/migrations/024.js +++ b/app/scripts/migrations/024.js @@ -8,13 +8,13 @@ all unapproved transactions */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data const newState = transformState(state) diff --git a/app/scripts/migrations/025.js b/app/scripts/migrations/025.js index 528ef219c..d338f265f 100644 --- a/app/scripts/migrations/025.js +++ b/app/scripts/migrations/025.js @@ -8,13 +8,13 @@ normalizes txParams on unconfirmed txs */ import ethUtil from 'ethereumjs-util' -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data const newState = transformState(state) diff --git a/app/scripts/migrations/026.js b/app/scripts/migrations/026.js index ec20f114a..2282455ef 100644 --- a/app/scripts/migrations/026.js +++ b/app/scripts/migrations/026.js @@ -7,12 +7,12 @@ This migration moves the identities stored in the KeyringController */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/027.js b/app/scripts/migrations/027.js index 9c672d048..dc4d0beb7 100644 --- a/app/scripts/migrations/027.js +++ b/app/scripts/migrations/027.js @@ -6,13 +6,13 @@ const version = 27 normalizes txParams on unconfirmed txs */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data const newState = transformState(state) diff --git a/app/scripts/migrations/028.js b/app/scripts/migrations/028.js index d6ee119fb..583f3299d 100644 --- a/app/scripts/migrations/028.js +++ b/app/scripts/migrations/028.js @@ -6,13 +6,13 @@ const version = 28 normalizes txParams on unconfirmed txs */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data const newState = transformState(state) diff --git a/app/scripts/migrations/030.js b/app/scripts/migrations/030.js index 0b6ca33c6..499f8d664 100644 --- a/app/scripts/migrations/030.js +++ b/app/scripts/migrations/030.js @@ -7,13 +7,13 @@ removes invalid chaids from preferences and networkController for custom rpcs */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data const newState = transformState(state) diff --git a/app/scripts/migrations/031.js b/app/scripts/migrations/031.js index 03757ce09..14d4a7ef8 100644 --- a/app/scripts/migrations/031.js +++ b/app/scripts/migrations/031.js @@ -1,6 +1,6 @@ // next version number const version = 31 -import clone from 'clone' +import { cloneDeep } from 'lodash' /* * The purpose of this migration is to properly set the completedOnboarding flag based on the state @@ -10,7 +10,7 @@ export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data const newState = transformState(state) diff --git a/app/scripts/migrations/032.js b/app/scripts/migrations/032.js index 6ad21fad7..4f807617d 100644 --- a/app/scripts/migrations/032.js +++ b/app/scripts/migrations/032.js @@ -1,5 +1,5 @@ const version = 32 -import clone from 'clone' +import { cloneDeep } from 'lodash' /** * The purpose of this migration is to set the {@code completedUiMigration} flag based on the user's UI preferences @@ -7,7 +7,7 @@ import clone from 'clone' export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data versionedData.data = transformState(state) diff --git a/app/scripts/migrations/033.js b/app/scripts/migrations/033.js index 9a1f3f48a..70710e793 100644 --- a/app/scripts/migrations/033.js +++ b/app/scripts/migrations/033.js @@ -7,13 +7,13 @@ Cleans up notices and assocated notice controller code */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data const newState = transformState(state) diff --git a/app/scripts/migrations/034.js b/app/scripts/migrations/034.js index d7fa0f69b..92a8d909f 100644 --- a/app/scripts/migrations/034.js +++ b/app/scripts/migrations/034.js @@ -1,5 +1,5 @@ const version = 34 -import clone from 'clone' +import { cloneDeep } from 'lodash' /** * The purpose of this migration is to enable the {@code privacyMode} feature flag and set the user as being migrated @@ -8,7 +8,7 @@ import clone from 'clone' export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data versionedData.data = transformState(state) diff --git a/app/scripts/migrations/035.js b/app/scripts/migrations/035.js index 748f2312c..b483c35de 100644 --- a/app/scripts/migrations/035.js +++ b/app/scripts/migrations/035.js @@ -7,13 +7,13 @@ Removes the deprecated 'seedWords' state */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version versionedData.data = transformState(versionedData.data) return versionedData diff --git a/app/scripts/migrations/036.js b/app/scripts/migrations/036.js index 186ff2623..0ba0bc035 100644 --- a/app/scripts/migrations/036.js +++ b/app/scripts/migrations/036.js @@ -1,5 +1,5 @@ const version = 36 -import clone from 'clone' +import { cloneDeep } from 'lodash' /** * The purpose of this migration is to remove the {@code privacyMode} feature flag. @@ -7,7 +7,7 @@ import clone from 'clone' export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data versionedData.data = transformState(state) diff --git a/app/scripts/migrations/037.js b/app/scripts/migrations/037.js index 2fcef5c73..6ca313acd 100644 --- a/app/scripts/migrations/037.js +++ b/app/scripts/migrations/037.js @@ -1,5 +1,5 @@ const version = 37 -import clone from 'clone' +import { cloneDeep } from 'lodash' import { util } from 'gaba' /** @@ -10,7 +10,7 @@ import { util } from 'gaba' export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data versionedData.data = transformState(state) diff --git a/app/scripts/migrations/038.js b/app/scripts/migrations/038.js index 70314aab8..e0e7d5b89 100644 --- a/app/scripts/migrations/038.js +++ b/app/scripts/migrations/038.js @@ -1,5 +1,5 @@ const version = 38 -import clone from 'clone' +import { cloneDeep } from 'lodash' import ABTestController from '../controllers/ab-test' import { getRandomArrayItem } from '../lib/util' @@ -9,7 +9,7 @@ import { getRandomArrayItem } from '../lib/util' export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data versionedData.data = transformState(state) diff --git a/app/scripts/migrations/039.js b/app/scripts/migrations/039.js index 5f6bc3d0c..f1f38c0a5 100644 --- a/app/scripts/migrations/039.js +++ b/app/scripts/migrations/039.js @@ -1,5 +1,5 @@ const version = 39 -import clone from 'clone' +import { cloneDeep } from 'lodash' import ethUtil from 'ethereumjs-util' const DAI_V1_CONTRACT_ADDRESS = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359' @@ -22,7 +22,7 @@ function isOldDai (token = {}) { export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data versionedData.data = transformState(state) diff --git a/app/scripts/migrations/040.js b/app/scripts/migrations/040.js index 19fa2bf16..ca243e4aa 100644 --- a/app/scripts/migrations/040.js +++ b/app/scripts/migrations/040.js @@ -1,5 +1,5 @@ const version = 40 -import clone from 'clone' +import { cloneDeep } from 'lodash' /** * Site connections are now managed by the PermissionsController, and the @@ -9,7 +9,7 @@ import clone from 'clone' export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data versionedData.data = transformState(state) diff --git a/app/scripts/migrations/041.js b/app/scripts/migrations/041.js index b5ffed38e..83028ed1b 100644 --- a/app/scripts/migrations/041.js +++ b/app/scripts/migrations/041.js @@ -1,5 +1,5 @@ const version = 41 -import clone from 'clone' +import { cloneDeep } from 'lodash' /** * PreferencesController.autoLogoutTimeLimit -> autoLockTimeLimit @@ -7,7 +7,7 @@ import clone from 'clone' export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data versionedData.data = transformState(state) diff --git a/app/scripts/migrations/fail-tx.js b/app/scripts/migrations/fail-tx.js index 52b3a7c96..e5a349033 100644 --- a/app/scripts/migrations/fail-tx.js +++ b/app/scripts/migrations/fail-tx.js @@ -1,8 +1,8 @@ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default function failTxsThat (version, reason, condition) { return function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/template.js b/app/scripts/migrations/template.js index bff71aa33..c9e3b795b 100644 --- a/app/scripts/migrations/template.js +++ b/app/scripts/migrations/template.js @@ -7,13 +7,13 @@ description of migration and what it does */ -import clone from 'clone' +import { cloneDeep } from 'lodash' export default { version, migrate: async function (originalVersionedData) { - const versionedData = clone(originalVersionedData) + const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data const newState = transformState(state) diff --git a/development/version-bump.js b/development/version-bump.js index 6ae21b782..74c321b26 100644 --- a/development/version-bump.js +++ b/development/version-bump.js @@ -1,7 +1,7 @@ -const clone = require('clone') +const { cloneDeep } = require('lodash') async function versionBump (bumpType, changelog, oldManifest) { - const manifest = clone(oldManifest) + const manifest = cloneDeep(oldManifest) const newVersion = newVersionFrom(manifest, bumpType) manifest.version = newVersion diff --git a/package.json b/package.json index 5ecb412cb..667876139 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,6 @@ "browserify-derequire": "^0.9.4", "c3": "^0.7.10", "classnames": "^2.2.6", - "clone": "^2.1.2", "content-hash": "^2.5.0", "copy-to-clipboard": "^3.0.8", "currency-formatter": "^1.4.2", diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index c4a6e4a8b..5da4750ee 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -1,6 +1,6 @@ import assert from 'assert' import sinon from 'sinon' -import clone from 'clone' +import { cloneDeep } from 'lodash' import nock from 'nock' import ethUtil from 'ethereumjs-util' import { obj as createThoughStream } from 'through2' @@ -94,7 +94,7 @@ describe('MetaMaskController', function () { return Promise.resolve(this.object) }, }, - initState: clone(firstTimeState), + initState: cloneDeep(firstTimeState), platform: { showTransactionNotification: () => {} }, }) // disable diagnostics diff --git a/test/unit/app/seed-phrase-verifier-test.js b/test/unit/app/seed-phrase-verifier-test.js index 1ffaf7bd1..7da97794a 100644 --- a/test/unit/app/seed-phrase-verifier-test.js +++ b/test/unit/app/seed-phrase-verifier-test.js @@ -1,5 +1,5 @@ import assert from 'assert' -import clone from 'clone' +import { cloneDeep } from 'lodash' import KeyringController from 'eth-keyring-controller' import firstTimeState from '../../../app/scripts/first-time-state' import seedPhraseVerifier from '../../../app/scripts/lib/seed-phrase-verifier' @@ -17,7 +17,7 @@ describe('SeedPhraseVerifier', function () { beforeEach(async function () { keyringController = new KeyringController({ - initState: clone(firstTimeState), + initState: cloneDeep(firstTimeState), encryptor: mockEncryptor, }) diff --git a/test/unit/migrations/migrator-test.js b/test/unit/migrations/migrator-test.js index 5173f8551..22485ff8f 100644 --- a/test/unit/migrations/migrator-test.js +++ b/test/unit/migrations/migrator-test.js @@ -1,6 +1,6 @@ import fs from 'fs' import assert from 'assert' -import clone from 'clone' +import { cloneDeep } from 'lodash' import pify from 'pify' import Migrator from '../../../app/scripts/lib/migrator' import liveMigrations from '../../../app/scripts/migrations' @@ -10,7 +10,7 @@ const stubMigrations = [ version: 1, migrate: (data) => { // clone the data just like we do in migrations - const clonedData = clone(data) + const clonedData = cloneDeep(data) clonedData.meta.version = 1 return Promise.resolve(clonedData) }, @@ -18,7 +18,7 @@ const stubMigrations = [ { version: 2, migrate: (data) => { - const clonedData = clone(data) + const clonedData = cloneDeep(data) clonedData.meta.version = 2 return Promise.resolve(clonedData) }, @@ -26,7 +26,7 @@ const stubMigrations = [ { version: 3, migrate: (data) => { - const clonedData = clone(data) + const clonedData = cloneDeep(data) clonedData.meta.version = 3 return Promise.resolve(clonedData) }, diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js index 349368701..b3aedd5a4 100644 --- a/test/unit/ui/app/actions.spec.js +++ b/test/unit/ui/app/actions.spec.js @@ -5,7 +5,7 @@ import assert from 'assert' import sinon from 'sinon' -import clone from 'clone' +import { cloneDeep } from 'lodash' import nock from 'nock' import fetchMock from 'fetch-mock' import configureStore from 'redux-mock-store' @@ -53,7 +53,7 @@ describe('Actions', () => { return Promise.resolve(this.object) }, }, - initState: clone(firstTimeState), + initState: cloneDeep(firstTimeState), }) metamaskController.threeBoxController = { diff --git a/ui/app/ducks/index.js b/ui/app/ducks/index.js index 3ceb529c1..4786584b8 100644 --- a/ui/app/ducks/index.js +++ b/ui/app/ducks/index.js @@ -1,4 +1,4 @@ -import clone from 'clone' +import { cloneDeep } from 'lodash' import copyToClipboard from 'copy-to-clipboard' // @@ -57,7 +57,7 @@ function rootReducer (state, action) { } window.getCleanAppState = function () { - const state = clone(window.METAMASK_CACHED_LOG_STATE) + const state = cloneDeep(window.METAMASK_CACHED_LOG_STATE) // append additional information state.version = global.platform.getVersion() state.browser = window.navigator.userAgent From 4136209f3dfbdf1056b7589eee4a94a08f7f2262 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 13:45:16 -0330 Subject: [PATCH 199/689] Remove redux-logger from mock-store (#7930) --- package.json | 1 - test/lib/mock-store.js | 8 +------- yarn.lock | 12 ------------ 3 files changed, 1 insertion(+), 20 deletions(-) diff --git a/package.json b/package.json index 667876139..850dccf12 100644 --- a/package.json +++ b/package.json @@ -165,7 +165,6 @@ "readable-stream": "^2.3.3", "recompose": "^0.25.0", "redux": "^3.0.5", - "redux-logger": "^3.0.6", "redux-thunk": "^2.2.0", "reselect": "^3.0.1", "rpc-cap": "^1.0.3", diff --git a/test/lib/mock-store.js b/test/lib/mock-store.js index b007533b7..b37d42c51 100644 --- a/test/lib/mock-store.js +++ b/test/lib/mock-store.js @@ -1,17 +1,11 @@ import { applyMiddleware, createStore } from 'redux' import thunkMiddleware from 'redux-thunk' -import { createLogger } from 'redux-logger' const rootReducer = function () {} export default configureStore -const loggerMiddleware = createLogger() - -const createStoreWithMiddleware = applyMiddleware( - thunkMiddleware, - loggerMiddleware -)(createStore) +const createStoreWithMiddleware = applyMiddleware(thunkMiddleware)(createStore) function configureStore (initialState) { return createStoreWithMiddleware(rootReducer, initialState) diff --git a/yarn.lock b/yarn.lock index ca47f7d4e..0f9deb2cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8686,11 +8686,6 @@ decompress@^4.0.0, decompress@^4.2.0: pify "^2.3.0" strip-dirs "^2.0.0" -deep-diff@^0.3.5: - version "0.3.8" - resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.8.tgz#c01de63efb0eec9798801d40c7e0dae25b582c84" - integrity sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ= - deep-eql@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" @@ -24308,13 +24303,6 @@ redux-devtools-instrument@^1.9.4: lodash "^4.2.0" symbol-observable "^1.0.2" -redux-logger@^3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/redux-logger/-/redux-logger-3.0.6.tgz#f7555966f3098f3c88604c449cf0baf5778274bf" - integrity sha1-91VZZvMJjzyIYExEnPC69XeCdL8= - dependencies: - deep-diff "^0.3.5" - redux-mock-store@^1.5.3: version "1.5.3" resolved "https://registry.yarnpkg.com/redux-mock-store/-/redux-mock-store-1.5.3.tgz#1f10528949b7ce8056c2532624f7cafa98576c6d" From 6f9b74256ca5c4c291386f24da48118338ef0a2e Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 13:59:56 -0330 Subject: [PATCH 200/689] Delete unused .dockerignore file (#7929) --- .dockerignore | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index ea6720feb..000000000 --- a/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -node_modules -builds -development \ No newline at end of file From 00a73ee25e744763bf11dba4c8c5eddaaee07ef0 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 29 Jan 2020 13:36:03 -0400 Subject: [PATCH 201/689] Replace `debounce` package with `debounce` function from `lodash` (#7931) These two functions differ slightly in options, but none of those options are being used by us, so in these cases they're functionally equivalent. They're even both descendants of the original `debounce` function from `underscore`. This was done to reduce the number of direct dependencies we have. It should not affect bundle size, as we still depend upon the `debounce` package transitively. --- app/scripts/metamask-controller.js | 2 +- package.json | 1 - ui/app/components/ui/mascot.js | 2 +- .../send/send-content/add-recipient/ens-input.component.js | 2 +- yarn.lock | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 9dc8f0b2c..5bbc54ccd 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -14,7 +14,7 @@ import ComposableObservableStore from './lib/ComposableObservableStore' import asStream from 'obs-store/lib/asStream' import AccountTracker from './lib/account-tracker' import RpcEngine from 'json-rpc-engine' -import debounce from 'debounce' +import { debounce } from 'lodash' import createEngineStream from 'json-rpc-middleware-stream/engineStream' import createFilterMiddleware from 'eth-json-rpc-filters' import createSubscriptionManager from 'eth-json-rpc-filters/subscriptionManager' diff --git a/package.json b/package.json index 850dccf12..e7f0c3088 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,6 @@ "copy-to-clipboard": "^3.0.8", "currency-formatter": "^1.4.2", "d3": "^5.15.0", - "debounce": "1.1.0", "debounce-stream": "^2.0.0", "deep-freeze-strict": "1.1.1", "dnode": "^1.2.2", diff --git a/ui/app/components/ui/mascot.js b/ui/app/components/ui/mascot.js index 835290487..db2037cdf 100644 --- a/ui/app/components/ui/mascot.js +++ b/ui/app/components/ui/mascot.js @@ -1,7 +1,7 @@ import PropTypes from 'prop-types' import React, { createRef, Component } from 'react' import metamaskLogo from 'metamask-logo' -import debounce from 'debounce' +import { debounce } from 'lodash' export default class Mascot extends Component { static propTypes = { diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js index bac9ab3e6..4efea98de 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js +++ b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js @@ -4,7 +4,7 @@ import c from 'classnames' import { isValidENSAddress, isValidAddress, isValidAddressHead } from '../../../../helpers/utils/util' import { ellipsify } from '../../send.utils' -import debounce from 'debounce' +import { debounce } from 'lodash' import copyToClipboard from 'copy-to-clipboard/index' import ENS from 'ethjs-ens' import networkMap from 'ethjs-ens/lib/network-map.json' diff --git a/yarn.lock b/yarn.lock index 0f9deb2cd..1c020d450 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8549,7 +8549,7 @@ debounce-stream@^2.0.0: duplexer "^0.1.1" through "^2.3.6" -debounce@1.1.0, debounce@^1.0.0: +debounce@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.1.0.tgz#6a1a4ee2a9dc4b7c24bb012558dbcdb05b37f408" integrity sha512-ZQVKfRVlwRfD150ndzEK8M90ABT+Y/JQKs4Y7U4MXdpuoUkkrr4DwKbVux3YjylA5bUMUj0Nc3pMxPJX6N2QQQ== From e8a42ba6b0f32f995eaa0b24200b63e38577144a Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 14:33:44 -0330 Subject: [PATCH 202/689] Remove unused promise-filter dependency (#7932) --- package.json | 1 - yarn.lock | 12 ------------ 2 files changed, 13 deletions(-) diff --git a/package.json b/package.json index e7f0c3088..80f2e4b72 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,6 @@ "pify": "^3.0.0", "polyfill-crypto.getrandomvalues": "^1.0.0", "post-message-stream": "^3.0.0", - "promise-filter": "^1.1.0", "promise-to-callback": "^1.0.0", "prop-types": "^15.6.1", "pubnub": "4.24.4", diff --git a/yarn.lock b/yarn.lock index 1c020d450..f59b88aa7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3857,11 +3857,6 @@ any-promise@1.3.0, any-promise@^1.0.0, any-promise@^1.1.0, any-promise@^1.3.0: resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= -any-promise@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-0.1.0.tgz#830b680aa7e56f33451d4b049f3bd8044498ee27" - integrity sha1-gwtoCqflbzNFHUsEnzvYBESY7ic= - anymatch@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" @@ -22783,13 +22778,6 @@ prometheus-gc-stats@~0.6.0: optionalDependencies: gc-stats "^1.2.1" -promise-filter@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/promise-filter/-/promise-filter-1.1.0.tgz#7ec3ce990c867ccb9de8638dbd19ee17a52a4b59" - integrity sha1-fsPOmQyGfMud6GONvRnuF6UqS1k= - dependencies: - any-promise "^0.1.0" - promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" From 59a1746afc6d286ab1c14aa9556ef26f1c0a844f Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 29 Jan 2020 14:16:38 -0400 Subject: [PATCH 203/689] Validate custom spend limit (#7920) The custom spend limit was previously not validated. It did have a minimum of zero set, but this didn't have any affect (that minimum is used for form constraint validation, and this field wasn't in a form). The field was never checked to ensure the contents didn't exceed the maximum. The field is now checked for values that exceed the maximum, and invalid values in general (including negative values). The parameters to the `showEditApprovalPermissionModal` were also alphabetized to make them easier to read. In the course of doing this, I noticed that the origin was missing from one of the calls. This was responsible for the modal saying "Spend limit requested by undefined" when clicking "Edit" under the transaction details. This has been fixed. --- app/_locales/en/messages.json | 6 +++ .../edit-approval-permission.component.js | 49 +++++++++++++++++-- .../confirm-approve-content.component.js | 16 +++++- .../confirm-approve.component.js | 1 + .../confirm-approve.container.js | 18 ++++--- 5 files changed, 75 insertions(+), 15 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 55b423894..64c95545a 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1307,6 +1307,12 @@ "message": "Spend limit requested by $1", "description": "Origin of the site requesting the spend limit" }, + "spendLimitTooLarge": { + "message": "Spend limit too large" + }, + "spendLimitInvalid": { + "message": "Spend limit invalid; must be a positive number" + }, "switchNetworks": { "message": "Switch Networks" }, diff --git a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js index f7dad3a50..7c850279b 100644 --- a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js +++ b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js @@ -1,13 +1,18 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' +import log from 'loglevel' import Modal from '../../modal' import Identicon from '../../../ui/identicon' import TextField from '../../../ui/text-field' +import { calcTokenAmount } from '../../../../helpers/utils/token-util' import classnames from 'classnames' import BigNumber from 'bignumber.js' +const MAX_UNSIGNED_256_INT = new BigNumber(2).pow(256).minus(1).toString(10) + export default class EditApprovalPermission extends PureComponent { static propTypes = { + decimals: PropTypes.number, hideModal: PropTypes.func.isRequired, selectedIdentity: PropTypes.object, tokenAmount: PropTypes.string, @@ -15,7 +20,7 @@ export default class EditApprovalPermission extends PureComponent { tokenSymbol: PropTypes.string, tokenBalance: PropTypes.string, setCustomAmount: PropTypes.func, - origin: PropTypes.string, + origin: PropTypes.string.isRequired, } static contextTypes = { @@ -27,7 +32,7 @@ export default class EditApprovalPermission extends PureComponent { selectedOptionIsUnlimited: !this.props.customTokenAmount, } - renderModalContent () { + renderModalContent (error) { const { t } = this.context const { hideModal, @@ -136,7 +141,6 @@ export default class EditApprovalPermission extends PureComponent {
    { this.setState({ customSpendLimit: event.target.value }) @@ -147,6 +151,7 @@ export default class EditApprovalPermission extends PureComponent { fullWidth margin="dense" value={ this.state.customSpendLimit } + error={error} />
    @@ -156,10 +161,44 @@ export default class EditApprovalPermission extends PureComponent { ) } + validateSpendLimit () { + const { t } = this.context + const { decimals } = this.props + const { selectedOptionIsUnlimited, customSpendLimit } = this.state + + if (selectedOptionIsUnlimited || !customSpendLimit) { + return + } + + let customSpendLimitNumber + try { + customSpendLimitNumber = new BigNumber(customSpendLimit) + } catch (error) { + log.debug(`Error converting '${customSpendLimit}' to BigNumber:`, error) + return t('spendLimitInvalid') + } + + if (customSpendLimitNumber.isNegative()) { + return t('spendLimitInvalid') + } + + const maxTokenAmount = calcTokenAmount(MAX_UNSIGNED_256_INT, decimals) + if (customSpendLimitNumber.greaterThan(maxTokenAmount)) { + return t('spendLimitTooLarge') + } + } + render () { const { t } = this.context const { setCustomAmount, hideModal, customTokenAmount } = this.props const { selectedOptionIsUnlimited, customSpendLimit } = this.state + + const error = this.validateSpendLimit() + const disabled = Boolean( + (customSpendLimit === customTokenAmount && !selectedOptionIsUnlimited) || + error + ) + return ( { @@ -170,9 +209,9 @@ export default class EditApprovalPermission extends PureComponent { submitType="primary" contentClass="edit-approval-permission-modal-content" containerClass="edit-approval-permission-modal-container" - submitDisabled={ (customSpendLimit === customTokenAmount) && !selectedOptionIsUnlimited } + submitDisabled={disabled} > - { this.renderModalContent() } + { this.renderModalContent(error) } ) } diff --git a/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js b/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js index 673bfe415..461d2e942 100644 --- a/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js +++ b/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js @@ -13,6 +13,7 @@ export default class ConfirmApproveContent extends Component { } static propTypes = { + decimals: PropTypes.number, tokenAmount: PropTypes.string, customTokenAmount: PropTypes.string, tokenSymbol: PropTypes.string, @@ -127,6 +128,7 @@ export default class ConfirmApproveContent extends Component { render () { const { t } = this.context const { + decimals, siteImage, tokenAmount, customTokenAmount, @@ -164,7 +166,15 @@ export default class ConfirmApproveContent extends Component { >
    showEditApprovalPermissionModal({ customTokenAmount, tokenAmount, tokenSymbol, setCustomAmount, tokenBalance, origin })} + onClick={() => showEditApprovalPermissionModal({ + customTokenAmount, + decimals, + origin, + setCustomAmount, + tokenAmount, + tokenSymbol, + tokenBalance, + })} > { t('editPermission') }
    @@ -209,10 +219,12 @@ export default class ConfirmApproveContent extends Component { showEdit: true, onEditClick: () => showEditApprovalPermissionModal({ customTokenAmount, + decimals, + origin, + setCustomAmount, tokenAmount, tokenSymbol, tokenBalance, - setCustomAmount, }), })} diff --git a/ui/app/pages/confirm-approve/confirm-approve.component.js b/ui/app/pages/confirm-approve/confirm-approve.component.js index bb7f6ceb2..01c93e5a4 100644 --- a/ui/app/pages/confirm-approve/confirm-approve.component.js +++ b/ui/app/pages/confirm-approve/confirm-approve.component.js @@ -87,6 +87,7 @@ export default class ConfirmApprove extends Component { title={tokensText} contentComponent={( { this.setState({ customPermissionAmount: newAmount }) diff --git a/ui/app/pages/confirm-approve/confirm-approve.container.js b/ui/app/pages/confirm-approve/confirm-approve.container.js index 29fec2ff3..92f0eb552 100644 --- a/ui/app/pages/confirm-approve/confirm-approve.container.js +++ b/ui/app/pages/confirm-approve/confirm-approve.container.js @@ -76,20 +76,22 @@ const mapDispatchToProps = (dispatch) => { return { showCustomizeGasModal: (txData) => dispatch(showModal({ name: 'CUSTOMIZE_GAS', txData })), showEditApprovalPermissionModal: ({ - tokenAmount, customTokenAmount, - tokenSymbol, - tokenBalance, - setCustomAmount, + decimals, origin, + setCustomAmount, + tokenAmount, + tokenBalance, + tokenSymbol, }) => dispatch(showModal({ name: 'EDIT_APPROVAL_PERMISSION', - tokenAmount, customTokenAmount, - tokenSymbol, - tokenBalance, - setCustomAmount, + decimals, origin, + setCustomAmount, + tokenAmount, + tokenBalance, + tokenSymbol, })), } } From 171d50434a56f2d697458f76bb9930ab7900061f Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 15:24:11 -0330 Subject: [PATCH 204/689] Delete outdated team page (#7928) --- docs/team.md | 78 ---------------------------------------------------- 1 file changed, 78 deletions(-) delete mode 100644 docs/team.md diff --git a/docs/team.md b/docs/team.md deleted file mode 100644 index 72f9d3226..000000000 --- a/docs/team.md +++ /dev/null @@ -1,78 +0,0 @@ -# The Team - -Here is an overview of the current MetaMask team, and their primary roles and responsibilities, in the order they joined the team. - -## Core Team Members - -The core team maintains aspects of the main product (the extension) and the core libraries (the MetaMask Controller, provider-engine, etc). - -### Aaron Davis - -@kumavis -Founder / Technical Lead - -Especially in charge of connection to the blockchain. Wrote [provider-engine](https://github.com/MetaMask/provider-engine), and is currently working with @hermanjunge on our JavaScript light-client. - -### Dan Finlay - -@danfinlay -Software Engineer / Product Lead - -Focused on the deliverable, user-valuable aspects of MetaMask, including usability and documentation. Coordinates efforts between different branches of the team, and integrations with other projects. - -### Frankie Pangilinan - -@frankiebee -Software Engineer / Transaction Manager Lead - -Frankie contributes code throughout MetaMask, but has become especially specialized in the way MetaMask manages transactions. She is also the original lead of the [Mascara](https://github.com/MetaMask/mascara) project. - -### Kevin Serrano - -@Zanibas -Software Engineer / Project Management Lead - -Kevin is a software engineer, but also spends a lot of his time keeping the team's administrative operations running smoothly. - -### Thomas Huang - -@tmashuang -QA Engineer - -Thomas is the head of MetaMask Quality Assurance. He both takes the final pass of branches of code before we ship to production, and is also in charge of continuously improving our automated quality assurance process. - -### Christian Jeria - -@cjeria -User Experience Designer - -Christian is the lead of MetaMask's user experience. He is continuously designing prototypes, testing them with users, and refining them with our developers for production. - -### Paul Bouchon - -@bitpshr -Software Engineer - -The newest member of the team! Paul is currently being onboarded, and finding his niche within the team. - -## Laboratory Team Members - -These team members are working on projects that will benefit MetaMask, but are not directly working on the product itself. - -### Herman Junge - -@hermanjunge -Software Engineer - -Herman is currently leading the Mustekala project, a JavaScript, IPFS-based Ethereum light client. - -## Kyokan Team Members - -[Kyokan](http://kyokan.io/) is a consulting firm that has been working closely with the MetaMask team on the latest version of our user interface. Their team members are not members of ConsenSys LLC, but they contribute a lot to the project. - -- Daniel Tsui (@sdsui) -- Chi Kei Chan (@chikeichan) -- Dan Miller (@danjm) -- David Yoo (@yookd) -- Whymarrh Whitby (@whymarrh) - From 6c616b0d833f4f0979e84c10e3cc3ba4cd25d231 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 15:50:52 -0330 Subject: [PATCH 205/689] Replace mkdirp with built-in functionality (#7934) --- gulpfile.js | 4 ++-- package.json | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 4a7c3a471..8dbcf9d1d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,3 +1,4 @@ +const fs = require('fs') const watchify = require('watchify') const browserify = require('browserify') const envify = require('envify/custom') @@ -23,7 +24,6 @@ const rename = require('gulp-rename') const gulpMultiProcess = require('gulp-multi-process') const endOfStream = pify(require('end-of-stream')) const sesify = require('sesify') -const mkdirp = require('mkdirp') const imagemin = require('gulp-imagemin') const { makeStringTransform } = require('browserify-transform-tools') @@ -679,7 +679,7 @@ function configureBundleForSesify ({ browserifyOpts.fullPaths = true // record dependencies used in bundle - mkdirp.sync('./sesify') + fs.mkdirSync('./sesify', { recursive: true }) browserifyOpts.plugin.push(['deps-dump', { filename: `./sesify/deps-${bundleName}.json`, }]) diff --git a/package.json b/package.json index 80f2e4b72..d90cd717a 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "test:flat:build": "yarn test:flat:build:ui && yarn test:flat:build:tests && yarn test:flat:build:locales", "test:flat:build:tests": "node test/integration/index.js", "test:flat:build:states": "node development/genStates.js", - "test:flat:build:locales": "mkdirp dist/chrome && cp -R app/_locales dist/chrome/_locales", + "test:flat:build:locales": "mkdir -p dist/chrome && cp -R app/_locales dist/chrome/_locales", "test:flat:build:ui": "yarn test:flat:build:states && browserify --transform babelify --transform brfs ./development/mock-dev.js -o ./development/bundle.js", "ganache:start": "./development/run-ganache", "sentry:publish": "node ./development/sentry-publish.js", @@ -126,7 +126,6 @@ "luxon": "^1.8.2", "metamask-inpage-provider": "^4.0.3", "metamask-logo": "^2.1.4", - "mkdirp": "^0.5.1", "multihashes": "^0.4.12", "nanoid": "^2.1.6", "nonce-tracker": "^1.0.0", From 07ce849c4869f0761640b8227a12dabe9b6c1f16 Mon Sep 17 00:00:00 2001 From: ryanml Date: Wed, 29 Jan 2020 11:42:46 -0800 Subject: [PATCH 206/689] Sorting seed phrase confirmation buttons alphabetically (#7933) --- test/e2e/address-book.spec.js | 2 +- test/e2e/incremental-security.spec.js | 2 +- test/e2e/metamask-responsive-ui.spec.js | 2 +- test/e2e/metamask-ui.spec.js | 2 +- .../confirm-seed-phrase.component.js | 39 +++++++++---------- .../confirm-seed-phrase/index.scss | 4 +- .../confirm-seed-phrase-component.test.js | 16 ++++---- 7 files changed, 33 insertions(+), 34 deletions(-) diff --git a/test/e2e/address-book.spec.js b/test/e2e/address-book.spec.js index 8d0d7ac8c..02d391cb4 100644 --- a/test/e2e/address-book.spec.js +++ b/test/e2e/address-book.spec.js @@ -98,7 +98,7 @@ describe('MetaMask', function () { }) async function clickWordAndWait (word) { - await driver.clickElement(By.css(`[data-testid="seed-phrase-shuffled"] [data-testid="draggable-seed-${word}"]`)) + await driver.clickElement(By.css(`[data-testid="seed-phrase-sorted"] [data-testid="draggable-seed-${word}"]`)) await driver.delay(tinyDelayMs) } diff --git a/test/e2e/incremental-security.spec.js b/test/e2e/incremental-security.spec.js index 3287ca0ae..734655b81 100644 --- a/test/e2e/incremental-security.spec.js +++ b/test/e2e/incremental-security.spec.js @@ -171,7 +171,7 @@ describe('MetaMask', function () { }) async function clickWordAndWait (word) { - await driver.clickElement(By.css(`[data-testid="seed-phrase-shuffled"] [data-testid="draggable-seed-${word}"]`)) + await driver.clickElement(By.css(`[data-testid="seed-phrase-sorted"] [data-testid="draggable-seed-${word}"]`)) await driver.delay(tinyDelayMs) } diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index f0d66746d..6dda0192c 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -93,7 +93,7 @@ describe('MetaMask', function () { }) async function clickWordAndWait (word) { - await driver.clickElement(By.css(`[data-testid="seed-phrase-shuffled"] [data-testid="draggable-seed-${word}"]`)) + await driver.clickElement(By.css(`[data-testid="seed-phrase-sorted"] [data-testid="draggable-seed-${word}"]`)) await driver.delay(tinyDelayMs) } diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index bc6b94c56..d3f5f6e5e 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -95,7 +95,7 @@ describe('MetaMask', function () { }) async function clickWordAndWait (word) { - await driver.clickElement(By.css(`[data-testid="seed-phrase-shuffled"] [data-testid="draggable-seed-${word}"]`)) + await driver.clickElement(By.css(`[data-testid="seed-phrase-sorted"] [data-testid="draggable-seed-${word}"]`)) await driver.delay(tinyDelayMs) } diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js index 2b6d5ceee..2f04a9055 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js @@ -1,7 +1,6 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' -import { shuffle } from 'lodash' import Button from '../../../../components/ui/button' import { INITIALIZE_END_OF_FLOW_ROUTE, @@ -34,7 +33,7 @@ export default class ConfirmSeedPhrase extends PureComponent { state = { selectedSeedIndices: [], - shuffledSeedWords: [], + sortedSeedWords: [], pendingSeedIndices: [], draggingSeedIndex: -1, hoveringIndex: -1, @@ -42,8 +41,8 @@ export default class ConfirmSeedPhrase extends PureComponent { componentDidMount () { const { seedPhrase = '' } = this.props - const shuffledSeedWords = shuffle(seedPhrase.split(' ')) || [] - this.setState({ shuffledSeedWords }) + const sortedSeedWords = (seedPhrase.split(' ') || []).sort() + this.setState({ sortedSeedWords }) } setDraggingSeedIndex = draggingSeedIndex => this.setState({ draggingSeedIndex }) @@ -106,24 +105,24 @@ export default class ConfirmSeedPhrase extends PureComponent { } } - handleSelectSeedWord = (shuffledIndex) => { + handleSelectSeedWord = (index) => { this.setState({ - selectedSeedIndices: [...this.state.selectedSeedIndices, shuffledIndex], - pendingSeedIndices: [...this.state.pendingSeedIndices, shuffledIndex], + selectedSeedIndices: [...this.state.selectedSeedIndices, index], + pendingSeedIndices: [...this.state.pendingSeedIndices, index], }) } - handleDeselectSeedWord = shuffledIndex => { + handleDeselectSeedWord = (index) => { this.setState({ - selectedSeedIndices: this.state.selectedSeedIndices.filter(i => shuffledIndex !== i), - pendingSeedIndices: this.state.pendingSeedIndices.filter(i => shuffledIndex !== i), + selectedSeedIndices: this.state.selectedSeedIndices.filter(i => index !== i), + pendingSeedIndices: this.state.pendingSeedIndices.filter(i => index !== i), }) } isValid () { const { seedPhrase } = this.props - const { selectedSeedIndices, shuffledSeedWords } = this.state - const selectedSeedWords = selectedSeedIndices.map(i => shuffledSeedWords[i]) + const { selectedSeedIndices, sortedSeedWords } = this.state + const selectedSeedWords = selectedSeedIndices.map(i => sortedSeedWords[i]) return seedPhrase === selectedSeedWords.join(' ') } @@ -132,7 +131,7 @@ export default class ConfirmSeedPhrase extends PureComponent { const { history } = this.props const { selectedSeedIndices, - shuffledSeedWords, + sortedSeedWords, draggingSeedIndex, } = this.state @@ -163,9 +162,9 @@ export default class ConfirmSeedPhrase extends PureComponent { { this.renderPendingSeeds() } { this.renderSelectedSeeds() } -
    +
    { - shuffledSeedWords.map((word, index) => { + sortedSeedWords.map((word, index) => { const isSelected = selectedSeedIndices.includes(index) return ( @@ -175,7 +174,7 @@ export default class ConfirmSeedPhrase extends PureComponent { index={index} setHoveringIndex={this.setHoveringIndex} onDrop={this.onDrop} - className="confirm-seed-phrase__seed-word--shuffled" + className="confirm-seed-phrase__seed-word--sorted" selected={isSelected} onClick={() => { if (!isSelected) { @@ -203,10 +202,10 @@ export default class ConfirmSeedPhrase extends PureComponent { } renderSelectedSeeds () { - const { shuffledSeedWords, selectedSeedIndices, draggingSeedIndex } = this.state + const { sortedSeedWords, selectedSeedIndices, draggingSeedIndex } = this.state return EMPTY_SEEDS.map((_, index) => { const seedIndex = selectedSeedIndices[index] - const word = shuffledSeedWords[seedIndex] + const word = sortedSeedWords[seedIndex] return ( { const seedIndex = indices[index] - const word = shuffledSeedWords[seedIndex] + const word = sortedSeedWords[seedIndex] return ( { }) assert.equal( - root.find('.confirm-seed-phrase__seed-word--shuffled').length, + root.find('.confirm-seed-phrase__seed-word--sorted').length, 12, 'should render 12 seed phrases' ) @@ -42,7 +42,7 @@ describe('ConfirmSeedPhrase Component', () => { } ) - const seeds = root.find('.confirm-seed-phrase__seed-word--shuffled') + const seeds = root.find('.confirm-seed-phrase__seed-word--sorted') // Click on 3 seeds to add to selected seeds.at(0).simulate('click') @@ -59,7 +59,7 @@ describe('ConfirmSeedPhrase Component', () => { root.state() root.update() root.state() - root.find('.confirm-seed-phrase__seed-word--shuffled').at(1).simulate('click') + root.find('.confirm-seed-phrase__seed-word--sorted').at(1).simulate('click') assert.deepEqual( root.state().selectedSeedIndices, [0, 2], @@ -80,7 +80,7 @@ describe('ConfirmSeedPhrase Component', () => { } ) - const seeds = root.find('.confirm-seed-phrase__seed-word--shuffled') + const seeds = root.find('.confirm-seed-phrase__seed-word--sorted') // Click on 3 seeds to add to selected seeds.at(0).simulate('click') @@ -113,7 +113,7 @@ describe('ConfirmSeedPhrase Component', () => { } ) - const seeds = root.find('.confirm-seed-phrase__seed-word--shuffled') + const seeds = root.find('.confirm-seed-phrase__seed-word--sorted') // Click on 3 seeds to add to selected seeds.at(0).simulate('click') @@ -148,12 +148,12 @@ describe('ConfirmSeedPhrase Component', () => { } ) - const shuffled = root.state().shuffledSeedWords - const seeds = root.find('.confirm-seed-phrase__seed-word--shuffled') + const sorted = root.state().sortedSeedWords + const seeds = root.find('.confirm-seed-phrase__seed-word--sorted') originalSeed.forEach(seed => { - const seedIndex = shuffled.findIndex(s => s === seed) + const seedIndex = sorted.findIndex(s => s === seed) seeds.at(seedIndex).simulate('click') }) From d75e587533d99b1c48b8e8d38fb56b963089b577 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 16:31:53 -0330 Subject: [PATCH 207/689] Replace fast-deep-equal with isEqual from lodash (#7935) --- package.json | 1 - .../permission-page-container.component.js | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index d90cd717a..5db38a20e 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,6 @@ "ethjs-query": "^0.3.4", "extension-port-stream": "^1.0.0", "extensionizer": "^1.0.1", - "fast-deep-equal": "^2.0.1", "fast-json-patch": "^2.0.4", "fuse.js": "^3.2.0", "gaba": "^1.9.3", diff --git a/ui/app/components/app/permission-page-container/permission-page-container.component.js b/ui/app/components/app/permission-page-container/permission-page-container.component.js index 310656d6e..bb5afac9e 100644 --- a/ui/app/components/app/permission-page-container/permission-page-container.component.js +++ b/ui/app/components/app/permission-page-container/permission-page-container.component.js @@ -1,6 +1,6 @@ import PropTypes from 'prop-types' import React, { Component } from 'react' -import deepEqual from 'fast-deep-equal' +import { isEqual } from 'lodash' import { PermissionPageContainerContent } from '.' import { PageContainerFooter } from '../../ui/page-container' @@ -40,7 +40,7 @@ export default class PermissionPageContainer extends Component { componentDidUpdate () { const newMethodNames = this.getRequestedMethodNames(this.props) - if (!deepEqual(Object.keys(this.state.selectedPermissions), newMethodNames)) { + if (!isEqual(Object.keys(this.state.selectedPermissions), newMethodNames)) { // this should be a new request, so just overwrite this.setState({ selectedPermissions: this.getRequestedMethodState(newMethodNames), From b4339f6cbfe70d292b4d22e76b45102816e9f49f Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 16:58:08 -0330 Subject: [PATCH 208/689] Move devDeps into devDeps (#7936) --- package.json | 4 ++-- yarn.lock | 64 ++++++++++++++++------------------------------------ 2 files changed, 21 insertions(+), 47 deletions(-) diff --git a/package.json b/package.json index 5db38a20e..64bcd0ddb 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,6 @@ "bignumber.js": "^4.1.0", "bip39": "^2.2.0", "bn.js": "^4.11.7", - "browserify-derequire": "^0.9.4", "c3": "^0.7.10", "classnames": "^2.2.6", "content-hash": "^2.5.0", @@ -167,7 +166,6 @@ "safe-event-emitter": "^1.0.1", "safe-json-stringify": "^1.2.0", "single-call-balance-checker-abi": "^1.0.0", - "string.prototype.matchall": "^3.0.1", "swappable-obj-proxy": "^1.1.0", "textarea-caret": "^3.0.1", "valid-url": "^1.0.9", @@ -196,6 +194,7 @@ "babelify": "^10.0.0", "brfs": "^1.6.1", "browserify": "^16.2.3", + "browserify-derequire": "^1.0.1", "browserify-transform-tools": "^1.7.0", "chai": "^4.1.0", "chalk": "^2.4.2", @@ -283,6 +282,7 @@ "sinon": "^5.0.0", "source-map": "^0.7.2", "source-map-explorer": "^2.0.1", + "string.prototype.matchall": "^4.0.2", "style-loader": "^0.21.0", "stylelint": "^9.10.1", "stylelint-config-standard": "^18.2.0", diff --git a/yarn.lock b/yarn.lock index f59b88aa7..ee678bf8e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6065,13 +6065,13 @@ browserify-cipher@^1.0.0: browserify-des "^1.0.0" evp_bytestokey "^1.0.0" -browserify-derequire@^0.9.4: - version "0.9.4" - resolved "https://registry.yarnpkg.com/browserify-derequire/-/browserify-derequire-0.9.4.tgz#64d61e56cfdff0b8f174fd8c57f8b4033e287895" - integrity sha1-ZNYeVs/f8LjxdP2MV/i0Az4oeJU= +browserify-derequire@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-derequire/-/browserify-derequire-1.0.1.tgz#6c7cdb228ccf21226e9a1d203a16be9da5afd253" + integrity sha512-UYKzp7fjiwq2+zj4IgS9lLUhNIdO3I4k+xEAAs5a6i3aQC3E+3gMYq9bDfyckojxNKCPnWxFWjJS4gGcxTXhUw== dependencies: - derequire "^2.0.0" - through2 "^1.1.1" + derequire "2.0.6" + through2 "3.0.1" browserify-des@^1.0.0: version "1.0.0" @@ -8947,7 +8947,7 @@ deps-sort@^2.0.0: subarg "^1.0.0" through2 "^2.0.0" -derequire@^2.0.0: +derequire@2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/derequire/-/derequire-2.0.6.tgz#31a414bb7ca176239fa78b116636ef77d517e768" integrity sha1-MaQUu3yhdiOfp4sRZjbvd9UX52g= @@ -24116,7 +24116,7 @@ read-pkg@^4.0.1: string_decoder "~1.0.3" util-deprecate "~1.0.1" -readable-stream@1.1, readable-stream@1.1.x, "readable-stream@>=1.1.13-1 <1.2.0-0", readable-stream@^1.0.33, readable-stream@~1.1.9: +readable-stream@1.1, readable-stream@1.1.x, readable-stream@^1.0.33, readable-stream@~1.1.9: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= @@ -24430,13 +24430,6 @@ regexp-tree@^0.1.6: resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.10.tgz#d837816a039c7af8a8d64d7a7c3cf6a1d93450bc" integrity sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ== -regexp.prototype.flags@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz#6b30724e306a27833eeb171b66ac8890ba37e41c" - integrity sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA== - dependencies: - define-properties "^1.1.2" - regexp.prototype.flags@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" @@ -26833,18 +26826,7 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -string.prototype.matchall@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-3.0.1.tgz#5a9e0b64bcbeb336aa4814820237c2006985646d" - integrity sha512-NSiU0ILQr9PQ1SZmM1X327U5LsM+KfDTassJfqN1al1+0iNpKzmQ4BfXOJwRnTEqv8nKJ67mFpqRoPaGWwvy5A== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.12.0" - function-bind "^1.1.1" - has-symbols "^1.0.0" - regexp.prototype.flags "^1.2.0" - -"string.prototype.matchall@^4.0.0 || ^3.0.1": +"string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz#48bb510326fb9fdeb6a33ceaa81a6ea04ef7648e" integrity sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg== @@ -27846,13 +27828,12 @@ through2@2.X, through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0.0 readable-stream "^2.1.5" xtend "~4.0.1" -through2@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/through2/-/through2-1.1.1.tgz#0847cbc4449f3405574dbdccd9bb841b83ac3545" - integrity sha1-CEfLxESfNAVXTb3M2buEG4OsNUU= +through2@3.0.1, through2@^3.0.0, through2@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" + integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww== dependencies: - readable-stream ">=1.1.13-1 <1.2.0-0" - xtend ">=4.0.0 <4.1.0-0" + readable-stream "2 || 3" through2@^2.0.2, through2@^2.0.5: version "2.0.5" @@ -27862,13 +27843,6 @@ through2@^2.0.2, through2@^2.0.5: readable-stream "~2.3.6" xtend "~4.0.1" -through2@^3.0.0, through2@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" - integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww== - dependencies: - readable-stream "2 || 3" - through2@~0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/through2/-/through2-0.2.3.tgz#eb3284da4ea311b6cc8ace3653748a52abf25a3f" @@ -30104,16 +30078,16 @@ xregexp@2.0.0: resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM= -"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.1, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= - xtend@^4.0.0, xtend@~4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +xtend@^4.0.1, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= + xtend@~2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" From fe83376b9f09200297bbf4058c07402fa2e2663d Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 17:11:28 -0330 Subject: [PATCH 209/689] Remove unused number-to-bn package (#7937) --- package.json | 1 - yarn.lock | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 64bcd0ddb..fdf698a7d 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,6 @@ "multihashes": "^0.4.12", "nanoid": "^2.1.6", "nonce-tracker": "^1.0.0", - "number-to-bn": "^1.7.0", "obj-multiplex": "^1.0.0", "obs-store": "^4.0.3", "percentile": "^1.2.0", diff --git a/yarn.lock b/yarn.lock index ee678bf8e..6e4eb7c95 100644 --- a/yarn.lock +++ b/yarn.lock @@ -20758,7 +20758,7 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= -number-to-bn@1.7.0, number-to-bn@^1.7.0: +number-to-bn@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= From cbfe5484d8f895fe17b01954f21680d81278f1cf Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 29 Jan 2020 17:03:49 -0400 Subject: [PATCH 210/689] Add Sentry environment (#7923) Any error sent to Sentry will now be marked with the environment they were sent from. The environment is set at build time, and is set dependant upon the build flags and CI-related environment variables. Setting the environment will let us filter error reports in Sentry to focus specifically upon reports sent from production, release candidates, PR testing, or whatever else. --- app/scripts/lib/setupSentry.js | 8 +++++--- gulpfile.js | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index f52258519..18c3507ea 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -1,9 +1,10 @@ import * as Sentry from '@sentry/browser' import { Dedupe, ExtraErrorData } from '@sentry/integrations' -const METAMASK_DEBUG = process.env.METAMASK_DEBUG import extractEthjsErrorMessage from './extractEthjsErrorMessage' +const METAMASK_DEBUG = process.env.METAMASK_DEBUG +const METAMASK_ENVIRONMENT = process.env.METAMASK_ENVIRONMENT const SENTRY_DSN_PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505' const SENTRY_DSN_DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496' @@ -17,16 +18,17 @@ function setupSentry (opts) { const isBrave = Boolean(window.chrome.ipcRenderer) if (METAMASK_DEBUG || process.env.IN_TEST) { - console.log('Setting up Sentry Remote Error Reporting: SENTRY_DSN_DEV') + console.log(`Setting up Sentry Remote Error Reporting for '${METAMASK_ENVIRONMENT}': SENTRY_DSN_DEV`) sentryTarget = SENTRY_DSN_DEV } else { - console.log('Setting up Sentry Remote Error Reporting: SENTRY_DSN_PROD') + console.log(`Setting up Sentry Remote Error Reporting for '${METAMASK_ENVIRONMENT}': SENTRY_DSN_PROD`) sentryTarget = SENTRY_DSN_PROD } Sentry.init({ dsn: sentryTarget, debug: METAMASK_DEBUG, + environment: METAMASK_ENVIRONMENT, integrations: [ new Dedupe(), new ExtraErrorData(), diff --git a/gulpfile.js b/gulpfile.js index 8dbcf9d1d..bfefb70cb 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -571,9 +571,27 @@ function generateBundler (opts, performBundle) { bundler = bundler.external(opts.externalDependencies) } + let environment + if (opts.devMode) { + environment = 'development' + } else if (opts.testing) { + environment = 'testing' + } else if (process.env.CIRCLE_BRANCH === 'master') { + environment = 'production' + } else if (/^Version-v(\d+)[.](\d+)[.](\d+)/.test(process.env.CIRCLE_BRANCH)) { + environment = 'release-candidate' + } else if (process.env.CIRCLE_BRANCH === 'develop') { + environment = 'staging' + } else if (process.env.CIRCLE_PULL_REQUEST) { + environment = 'pull-request' + } else { + environment = 'other' + } + // Inject variables into bundle bundler.transform(envify({ METAMASK_DEBUG: opts.devMode, + METAMASK_ENVIRONMENT: environment, NODE_ENV: opts.devMode ? 'development' : 'production', IN_TEST: opts.testing, PUBNUB_SUB_KEY: process.env.PUBNUB_SUB_KEY || '', From 442892678485e90a0d50523e5dfbe05d9d7902fb Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 17:47:34 -0330 Subject: [PATCH 211/689] Move polyfill-crypto.getrandomvalues to devDeps (#7938) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fdf698a7d..c22e2985c 100644 --- a/package.json +++ b/package.json @@ -131,7 +131,6 @@ "obs-store": "^4.0.3", "percentile": "^1.2.0", "pify": "^3.0.0", - "polyfill-crypto.getrandomvalues": "^1.0.0", "post-message-stream": "^3.0.0", "promise-to-callback": "^1.0.0", "prop-types": "^15.6.1", @@ -261,6 +260,7 @@ "node-sass": "^4.12.0", "nyc": "^13.0.0", "path": "^0.12.7", + "polyfill-crypto.getrandomvalues": "^1.0.0", "proxyquire": "2.0.1", "qs": "^6.2.0", "qunitjs": "^2.4.1", From e380c6fc6ca0461c75d867dba5dc04eff2acfd5c Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 17:47:47 -0330 Subject: [PATCH 212/689] Remove unused fs-extra and fs-promise devDependencies (#7939) --- package.json | 2 -- yarn.lock | 45 ++------------------------------------------- 2 files changed, 2 insertions(+), 45 deletions(-) diff --git a/package.json b/package.json index c22e2985c..4ddd83169 100644 --- a/package.json +++ b/package.json @@ -215,8 +215,6 @@ "eslint-plugin-react": "^7.4.0", "fetch-mock": "^6.5.2", "file-loader": "^1.1.11", - "fs-extra": "^6.0.1", - "fs-promise": "^2.0.3", "ganache-cli": "^6.4.4", "ganache-core": "2.8.0", "geckodriver": "^1.19.1", diff --git a/yarn.lock b/yarn.lock index 6e4eb7c95..115723c7e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3852,7 +3852,7 @@ ansi-wrap@0.1.0, ansi-wrap@^0.1.0: resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= -any-promise@1.3.0, any-promise@^1.0.0, any-promise@^1.1.0, any-promise@^1.3.0: +any-promise@1.3.0, any-promise@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= @@ -12581,7 +12581,7 @@ fs-exists-sync@^0.1.0: resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" integrity sha1-mC1ok6+RjnLQjeyehnP/K1qNat0= -fs-extra@6.0.1, fs-extra@^6.0.1: +fs-extra@6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" integrity sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA== @@ -12610,14 +12610,6 @@ fs-extra@^1.0.0: jsonfile "^2.1.0" klaw "^1.0.0" -fs-extra@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" - integrity sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU= - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - fs-extra@^4.0.1, fs-extra@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" @@ -12667,16 +12659,6 @@ fs-mkdirp-stream@^1.0.0: graceful-fs "^4.1.11" through2 "^2.0.3" -fs-promise@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-2.0.3.tgz#f64e4f854bcf689aa8bddcba268916db3db46854" - integrity sha1-9k5PhUvPaJqovdy6JokW2z20aFQ= - dependencies: - any-promise "^1.3.0" - fs-extra "^2.0.0" - mz "^2.6.0" - thenify-all "^1.6.0" - fs-write-stream-atomic@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" @@ -20126,15 +20108,6 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -mz@^2.6.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" - integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== - dependencies: - any-promise "^1.0.0" - object-assign "^4.0.1" - thenify-all "^1.0.0" - nan@2.13.2: version "2.13.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" @@ -27771,20 +27744,6 @@ theming@^1.3.0: is-plain-object "^2.0.1" prop-types "^15.5.8" -thenify-all@^1.0.0, thenify-all@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" - integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= - dependencies: - thenify ">= 3.1.0 < 4" - -"thenify@>= 3.1.0 < 4": - version "3.3.0" - resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" - integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= - dependencies: - any-promise "^1.0.0" - throat@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" From 3b187eff43db4e90c15beb12ad27b0d4d20495b2 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 20:00:42 -0330 Subject: [PATCH 213/689] Remove unused rimraf devDependency (#7940) --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 4ddd83169..6a7cb2e2b 100644 --- a/package.json +++ b/package.json @@ -270,7 +270,6 @@ "remote-redux-devtools": "^0.5.16", "remotedev-server": "^0.3.1", "resolve-url-loader": "^2.3.0", - "rimraf": "^2.6.2", "sass-loader": "^7.0.1", "selenium-webdriver": "^4.0.0-alpha.5", "serve-handler": "^6.1.2", From 472d8c31604bdce3681937637780191f8e7f72df Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 21:24:08 -0330 Subject: [PATCH 214/689] Remove unnecessary 'path' dependency (#7942) --- package.json | 1 - yarn.lock | 12 ++---------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 6a7cb2e2b..59e84c1ac 100644 --- a/package.json +++ b/package.json @@ -257,7 +257,6 @@ "node-fetch": "^2.6.0", "node-sass": "^4.12.0", "nyc": "^13.0.0", - "path": "^0.12.7", "polyfill-crypto.getrandomvalues": "^1.0.0", "proxyquire": "2.0.1", "qs": "^6.2.0", diff --git a/yarn.lock b/yarn.lock index 115723c7e..9f894cb3e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21932,14 +21932,6 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -path@^0.12.7: - version "0.12.7" - resolved "https://registry.yarnpkg.com/path/-/path-0.12.7.tgz#d4dc2a506c4ce2197eb481ebfcd5b36c0140b10f" - integrity sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8= - dependencies: - process "^0.11.1" - util "^0.10.3" - pathval@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" @@ -22687,7 +22679,7 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -process@^0.11.1, process@^0.11.10, process@~0.11.0: +process@^0.11.10, process@~0.11.0: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= @@ -28845,7 +28837,7 @@ util.promisify@^1.0.0: has-symbols "^1.0.1" object.getownpropertydescriptors "^2.1.0" -util@0.10.3, util@^0.10.3, util@~0.10.1: +util@0.10.3, util@~0.10.1: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= From ee415058ccb3c78f480611343402f2a0b331381f Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 29 Jan 2020 20:57:14 -0400 Subject: [PATCH 215/689] Only resolve ENS on mainnet (#7944) The ENS resolver will now bail on any network other than mainnet. --- app/scripts/background.js | 1 + app/scripts/lib/ens-ipfs/setup.js | 5 +++-- app/scripts/metamask-controller.js | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/scripts/background.js b/app/scripts/background.js index bee63e711..774d04691 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -254,6 +254,7 @@ function setupController (initState, initLangCode) { }) setupEnsIpfsResolver({ + getCurrentNetwork: controller.getCurrentNetwork, getIpfsGateway: controller.preferencesController.getIpfsGateway.bind(controller.preferencesController), provider: controller.provider, }) diff --git a/app/scripts/lib/ens-ipfs/setup.js b/app/scripts/lib/ens-ipfs/setup.js index 3221cd62a..ee04b9340 100644 --- a/app/scripts/lib/ens-ipfs/setup.js +++ b/app/scripts/lib/ens-ipfs/setup.js @@ -6,7 +6,7 @@ const supportedTopLevelDomains = ['eth'] export default setupEnsIpfsResolver -function setupEnsIpfsResolver ({ provider, getIpfsGateway }) { +function setupEnsIpfsResolver ({ provider, getCurrentNetwork, getIpfsGateway }) { // install listener const urlPatterns = supportedTopLevelDomains.map(tld => `*://*.${tld}/*`) @@ -23,7 +23,8 @@ function setupEnsIpfsResolver ({ provider, getIpfsGateway }) { async function webRequestDidFail (details) { const { tabId, url } = details // ignore requests that are not associated with tabs - if (tabId === -1) { + // only attempt ENS resolution on mainnet + if (tabId === -1 || getCurrentNetwork() !== '1') { return } // parse ens name diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 5bbc54ccd..4fe9903ea 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -675,6 +675,10 @@ export default class MetamaskController extends EventEmitter { }) } + getCurrentNetwork = () => { + return this.networkController.store.getState().network + } + /** * Collects all the information that we want to share * with the mobile client for syncing purposes From 4ad49ffd68cc72fb54ac26a044ba3bb918f92c27 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 21:28:44 -0330 Subject: [PATCH 216/689] Remove unused mocha-eslint dependency (#7943) --- package.json | 1 - yarn.lock | 39 ++------------------------------------- 2 files changed, 2 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index 59e84c1ac..f15be0215 100644 --- a/package.json +++ b/package.json @@ -250,7 +250,6 @@ "koa": "^2.7.0", "lockfile-lint": "^3.0.5", "mocha": "^5.0.0", - "mocha-eslint": "^4.0.0", "mocha-jsdom": "^1.1.0", "mocha-sinon": "^2.0.0", "nock": "^9.0.14", diff --git a/yarn.lock b/yarn.lock index 9f894cb3e..c625e2cd7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6763,7 +6763,7 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4. escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: +chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= @@ -10368,7 +10368,7 @@ eslint@^3.7.1: text-table "~0.2.0" user-home "^2.0.0" -eslint@^4.0.0, eslint@^4.2.0: +eslint@^4.0.0: version "4.19.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" integrity sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ== @@ -13070,14 +13070,6 @@ gl-vec3@1.0.3: resolved "https://registry.yarnpkg.com/gl-vec3/-/gl-vec3-1.0.3.tgz#110fd897d0729f6398307381567d0944941bf22b" integrity sha1-EQ/Yl9Byn2OYMHOBVn0JRJQb8is= -glob-all@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-all/-/glob-all-3.1.0.tgz#8913ddfb5ee1ac7812656241b03d5217c64b02ab" - integrity sha1-iRPd+17hrHgSZWJBsD1SF8ZLAqs= - dependencies: - glob "^7.0.5" - yargs "~1.2.6" - glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" @@ -19650,11 +19642,6 @@ minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2 resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= -minimist@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.1.0.tgz#99df657a52574c21c9057497df742790b2b4c0de" - integrity sha1-md9lelJXTCHJBXSX33QnkLK0wN4= - minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" @@ -19764,16 +19751,6 @@ mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0 dependencies: minimist "0.0.8" -mocha-eslint@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/mocha-eslint/-/mocha-eslint-4.1.0.tgz#d08eba98665f7ce4ebef0d27c3a235409ebbb8ad" - integrity sha512-y+TIaoozAiuksnsr/7GVw7F2nAqotrZ06SHIw8wMR6PVWipXre5Hz59bsqLX1n2Lqu2YDebUX1A4qF/rtmWsYQ== - dependencies: - chalk "^1.1.0" - eslint "^4.2.0" - glob-all "^3.0.1" - replaceall "^0.1.6" - mocha-jsdom@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mocha-jsdom/-/mocha-jsdom-1.1.0.tgz#e1576fbd0601cc89d358a213a0e5585d1b7c7a01" @@ -24683,11 +24660,6 @@ replace-homedir@^1.0.0: is-absolute "^1.0.0" remove-trailing-separator "^1.1.0" -replaceall@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/replaceall/-/replaceall-0.1.6.tgz#81d81ac7aeb72d7f5c4942adf2697a3220688d8e" - integrity sha1-gdgax663LX9cSUKt8ml6MiBojY4= - replacestream@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/replacestream/-/replacestream-4.0.3.tgz#3ee5798092be364b1cdb1484308492cb3dff2f36" @@ -30287,13 +30259,6 @@ yargs@^7.0.0, yargs@^7.1.0: y18n "^3.2.1" yargs-parser "^5.0.0" -yargs@~1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-1.2.6.tgz#9c7b4a82fd5d595b2bf17ab6dcc43135432fe34b" - integrity sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s= - dependencies: - minimist "^0.1.0" - yauzl@2.10.0, yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" From 2f3f605521618682f8edae2dad373ca3c3a984f3 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 21:31:32 -0330 Subject: [PATCH 217/689] Inline isomorphic-fetch test helper (#7945) --- package.json | 1 - test/helper.js | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f15be0215..0f650db67 100644 --- a/package.json +++ b/package.json @@ -239,7 +239,6 @@ "gulp-watch": "^5.0.1", "gulp-zip": "^4.0.0", "http-server": "^0.11.1", - "isomorphic-fetch": "^2.2.1", "jsdom": "^11.2.0", "jsdom-global": "^3.0.2", "karma": "^4.1.0", diff --git a/test/helper.js b/test/helper.js index 7d0df1745..38cdb6bfd 100644 --- a/test/helper.js +++ b/test/helper.js @@ -42,7 +42,12 @@ global.log = log // // fetch -global.fetch = require('isomorphic-fetch') +const fetch = require('node-fetch') + +global.fetch = fetch +global.Response = fetch.Response +global.Headers = fetch.Headers +global.Request = fetch.Request require('abortcontroller-polyfill/dist/polyfill-patch-fetch') // dom From 555443787b8b0c06d7d6507815606c1601b095ef Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 22:05:47 -0330 Subject: [PATCH 218/689] Remove dead link to team page in README (#7946) --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index d2a029480..07c4fe7c7 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,6 @@ To write tests that will be run in the browser using QUnit, add your test files - [How to add custom build to Firefox](./docs/add-to-firefox.md) - [How to add a new translation to MetaMask](./docs/translating-guide.md) - [Publishing Guide](./docs/publishing.md) -- [The MetaMask Team](./docs/team.md) - [How to live reload on local dependency changes](./docs/developing-on-deps.md) - [How to add new networks to the Provider Menu](./docs/adding-new-networks.md) - [How to port MetaMask to a new platform](./docs/porting_to_new_environment.md) From ca9aaad911a1e638524005aab7f7c4bb971f8591 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 29 Jan 2020 22:36:52 -0330 Subject: [PATCH 219/689] Remove mocha-jsdom and mocha-sinon (#7947) --- package.json | 2 -- yarn.lock | 10 ---------- 2 files changed, 12 deletions(-) diff --git a/package.json b/package.json index 0f650db67..38e6af743 100644 --- a/package.json +++ b/package.json @@ -249,8 +249,6 @@ "koa": "^2.7.0", "lockfile-lint": "^3.0.5", "mocha": "^5.0.0", - "mocha-jsdom": "^1.1.0", - "mocha-sinon": "^2.0.0", "nock": "^9.0.14", "node-fetch": "^2.6.0", "node-sass": "^4.12.0", diff --git a/yarn.lock b/yarn.lock index c625e2cd7..71dfce829 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19751,16 +19751,6 @@ mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0 dependencies: minimist "0.0.8" -mocha-jsdom@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mocha-jsdom/-/mocha-jsdom-1.1.0.tgz#e1576fbd0601cc89d358a213a0e5585d1b7c7a01" - integrity sha1-4VdvvQYBzInTWKIToOVYXRt8egE= - -mocha-sinon@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mocha-sinon/-/mocha-sinon-2.0.0.tgz#723a9310e7d737d7b77c7a66821237425b032d48" - integrity sha1-cjqTEOfXN9e3fHpmghI3QlsDLUg= - mocha@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.0.0.tgz#cccac988b0bc5477119cba0e43de7af6d6ad8f4e" From 7710286472d04a1077b1309566c0b1e3f7a25dd4 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 30 Jan 2020 10:28:56 -0330 Subject: [PATCH 220/689] Explicitly set Sass compiler for gulp-sass (#7948) As per the gulp-sass docs [1] we should be setting the `sass.compiler` property for forwards-compatibility "in case the default ever changes." [1]:https://github.com/dlmanning/gulp-sass/tree/v4.0.2#basic-usage --- gulpfile.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gulpfile.js b/gulpfile.js index bfefb70cb..79b725557 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -29,6 +29,8 @@ const { makeStringTransform } = require('browserify-transform-tools') const packageJSON = require('./package.json') +sass.compiler = require('node-sass') + const dependencies = Object.keys(packageJSON && packageJSON.dependencies || {}) const materialUIDependencies = ['@material-ui/core'] const reactDepenendencies = dependencies.filter(dep => dep.match(/react/)) From 9a692d721d9ed2bd3a77818239b208b3bbe388ee Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 30 Jan 2020 10:29:16 -0330 Subject: [PATCH 221/689] ci: Update shellcheck version used in CI (#7951) --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1d17a5808..cd60aa0d0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -193,10 +193,10 @@ jobs: test-lint-shellcheck: docker: - - image: circleci/node:10.18-browsers + - image: koalaman/shellcheck-alpine:stable steps: - checkout - - run: sudo apt-get install shellcheck + - run: apk add --no-cache bash jq yarn - run: name: Shellcheck Lint command: yarn lint:shellcheck From 739b5dfe72dad93f97603a22e61632a2ae872c84 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 30 Jan 2020 10:30:30 -0330 Subject: [PATCH 222/689] Move issue template and contributing doc to .github (#7952) --- CONTRIBUTING.md => .github/CONTRIBUTING.md | 0 ISSUE_TEMPLATE => .github/ISSUE_TEMPLATE.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename CONTRIBUTING.md => .github/CONTRIBUTING.md (100%) rename ISSUE_TEMPLATE => .github/ISSUE_TEMPLATE.md (100%) diff --git a/CONTRIBUTING.md b/.github/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to .github/CONTRIBUTING.md diff --git a/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE.md similarity index 100% rename from ISSUE_TEMPLATE rename to .github/ISSUE_TEMPLATE.md From 0001b49cdf9c3219e9a082713fb89e37382ec8f5 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 30 Jan 2020 10:50:20 -0330 Subject: [PATCH 223/689] Remove gulp-eslint and gulp-util dependency (#7949) --- gulpfile.js | 4 +- package.json | 5 +- yarn.lock | 419 ++++++++++----------------------------------------- 3 files changed, 84 insertions(+), 344 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 79b725557..fb37c457b 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -5,7 +5,7 @@ const envify = require('envify/custom') const gulp = require('gulp') const source = require('vinyl-source-stream') const buffer = require('vinyl-buffer') -const gutil = require('gulp-util') +const log = require('fancy-log') const watch = require('gulp-watch') const sourcemaps = require('gulp-sourcemaps') const jsoneditor = require('gulp-json-editor') @@ -626,7 +626,7 @@ function bundleTask (opts) { if (!bundler) { bundler = generateBundler(opts, performBundle) // output build logs to terminal - bundler.on('log', gutil.log) + bundler.on('log', log) } let buildStream = bundler.bundle() diff --git a/package.json b/package.json index 38e6af743..348b8e1ff 100644 --- a/package.json +++ b/package.json @@ -213,6 +213,7 @@ "eslint-plugin-json": "^1.2.0", "eslint-plugin-mocha": "^5.0.0", "eslint-plugin-react": "^7.4.0", + "fancy-log": "^1.3.3", "fetch-mock": "^6.5.2", "file-loader": "^1.1.11", "ganache-cli": "^6.4.4", @@ -223,9 +224,8 @@ "gulp-autoprefixer": "^5.0.0", "gulp-babel": "^7.0.0", "gulp-debug": "^3.2.0", - "gulp-eslint": "^4.0.0", "gulp-imagemin": "^6.1.0", - "gulp-json-editor": "^2.2.1", + "gulp-json-editor": "^2.5.4", "gulp-livereload": "4.0.0", "gulp-multi-process": "^1.3.1", "gulp-rename": "^1.4.0", @@ -235,7 +235,6 @@ "gulp-sourcemaps": "^2.6.0", "gulp-stylelint": "^7.0.0", "gulp-terser-js": "^5.0.0", - "gulp-util": "^3.0.7", "gulp-watch": "^5.0.1", "gulp-zip": "^4.0.0", "http-server": "^0.11.1", diff --git a/yarn.lock b/yarn.lock index 71dfce829..9a3583c26 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3422,7 +3422,7 @@ acorn@^4.0.3: resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= -acorn@^5.5.0, acorn@^5.5.3: +acorn@^5.5.3: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== @@ -3623,11 +3623,6 @@ ajv-keywords@^1.0.0: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" integrity sha1-MU3QpLM2j609/NxU7eYXG4htrzw= -ajv-keywords@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" - integrity sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I= - ajv-keywords@^3.1.0: version "3.4.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.0.tgz#4b831e7b531415a7cc518cd404e73f6193c6349d" @@ -3664,7 +3659,7 @@ ajv@^4.7.0: co "^4.6.0" json-stable-stringify "^1.0.1" -ajv@^5.1.0, ajv@^5.2.3, ajv@^5.3.0: +ajv@^5.1.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= @@ -4049,11 +4044,6 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= - array-each@^1.0.0, array-each@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" @@ -4153,7 +4143,7 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array-uniq@^1.0.1, array-uniq@^1.0.2: +array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= @@ -5563,11 +5553,6 @@ bech32@^1.1.2: resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.3.tgz#bd47a8986bbb3eec34a56a097a84b8d3e9a2dfcd" integrity sha512-yuVFUvrNcoJi0sv5phmqc6P+Fl1HjRDRNOOkHY2X/3LBy2bIGNSFx4fZ95HMaXHupuS7cZR15AsvtmCIF4UEyg== -beeper@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" - integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak= - better-assert@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" @@ -7491,7 +7476,7 @@ concurrently@^4.1.1: tree-kill "^1.1.0" yargs "^12.0.1" -config-chain@^1.1.11: +config-chain@^1.1.11, config-chain@^1.1.12: version "1.1.12" resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== @@ -7499,14 +7484,6 @@ config-chain@^1.1.11: ini "^1.3.4" proto-list "~1.2.1" -config-chain@~1.1.5: - version "1.1.11" - resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2" - integrity sha1-q6CXR9++TD5w52am5BWG4YWfxvI= - dependencies: - ini "^1.3.4" - proto-list "~1.2.1" - configstore@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f" @@ -8525,11 +8502,6 @@ date-now@^0.1.4: resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= -dateformat@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" - integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI= - dateformat@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" @@ -8735,10 +8707,10 @@ deepmerge@^2.0.1: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170" integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA== -deepmerge@~0.2.7: - version "0.2.10" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-0.2.10.tgz#8906bf9e525a4fbf1b203b2afcb4640249821219" - integrity sha1-iQa/nlJaT78bIDsq/LRkAkmCEhk= +deepmerge@^4.2.1: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== default-compare@^1.0.0: version "1.0.0" @@ -8983,15 +8955,6 @@ detect-file@^1.0.0: resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= -detect-indent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-2.0.0.tgz#720ff51e4d97b76884f6bf57292348b13dfde939" - integrity sha1-cg/1Hk2Xt2iE9r9XKSNIsT396Tk= - dependencies: - get-stdin "^3.0.0" - minimist "^1.1.0" - repeating "^1.1.0" - detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" @@ -8999,6 +8962,11 @@ detect-indent@^4.0.0: dependencies: repeating "^2.0.0" +detect-indent@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd" + integrity sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA== + detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" @@ -9234,13 +9202,6 @@ doctrine@^2.0.0: dependencies: esutils "^2.0.2" -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -9440,13 +9401,6 @@ drbg.js@^1.0.1: create-hash "^1.1.2" create-hmac "^1.1.4" -duplexer2@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" - integrity sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds= - dependencies: - readable-stream "~1.1.9" - duplexer2@^0.1.2, duplexer2@^0.1.4, duplexer2@~0.1.0, duplexer2@~0.1.2, duplexer2@~0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" @@ -9507,6 +9461,16 @@ ecstatic@^3.0.0: minimist "^1.1.0" url-join "^2.0.5" +editorconfig@^0.15.3: + version "0.15.3" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" + integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g== + dependencies: + commander "^2.19.0" + lru-cache "^4.1.5" + semver "^5.6.0" + sigmund "^1.0.1" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -10257,7 +10221,7 @@ eslint-rule-composer@^0.3.0: resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== -eslint-scope@3.7.1, eslint-scope@^3.7.1: +eslint-scope@3.7.1: version "3.7.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" integrity sha1-PWPD7f2gLgbgGkUq2IyqzHzctug= @@ -10368,50 +10332,6 @@ eslint@^3.7.1: text-table "~0.2.0" user-home "^2.0.0" -eslint@^4.0.0: - version "4.19.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" - integrity sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ== - dependencies: - ajv "^5.3.0" - babel-code-frame "^6.22.0" - chalk "^2.1.0" - concat-stream "^1.6.0" - cross-spawn "^5.1.0" - debug "^3.1.0" - doctrine "^2.1.0" - eslint-scope "^3.7.1" - eslint-visitor-keys "^1.0.0" - espree "^3.5.4" - esquery "^1.0.0" - esutils "^2.0.2" - file-entry-cache "^2.0.0" - functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.0.1" - ignore "^3.3.3" - imurmurhash "^0.1.4" - inquirer "^3.0.6" - is-resolvable "^1.0.0" - js-yaml "^3.9.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.4" - minimatch "^3.0.2" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" - pluralize "^7.0.0" - progress "^2.0.0" - regexpp "^1.0.1" - require-uncached "^1.0.3" - semver "^5.3.0" - strip-ansi "^4.0.0" - strip-json-comments "~2.0.1" - table "4.0.2" - text-table "~0.2.0" - eslint@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.0.1.tgz#4a32181d72cb999d6f54151df7d337131f81cda7" @@ -10471,14 +10391,6 @@ espree@^3.4.0: acorn "^5.2.1" acorn-jsx "^3.0.0" -espree@^3.5.4: - version "3.5.4" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" - integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== - dependencies: - acorn "^5.5.0" - acorn-jsx "^3.0.0" - espree@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" @@ -11722,7 +11634,7 @@ extensionizer@^1.0.1: resolved "https://registry.yarnpkg.com/extensionizer/-/extensionizer-1.0.1.tgz#504544239a7610ba8404b15c1832091a37768d09" integrity sha512-UES5CSOYqshNsWFrpORcQR47+ph6UvQK25mguD44IyeMemt40CG+LTZrH1PgpGUHX3w7ACtNQnmM0J+qEe8G0Q== -external-editor@^2.0.4, external-editor@^2.1.0: +external-editor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.1.0.tgz#3d026a21b7f95b5726387d4200ac160d372c3b48" integrity sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA== @@ -11808,7 +11720,7 @@ falafel@^2.0.0, falafel@^2.1.0: isarray "0.0.1" object-keys "^1.0.6" -fancy-log@1.3.2, fancy-log@^1.1.0, fancy-log@^1.3.2: +fancy-log@1.3.2, fancy-log@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" integrity sha1-9BEl49hPLn2JpD0G2VjI94vha+E= @@ -11817,6 +11729,16 @@ fancy-log@1.3.2, fancy-log@^1.1.0, fancy-log@^1.3.2: color-support "^1.1.3" time-stamp "^1.0.0" +fancy-log@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" + integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== + dependencies: + ansi-gray "^0.1.1" + color-support "^1.1.3" + parse-node-version "^1.0.0" + time-stamp "^1.0.0" + fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" @@ -12956,11 +12878,6 @@ get-proxy@^2.0.0: dependencies: npm-conf "^1.1.0" -get-stdin@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-3.0.2.tgz#c1ced24b9039b38ded85bdf161e57713b6dd4abe" - integrity sha1-wc7SS5A5s43thb3xYeV3E7bdSr4= - get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" @@ -13250,7 +13167,7 @@ global@^4.4.0: min-document "^2.19.0" process "^0.11.10" -globals@^11.0.1, globals@^11.1.0, globals@^11.7.0: +globals@^11.1.0, globals@^11.7.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== @@ -13600,14 +13517,6 @@ gulp-debug@^3.2.0: through2 "^2.0.0" tildify "^1.1.2" -gulp-eslint@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/gulp-eslint/-/gulp-eslint-4.0.0.tgz#16d9ea4d696e7b7a9d65eeb1aa5bc4ba0a22c7f7" - integrity sha512-+qsePo04v1O3JshpNvww9+bOgZEJ6Cc2/w3mEktfKz0NL0zsh1SWzjyIL2FIM2zzy6IYQYv+j8REZORF8dKX4g== - dependencies: - eslint "^4.0.0" - gulp-util "^3.0.8" - gulp-imagemin@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/gulp-imagemin/-/gulp-imagemin-6.1.0.tgz#d1f1cb17b930da6424c1994388bada2355bc4295" @@ -13626,16 +13535,16 @@ gulp-imagemin@^6.1.0: imagemin-optipng "^7.0.0" imagemin-svgo "^7.0.0" -gulp-json-editor@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/gulp-json-editor/-/gulp-json-editor-2.2.1.tgz#7c4dd7477e8d06dc5dc49c0b81e745cdb04f97bb" - integrity sha1-fE3XR36NBtxdxJwLgedFzbBPl7s= +gulp-json-editor@^2.5.4: + version "2.5.4" + resolved "https://registry.yarnpkg.com/gulp-json-editor/-/gulp-json-editor-2.5.4.tgz#b77b46bca22d2dd1ac9f15bbec1eddbe5ef3567c" + integrity sha512-3IdMYsSACfLFYipet9Rmpag7PEU059KnR6TWgfuAfz+ftyzN8yaEvf9vXAD5b9K9v711Ymcpqe6vWGQYfQJ/uQ== dependencies: - deepmerge "~0.2.7" - detect-indent "^2.0.0" - gulp-util "~3.0.0" - js-beautify "~1.5.4" - through2 "~0.5.0" + deepmerge "^4.2.1" + detect-indent "^6.0.0" + js-beautify "^1.10.2" + plugin-error "^1.0.1" + through2 "^3.0.1" gulp-livereload@4.0.0: version "4.0.0" @@ -13738,30 +13647,6 @@ gulp-terser-js@^5.0.0: through2 "^3.0.1" vinyl-sourcemaps-apply "^0.2.1" -gulp-util@^3.0.7, gulp-util@^3.0.8, gulp-util@~3.0.0: - version "3.0.8" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" - integrity sha1-AFTh50RQLifATBh8PsxQXdVLu08= - dependencies: - array-differ "^1.0.0" - array-uniq "^1.0.2" - beeper "^1.0.0" - chalk "^1.0.0" - dateformat "^2.0.0" - fancy-log "^1.1.0" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash._reescape "^3.0.0" - lodash._reevaluate "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.template "^3.0.0" - minimist "^1.1.0" - multipipe "^0.1.2" - object-assign "^3.0.0" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl "^0.5.0" - gulp-watch@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/gulp-watch/-/gulp-watch-5.0.1.tgz#83d378752f5bfb46da023e73c17ed1da7066215d" @@ -13904,13 +13789,6 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-gulplog@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" - integrity sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4= - dependencies: - sparkles "^1.0.0" - has-localstorage@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-localstorage/-/has-localstorage-1.0.1.tgz#fe62406c4767fbd6d784dac6905928108b82971b" @@ -14493,7 +14371,7 @@ ignore-walk@^3.0.1: dependencies: minimatch "^3.0.4" -ignore@^3.2.0, ignore@^3.3.3, ignore@^3.3.5: +ignore@^3.2.0, ignore@^3.3.5: version "3.3.7" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" integrity sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA== @@ -14767,26 +14645,6 @@ inquirer@^0.12.0: strip-ansi "^3.0.0" through "^2.3.6" -inquirer@^3.0.6: - version "3.3.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" - integrity sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ== - dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.4" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx-lite "^4.0.8" - rx-lite-aggregates "^4.0.8" - string-width "^2.1.0" - strip-ansi "^4.0.0" - through "^2.3.6" - inquirer@^6.2.2: version "6.3.1" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.3.1.tgz#7a413b5e7950811013a3db491c61d1f3b776e8e7" @@ -16771,14 +16629,16 @@ js-base64@^2.1.8: resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.3.tgz#2e545ec2b0f2957f41356510205214e98fad6582" integrity sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw== -js-beautify@~1.5.4: - version "1.5.10" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.5.10.tgz#4d95371702699344a516ca26bf59f0a27bb75719" - integrity sha1-TZU3FwJpk0SlFsomv1nwonu3Vxk= +js-beautify@^1.10.2: + version "1.10.3" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.3.tgz#c73fa10cf69d3dfa52d8ed624f23c64c0a6a94c1" + integrity sha512-wfk/IAWobz1TfApSdivH5PJ0miIHgDoYb1ugSqHcODPmaYu46rYe5FVuIEkhjg8IQiv6rDNPyhsqbsohI/C2vQ== dependencies: - config-chain "~1.1.5" - mkdirp "~0.5.0" - nopt "~3.0.1" + config-chain "^1.1.12" + editorconfig "^0.15.3" + glob "^7.1.3" + mkdirp "~0.5.1" + nopt "~4.0.1" js-levenshtein@^1.1.3: version "1.1.6" @@ -16830,7 +16690,7 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.2.5, js-yaml@^3.2.7, js-yaml@^3.5.1, js-yaml@^3.6.1, js-yaml@^3.9.0, js-yaml@^3.9.1: +js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.2.5, js-yaml@^3.2.7, js-yaml@^3.5.1, js-yaml@^3.6.1, js-yaml@^3.9.0: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -18502,16 +18362,6 @@ lodash._baseflatten@^3.0.0: lodash.isarguments "^3.0.0" lodash.isarray "^3.0.0" -lodash._basetostring@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - integrity sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U= - -lodash._basevalues@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" - integrity sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc= - lodash._bindcallback@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" @@ -18536,26 +18386,6 @@ lodash._isiterateecall@^3.0.0: resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= -lodash._reescape@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" - integrity sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo= - -lodash._reevaluate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" - integrity sha1-WLx0xAZklTrgsSTYBpltrKQx4u0= - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= - lodash.assign@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-3.2.0.tgz#3ce9f0234b4b2223e296b8fa0ac1fee8ebca64fa" @@ -18610,13 +18440,6 @@ lodash.defaults@^4.0.0: resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= -lodash.escape@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" - integrity sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg= - dependencies: - lodash._root "^3.0.0" - lodash.escape@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98" @@ -18759,29 +18582,6 @@ lodash.tail@^4.1.1: resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" integrity sha1-0jM6NtnncXyK0vfKyv7HwytERmQ= -lodash.template@^3.0.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" - integrity sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8= - dependencies: - lodash._basecopy "^3.0.0" - lodash._basetostring "^3.0.0" - lodash._basevalues "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.keys "^3.0.0" - lodash.restparam "^3.0.0" - lodash.templatesettings "^3.0.0" - -lodash.templatesettings@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" - integrity sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU= - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.throttle@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" @@ -18958,6 +18758,14 @@ lru-cache@^3.2.0: dependencies: pseudomap "^1.0.1" +lru-cache@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -19744,7 +19552,7 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -20008,13 +19816,6 @@ multihashing-async@~0.7.0: multihashes "~0.4.13" murmurhash3js-revisited "^3.0.0" -multipipe@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" - integrity sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s= - dependencies: - duplexer2 "0.0.2" - multistream-select@~0.14.4: version "0.14.6" resolved "https://registry.yarnpkg.com/multistream-select/-/multistream-select-0.14.6.tgz#a3998eeb3fed83be2e8cd1eac5053825899f8d4b" @@ -20510,14 +20311,14 @@ nonce-tracker@^1.0.0: await-semaphore "^0.1.3" ethjs-query "^0.3.8" -"nopt@2 || 3", nopt@~3.0.1: +"nopt@2 || 3": version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= dependencies: abbrev "1" -nopt@^4.0.1: +nopt@^4.0.1, nopt@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= @@ -20776,11 +20577,6 @@ object-assign@^2.0.0: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-2.1.1.tgz#43c36e5d569ff8e4816c4efa8be02d26967c18aa" integrity sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo= -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= - object-component@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" @@ -21706,6 +21502,11 @@ parse-json@^5.0.0: json-parse-better-errors "^1.0.1" lines-and-columns "^1.1.6" +parse-node-version@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" + integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== + parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" @@ -22218,11 +22019,6 @@ pluralize@^1.2.1: resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" integrity sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU= -pluralize@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" - integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== - pn@^1.0.0, pn@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" @@ -24080,7 +23876,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.8, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@~1.0.15, readable-stream@~1.0.17: +readable-stream@~1.0.15: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= @@ -24370,11 +24166,6 @@ regexp.prototype.flags@^1.3.0: define-properties "^1.1.3" es-abstract "^1.17.0-next.1" -regexpp@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" - integrity sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw== - regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" @@ -24617,13 +24408,6 @@ repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= -repeating@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-1.1.3.tgz#3d4114218877537494f97f77f9785fab810fa4ac" - integrity sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw= - dependencies: - is-finite "^1.0.0" - repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" @@ -24770,7 +24554,7 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== -require-uncached@^1.0.2, require-uncached@^1.0.3: +require-uncached@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= @@ -25131,18 +24915,6 @@ rw@1: resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" integrity sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q= -rx-lite-aggregates@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" - integrity sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74= - dependencies: - rx-lite "*" - -rx-lite@*, rx-lite@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" - integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ= - rx-lite@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" @@ -25824,6 +25596,11 @@ side-channel@^1.0.2: es-abstract "^1.17.0-next.1" object-inspect "^1.7.0" +sigmund@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" @@ -25932,13 +25709,6 @@ slice-ansi@0.0.4: resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= -slice-ansi@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" - integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== - dependencies: - is-fullwidth-code-point "^2.0.0" - slice-ansi@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" @@ -27333,18 +27103,6 @@ syntax-error@^1.1.1: dependencies: acorn-node "^1.2.0" -table@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" - integrity sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA== - dependencies: - ajv "^5.2.3" - ajv-keywords "^2.1.0" - chalk "^2.1.0" - lodash "^4.17.4" - slice-ansi "1.0.0" - string-width "^2.1.1" - table@^3.7.8: version "3.8.3" resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" @@ -27764,14 +27522,6 @@ through2@~0.2.3: readable-stream "~1.1.9" xtend "~2.1.1" -through2@~0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.5.1.tgz#dfdd012eb9c700e2323fd334f38ac622ab372da7" - integrity sha1-390BLrnHAOIyP9M084rGIqs3Lac= - dependencies: - readable-stream "~1.0.17" - xtend "~3.0.0" - through@2, "through@>=2.2.7 <3", through@^2.3.6, through@^2.3.7, through@^2.3.8, through@~2.3, through@~2.3.1, through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -29028,15 +28778,6 @@ vinyl-sourcemaps-apply@^0.2.0, vinyl-sourcemaps-apply@^0.2.1: dependencies: source-map "^0.5.1" -vinyl@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" - integrity sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - vinyl@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" From 0159670214dfaa76977d368df1f69b9a480ca61b Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 30 Jan 2020 12:03:28 -0330 Subject: [PATCH 224/689] Update ENS registry addresses (#7954) --- app/scripts/lib/ens-ipfs/resolver.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/app/scripts/lib/ens-ipfs/resolver.js b/app/scripts/lib/ens-ipfs/resolver.js index b2719097a..06041b6c7 100644 --- a/app/scripts/lib/ens-ipfs/resolver.js +++ b/app/scripts/lib/ens-ipfs/resolver.js @@ -57,20 +57,22 @@ function hexValueIsEmpty (value) { return [undefined, null, '0x', '0x0', '0x0000000000000000000000000000000000000000000000000000000000000000'].includes(value) } +/** + * Returns the registry address for the given chain ID + * @param {number} chainId the chain ID + * @returns {string|null} the registry address if known, null otherwise + */ function getRegistryForChainId (chainId) { switch (chainId) { - // mainnet case 1: - return '0x314159265dd8dbb310642f98f50c066173c1259b' - // ropsten + // falls through case 3: - return '0x112234455c3a32fd11230c42e7bccd4a84e02010' - // rinkeby + // falls through case 4: - return '0xe7410170f87102df0055eb195163a03b7f2bff4a' - // goerli + // falls through case 5: - return '0x112234455c3a32fd11230c42e7bccd4a84e02010' + // Mainnet, Ropsten, Rinkeby, and Goerli, respectively, use the same address + return '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e' default: return null } From 490f9a5bf4169adc557f663b45d6bf0a6f85f46c Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 30 Jan 2020 12:03:47 -0330 Subject: [PATCH 225/689] Bump tree-kill version to fix high-severity vulnerability (#7956) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9a3583c26..bf2a45649 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27800,9 +27800,9 @@ traverse@~0.6.3: integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc= tree-kill@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.1.tgz#5398f374e2f292b9dcc7b2e71e30a5c3bb6c743a" - integrity sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q== + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== trezor-connect@^7.0.1: version "7.0.3" From 1dd30bd46bf6195c90d99f2b39205b1d0fd57b4c Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 30 Jan 2020 12:29:52 -0330 Subject: [PATCH 226/689] Bump node-sass to fix low-severity vulnerability (#7955) --- yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index bf2a45649..a8aae95ca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -20251,9 +20251,9 @@ node-releases@^1.1.46: semver "^6.3.0" node-sass@^4.12.0, node-sass@^4.8.3: - version "4.12.0" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.12.0.tgz#0914f531932380114a30cc5fa4fa63233a25f017" - integrity sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ== + version "4.13.1" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.13.1.tgz#9db5689696bb2eec2c32b98bfea4c7a2e992d0a3" + integrity sha512-TTWFx+ZhyDx1Biiez2nB0L3YrCZ/8oHagaDalbuBSlqXgUPsdkUSzJsVxeDO9LtPB49+Fh3WQl3slABo6AotNw== dependencies: async-foreach "^0.1.3" chalk "^1.1.1" @@ -20262,7 +20262,7 @@ node-sass@^4.12.0, node-sass@^4.8.3: get-stdin "^4.0.1" glob "^7.0.3" in-publish "^2.0.0" - lodash "^4.17.11" + lodash "^4.17.15" meow "^3.7.0" mkdirp "^0.5.1" nan "^2.13.2" From 608a1fc29822ef31ad55f70a7e88000708aec3c5 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 30 Jan 2020 14:11:26 -0330 Subject: [PATCH 227/689] Remove cross-env (#7950) --- package.json | 9 ++++----- test/env.js | 1 + yarn.lock | 10 +--------- 3 files changed, 6 insertions(+), 14 deletions(-) create mode 100644 test/env.js diff --git a/package.json b/package.json index 348b8e1ff..c02cb393e 100644 --- a/package.json +++ b/package.json @@ -16,9 +16,9 @@ "dapp-forwarder": "concurrently -k -n forwarder,dapp -p '[{time}][{name}]' 'yarn forwarder' 'yarn dapp'", "watch:test:unit": "nodemon --exec \"yarn test:unit\" ./test ./app ./ui", "sendwithprivatedapp": "node development/static-server.js test/e2e/send-eth-with-private-key-test --port 8080", - "test:unit": "cross-env METAMASK_ENV=test mocha --exit --require test/setup.js --recursive \"test/unit/**/*.js\" \"ui/app/**/*.test.js\"", - "test:unit:global": "cross-env METAMASK_ENV=test mocha --exit --require test/setup.js --recursive mocha test/unit-global/*", - "test:single": "cross-env METAMASK_ENV=test mocha --require test/helper.js", + "test:unit": "mocha --exit --require test/env.js --require test/setup.js --recursive \"test/unit/**/*.js\" \"ui/app/**/*.test.js\"", + "test:unit:global": "mocha --exit --require test/env.js --require test/setup.js --recursive mocha test/unit-global/*", + "test:single": "mocha --require test/env.js --require test/helper.js", "test:integration": "yarn test:integration:build && yarn test:flat", "test:integration:build": "gulp build:scss", "test:e2e:chrome": "SELENIUM_BROWSER=chrome test/e2e/run-all.sh", @@ -44,7 +44,7 @@ "verify-locales": "node ./development/verify-locale-strings.js", "verify-locales:fix": "node ./development/verify-locale-strings.js --fix", "mozilla-lint": "addons-linter dist/firefox", - "watch": "cross-env METAMASK_ENV=test mocha --watch --require test/setup.js --reporter min --recursive \"test/unit/**/*.js\" \"ui/app/**/*.test.js\"", + "watch": "mocha --watch --require test/env.js --require test/setup.js --reporter min --recursive \"test/unit/**/*.js\" \"ui/app/**/*.test.js\"", "devtools:react": "react-devtools", "devtools:redux": "remotedev --hostname=localhost --port=8000", "start:dev": "concurrently -k -n build,react,redux yarn:start yarn:devtools:react yarn:devtools:redux", @@ -199,7 +199,6 @@ "chromedriver": "^79.0.0", "concurrently": "^4.1.1", "coveralls": "^3.0.0", - "cross-env": "^5.1.4", "css-loader": "^2.1.1", "del": "^3.0.0", "deps-dump": "^1.1.0", diff --git a/test/env.js b/test/env.js new file mode 100644 index 000000000..1fbdad3df --- /dev/null +++ b/test/env.js @@ -0,0 +1 @@ +process.env.METAMASK_ENV = 'test' diff --git a/yarn.lock b/yarn.lock index a8aae95ca..232efa3f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7870,14 +7870,6 @@ create-react-context@^0.2.1: fbjs "^0.8.0" gud "^1.0.0" -cross-env@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.1.4.tgz#f61c14291f7cc653bb86457002ea80a04699d022" - integrity sha512-Mx8mw6JWhfpYoEk7PGvHxJMLQwQHORAs8+2bX+C1lGQ4h3GkDb1zbzC2Nw85YH9ZQMlO0BHZxMacgrfPmMFxbg== - dependencies: - cross-spawn "^5.1.0" - is-windows "^1.0.0" - cross-fetch@2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.2.tgz#a47ff4f7fc712daba8f6a695a11c948440d45723" @@ -16000,7 +15992,7 @@ is-windows@^0.2.0: resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" integrity sha1-3hqm1j6indJIc3tp8f+LgALSEIw= -is-windows@^1.0.0, is-windows@^1.0.1, is-windows@^1.0.2: +is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== From 5d1c9313db0b64abf29f61c60e61cfe37e4637ff Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Thu, 30 Jan 2020 11:34:45 -0800 Subject: [PATCH 228/689] Various component tests and some conditional statements (#7765) * Various component tests and some conditional statements Conditional in account-menu in removeAccount when keyring sometimes is not initially provideed Conditional on unlock-page when there is no target.getBoundingClientRect on the element. * Update helpers * Remove component debugging * Add default params for render helpers * Remove stubComponent for old Mascot Changes in https://github.com/MetaMask/metamask-extension/pull/7893 has prevented the need to stub it out. Change logout to lock in account-menu test --- test/helper.js | 3 + test/lib/render-helpers.js | 43 ++- .../account-menu/account-menu.component.js | 6 + .../account-menu/tests/account-menu.test.js | 209 ++++++++++ .../app/app-header/tests/app-header.test.js | 99 +++++ .../app/dropdowns/account-details-dropdown.js | 2 +- .../advanced-gas-input-component.test.js | 104 +++++ .../app/info-box/tests/info-box.test.js | 37 ++ .../app/menu-bar/tests/menu-bar.test.js | 94 +++++ .../tests/confirm-delete-network.test.js | 58 +++ .../tests/confirm-remove-account.test.js | 82 ++++ .../tests/confirm-reset-account.test.js | 46 +++ .../tests/metametrics-opt-in-modal.test.js | 55 +++ .../tests/reject-transactions.test.js | 48 +++ .../tests/account-details-modal.test.js | 82 ++++ .../tests/transaction-confirmed.test.js | 32 ++ .../app/tests/signature-request.test.js | 69 ++++ .../components/app/tests/token-cell.spec.js | 69 ++++ .../components/ui/alert/tests/alert.test.js | 43 +++ .../with-token-tracker.component.test.js | 44 +++ .../pages/add-token/tests/add-token.test.js | 100 +++++ .../tests/create-account.test.js | 46 +++ .../end-of-flow/tests/end-of-flow.test.js | 39 ++ .../tests/first-time-flow-switch.test.js | 73 ++++ .../tests/metametrics-opt-in.test.js | 43 +++ .../tests/reveal-seed-phrase.test.js | 48 +++ .../select-action/tests/select-action.test.js | 46 +++ .../welcome/tests/welcome.test.js | 55 +++ .../pages/keychains/tests/reveal-seed.test.js | 31 ++ ui/app/pages/lock/tests/lock.test.js | 48 +++ .../gas-fee-display.component.test.js | 0 .../security-tab/tests/security-tab.test.js | 55 +++ .../settings-tab/tests/settings-tab.test.js | 61 +++ .../unlock-page/tests/unlock-page.test.js | 69 ++++ .../unlock-page/unlock-page.component.js | 16 +- .../tests/confirm-transaction.test.js | 159 ++++++++ ui/app/selectors/tests/tokens.test.js | 28 ++ ui/app/selectors/tests/transactions.test.js | 356 ++++++++++++++++++ 38 files changed, 2472 insertions(+), 26 deletions(-) create mode 100644 ui/app/components/app/account-menu/tests/account-menu.test.js create mode 100644 ui/app/components/app/app-header/tests/app-header.test.js create mode 100644 ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js create mode 100644 ui/app/components/app/info-box/tests/info-box.test.js create mode 100644 ui/app/components/app/menu-bar/tests/menu-bar.test.js create mode 100644 ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js create mode 100644 ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js create mode 100644 ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js create mode 100644 ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js create mode 100644 ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js create mode 100644 ui/app/components/app/modals/tests/account-details-modal.test.js create mode 100644 ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js create mode 100644 ui/app/components/app/tests/signature-request.test.js create mode 100644 ui/app/components/app/tests/token-cell.spec.js create mode 100644 ui/app/components/ui/alert/tests/alert.test.js create mode 100644 ui/app/helpers/higher-order-components/with-token-tracker/tests/with-token-tracker.component.test.js create mode 100644 ui/app/pages/add-token/tests/add-token.test.js create mode 100644 ui/app/pages/create-account/tests/create-account.test.js create mode 100644 ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js create mode 100644 ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js create mode 100644 ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js create mode 100644 ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js create mode 100644 ui/app/pages/first-time-flow/select-action/tests/select-action.test.js create mode 100644 ui/app/pages/first-time-flow/welcome/tests/welcome.test.js create mode 100644 ui/app/pages/keychains/tests/reveal-seed.test.js create mode 100644 ui/app/pages/lock/tests/lock.test.js rename ui/app/pages/send/send-content/send-gas-row/gas-fee-display/{test => tests}/gas-fee-display.component.test.js (100%) create mode 100644 ui/app/pages/settings/security-tab/tests/security-tab.test.js create mode 100644 ui/app/pages/settings/settings-tab/tests/settings-tab.test.js create mode 100644 ui/app/pages/unlock-page/tests/unlock-page.test.js create mode 100644 ui/app/selectors/tests/confirm-transaction.test.js create mode 100644 ui/app/selectors/tests/tokens.test.js create mode 100644 ui/app/selectors/tests/transactions.test.js diff --git a/test/helper.js b/test/helper.js index 38cdb6bfd..90dc9898d 100644 --- a/test/helper.js +++ b/test/helper.js @@ -56,6 +56,9 @@ require('jsdom-global')() // localStorage window.localStorage = {} +// override metamask-logo +window.requestAnimationFrame = () => {} + // crypto.getRandomValues if (!window.crypto) { window.crypto = {} diff --git a/test/lib/render-helpers.js b/test/lib/render-helpers.js index ea0c5cf6b..45bcb1656 100644 --- a/test/lib/render-helpers.js +++ b/test/lib/render-helpers.js @@ -1,14 +1,7 @@ -import { shallow, mount } from 'enzyme' import React from 'react' -import { BrowserRouter } from 'react-router-dom' -import { shape } from 'prop-types' - -export function shallowWithStore (component, store) { - const context = { - store, - } - return shallow(component, { context }) -} +import { mount } from 'enzyme' +import { MemoryRouter } from 'react-router-dom' +import PropTypes from 'prop-types' export function mountWithStore (component, store) { const context = { @@ -17,26 +10,40 @@ export function mountWithStore (component, store) { return mount(component, { context }) } -export function mountWithRouter (node) { +export function mountWithRouter (component, store = {}, pathname = '/') { // Instantiate router context const router = { - history: new BrowserRouter().history, + history: new MemoryRouter().history, route: { - location: {}, + location: { + pathname: pathname, + }, match: {}, }, } const createContext = () => ({ - context: { router, t: () => {} }, - childContextTypes: { router: shape({}), t: () => {} }, + context: { + router, + t: str => str, + tOrKey: str => str, + metricsEvent: () => {}, + store, + }, + childContextTypes: { + router: PropTypes.object, + t: PropTypes.func, + tOrKey: PropTypes.func, + metricsEvent: PropTypes.func, + store: PropTypes.object, + }, }) const Wrapper = () => ( - - {node} - + + {component} + ) return mount(, createContext()) diff --git a/ui/app/components/app/account-menu/account-menu.component.js b/ui/app/components/app/account-menu/account-menu.component.js index 523aaea9d..b249ee179 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/app/components/app/account-menu/account-menu.component.js @@ -193,6 +193,12 @@ export default class AccountMenu extends Component { renderRemoveAccount (keyring, identity) { const { t } = this.context + + // Sometimes keyrings aren't loaded yet + if (!keyring) { + return null + } + // Any account that's not from the HD wallet Keyring can be removed const { type } = keyring const isRemovable = type !== 'HD Key Tree' diff --git a/ui/app/components/app/account-menu/tests/account-menu.test.js b/ui/app/components/app/account-menu/tests/account-menu.test.js new file mode 100644 index 000000000..b1ebcf61c --- /dev/null +++ b/ui/app/components/app/account-menu/tests/account-menu.test.js @@ -0,0 +1,209 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import configureMockStore from 'redux-mock-store' +import { mountWithRouter } from '../../../../../../test/lib/render-helpers' +import AccountMenu from '../index' +import { Provider } from 'react-redux' + +describe('Account Menu', async () => { + + let wrapper + + const mockStore = { + metamask: { + provider: { + type: 'test', + }, + preferences: { + useNativeCurrencyAsPrimaryCurrency: true, + }, + }, + } + + const store = configureMockStore()(mockStore) + + const props = { + isAccountMenuOpen: true, + addressConnectedDomainMap: {}, + accounts: [ + { + address: '0xAddress', + name: 'Account 1', + balance: '0x0', + }, + { + address: '0xImportedAddress', + name: 'Imported Account 1', + balance: '0x0', + }, + ], + keyrings: [ + { + type: 'HD Key Tree', + accounts: [ + '0xAdress', + ], + }, + { + type: 'Simple Key Pair', + accounts: [ + '0xImportedAddress', + ], + }, + ], + prevIsAccountMenuOpen: false, + lockMetamask: sinon.spy(), + showAccountDetail: sinon.spy(), + showRemoveAccountConfirmationModal: sinon.spy(), + toggleAccountMenu: sinon.spy(), + history: { + push: sinon.spy(), + }, + + } + + before(() => { + wrapper = mountWithRouter( + + + , store + ) + }) + + afterEach(() => { + props.toggleAccountMenu.resetHistory() + props.history.push.resetHistory() + }) + + describe('Render Content', () => { + it('returns account name from identities', () => { + const accountName = wrapper.find('.account-menu__name') + assert.equal(accountName.length, 2) + }) + + it('renders user preference currency display balance from account balance', () => { + const accountBalance = wrapper.find('.currency-display-component.account-menu__balance') + assert.equal(accountBalance.length, 2) + }) + + it('simulate click', () => { + const click = wrapper.find('.account-menu__account.menu__item--clickable') + click.first().simulate('click') + + assert(props.showAccountDetail.calledOnce) + assert.equal(props.showAccountDetail.getCall(0).args[0], '0xAddress') + }) + + it('render imported account label', () => { + const importedAccount = wrapper.find('.keyring-label.allcaps') + assert.equal(importedAccount.text(), 'imported') + }) + + it('remove account', () => { + const removeAccount = wrapper.find('.remove-account-icon') + removeAccount.simulate('click', { + preventDefault: () => {}, + stopPropagation: () => {}, + }) + + assert(props.showRemoveAccountConfirmationModal.calledOnce) + assert.deepEqual(props.showRemoveAccountConfirmationModal.getCall(0).args[0], + { address: '0xImportedAddress', balance: '0x0', name: 'Imported Account 1' } + ) + }) + }) + + describe('Log Out', () => { + let logout + + it('logout', () => { + logout = wrapper.find('.account-menu__lock-button') + assert.equal(logout.length, 1) + }) + + it('simulate click', () => { + logout.simulate('click') + assert(props.lockMetamask.calledOnce) + assert.equal(props.history.push.getCall(0).args[0], '/') + }) + }) + + describe('Create Account', () => { + let createAccount + + it('renders create account item', () => { + createAccount = wrapper.find({ text: 'createAccount' }) + assert.equal(createAccount.length, 1) + }) + + it('calls toggle menu and push new-account route to history', () => { + createAccount.simulate('click') + assert(props.toggleAccountMenu.calledOnce) + assert.equal(props.history.push.getCall(0).args[0], '/new-account') + }) + }) + + describe('Import Account', () => { + let importAccount + + it('renders import account item', () => { + importAccount = wrapper.find({ text: 'importAccount' }) + assert.equal(importAccount.length, 1) + }) + + it('calls toggle menu and push /new-account/import route to history', () => { + importAccount.simulate('click') + assert(props.toggleAccountMenu.calledOnce) + assert(props.history.push.getCall(0).args[0], '/new-account/import') + }) + }) + + describe('Connect Hardware Wallet', () => { + + let connectHardwareWallet + + it('renders import account item', () => { + connectHardwareWallet = wrapper.find({ text: 'connectHardwareWallet' }) + assert.equal(connectHardwareWallet.length, 1) + }) + + it('calls toggle menu and push /new-account/connect route to history', () => { + connectHardwareWallet.simulate('click') + assert(props.toggleAccountMenu.calledOnce) + assert.equal(props.history.push.getCall(0).args[0], '/new-account/connect') + }) + }) + + describe('Info & Help', () => { + + let infoHelp + + it('renders import account item', () => { + infoHelp = wrapper.find({ text: 'infoHelp' }) + assert.equal(infoHelp.length, 1) + }) + + it('calls toggle menu and push /new-account/connect route to history', () => { + infoHelp.simulate('click') + assert(props.toggleAccountMenu.calledOnce) + assert.equal(props.history.push.getCall(0).args[0], '/settings/about-us') + }) + }) + + describe('Settings', () => { + + let settings + + it('renders import account item', () => { + settings = wrapper.find({ text: 'settings' }) + assert.equal(settings.length, 1) + }) + + it('calls toggle menu and push /new-account/connect route to history', () => { + settings.simulate('click') + assert(props.toggleAccountMenu.calledOnce) + assert.equal(props.history.push.getCall(0).args[0], '/settings') + }) + }) +}) diff --git a/ui/app/components/app/app-header/tests/app-header.test.js b/ui/app/components/app/app-header/tests/app-header.test.js new file mode 100644 index 000000000..37d1c32c4 --- /dev/null +++ b/ui/app/components/app/app-header/tests/app-header.test.js @@ -0,0 +1,99 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { shallow } from 'enzyme' +import MetaFoxLogo from '../../../ui/metafox-logo' +import AppHeader from '../index' + +describe('App Header', () => { + let wrapper + + const props = { + hideNetworkDropdown: sinon.spy(), + showNetworkDropdown: sinon.spy(), + toggleAccountMenu: sinon.spy(), + history: { + push: sinon.spy(), + }, + network: 'test', + provider: {}, + selectedAddress: '0xAddress', + disabled: false, + hideNetworkIndicator: false, + networkDropdownOpen: false, + isAccountMenuOpen: false, + isUnlocked: true, + } + + beforeEach(() => { + wrapper = shallow( + , { + context: { + t: str => str, + metricsEvent: () => {}, + }, + } + ) + }) + + afterEach(() => { + props.toggleAccountMenu.resetHistory() + }) + + describe('App Header Logo', () => { + it('routes to default route when logo is clicked', () => { + const appLogo = wrapper.find(MetaFoxLogo) + appLogo.simulate('click') + assert(props.history.push.calledOnce) + assert.equal(props.history.push.getCall(0).args[0], '/') + }) + }) + + describe('Network', () => { + it('shows network dropdown when networkDropdownOpen is false', () => { + const network = wrapper.find({ network: 'test' }) + + network.simulate('click', { + preventDefault: () => {}, + stopPropagation: () => {}, + }) + + assert(props.showNetworkDropdown.calledOnce) + }) + + it('hides network dropdown when networkDropdownOpen is true', () => { + wrapper.setProps({ networkDropdownOpen: true }) + const network = wrapper.find({ network: 'test' }) + + network.simulate('click', { + preventDefault: () => {}, + stopPropagation: () => {}, + }) + + assert(props.hideNetworkDropdown.calledOnce) + }) + + it('hides network indicator', () => { + wrapper.setProps({ hideNetworkIndicator: true }) + const network = wrapper.find({ network: 'test' }) + assert.equal(network.length, 0) + }) + }) + + describe('Account Menu', () => { + + it('toggles account menu', () => { + const accountMenu = wrapper.find('.account-menu__icon') + accountMenu.simulate('click') + assert(props.toggleAccountMenu.calledOnce) + }) + + it('does not toggle account menu when disabled', () => { + wrapper.setProps({ disabled: true }) + const accountMenu = wrapper.find('.account-menu__icon') + accountMenu.simulate('click') + assert(props.toggleAccountMenu.notCalled) + }) + }) + +}) diff --git a/ui/app/components/app/dropdowns/account-details-dropdown.js b/ui/app/components/app/dropdowns/account-details-dropdown.js index bfd1df777..a9d5f0a5a 100644 --- a/ui/app/components/app/dropdowns/account-details-dropdown.js +++ b/ui/app/components/app/dropdowns/account-details-dropdown.js @@ -40,7 +40,7 @@ class AccountDetailsDropdown extends Component { static propTypes = { selectedIdentity: PropTypes.object.isRequired, - network: PropTypes.number.isRequired, + network: PropTypes.string.isRequired, keyrings: PropTypes.array.isRequired, showAccountDetailModal: PropTypes.func.isRequired, viewOnEtherscan: PropTypes.func.isRequired, diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js b/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js new file mode 100644 index 000000000..e45740f5b --- /dev/null +++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js @@ -0,0 +1,104 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { mount } from 'enzyme' +import AdvancedTabContent from '../index' + +describe('Advanced Gas Inputs', () => { + let wrapper, clock + + const props = { + updateCustomGasPrice: sinon.spy(), + updateCustomGasLimit: sinon.spy(), + showGasPriceInfoModal: sinon.spy(), + showGasLimitInfoModal: sinon.spy(), + customGasPrice: 0, + customGasLimit: 0, + insufficientBalance: false, + customPriceIsSafe: true, + isSpeedUp: false, + } + + beforeEach(() => { + clock = sinon.useFakeTimers() + + wrapper = mount( + , { + context: { + t: str => str, + }, + }) + }) + + afterEach(() => { + clock.restore() + }) + + it('wont update gasPrice in props before debounce', () => { + const event = { target: { value: 1 } } + + wrapper.find('input').at(0).simulate('change', event) + clock.tick(499) + + assert.equal(props.updateCustomGasPrice.callCount, 0) + }) + + it('simulates onChange on gas price after debounce', () => { + const event = { target: { value: 1 } } + + wrapper.find('input').at(0).simulate('change', event) + clock.tick(500) + + assert.equal(props.updateCustomGasPrice.calledOnce, true) + assert.equal(props.updateCustomGasPrice.calledWith(1), true) + }) + + it('wont update gasLimit in props before debounce', () => { + const event = { target: { value: 21000 } } + + wrapper.find('input').at(1).simulate('change', event) + clock.tick(499) + + assert.equal(props.updateCustomGasLimit.callCount, 0) + }) + + it('simulates onChange on gas limit after debounce', () => { + const event = { target: { value: 21000 } } + + wrapper.find('input').at(1).simulate('change', event) + clock.tick(500) + + assert.equal(props.updateCustomGasLimit.calledOnce, true) + assert.equal(props.updateCustomGasLimit.calledWith(21000), true) + }) + + it('errors when insuffientBalance under gas price and gas limit', () => { + wrapper.setProps({ insufficientBalance: true }) + const renderError = wrapper.find('.advanced-gas-inputs__gas-edit-row__error-text') + assert.equal(renderError.length, 2) + + assert.equal(renderError.at(0).text(), 'insufficientBalance') + assert.equal(renderError.at(1).text(), 'insufficientBalance') + }) + + it('errors zero gas price / speed up', () => { + wrapper.setProps({ isSpeedUp: true }) + + const renderError = wrapper.find('.advanced-gas-inputs__gas-edit-row__error-text') + assert.equal(renderError.length, 2) + + assert.equal(renderError.at(0).text(), 'zeroGasPriceOnSpeedUpError') + assert.equal(renderError.at(1).text(), 'gasLimitTooLow') + }) + + it('warns when custom gas price is too low', () => { + wrapper.setProps({ customPriceIsSafe: false }) + + const renderWarning = wrapper.find('.advanced-gas-inputs__gas-edit-row__warning-text') + assert.equal(renderWarning.length, 1) + + assert.equal(renderWarning.text(), 'gasPriceExtremelyLow') + }) +}) diff --git a/ui/app/components/app/info-box/tests/info-box.test.js b/ui/app/components/app/info-box/tests/info-box.test.js new file mode 100644 index 000000000..904e868ba --- /dev/null +++ b/ui/app/components/app/info-box/tests/info-box.test.js @@ -0,0 +1,37 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { shallow } from 'enzyme' + +import InfoBox from '../index' + +describe('InfoBox', () => { + + let wrapper + + const props = { + title: 'Title', + description: 'Description', + onClose: sinon.spy(), + } + + beforeEach(() => { + wrapper = shallow() + }) + + it('renders title from props', () => { + const title = wrapper.find('.info-box__title') + assert.equal(title.text(), props.title) + }) + + it('renders description from props', () => { + const description = wrapper.find('.info-box__description') + assert.equal(description.text(), props.description) + }) + + it('closes info box', () => { + const close = wrapper.find('.info-box__close') + close.simulate('click') + assert(props.onClose.calledOnce) + }) +}) diff --git a/ui/app/components/app/menu-bar/tests/menu-bar.test.js b/ui/app/components/app/menu-bar/tests/menu-bar.test.js new file mode 100644 index 000000000..a43b994ba --- /dev/null +++ b/ui/app/components/app/menu-bar/tests/menu-bar.test.js @@ -0,0 +1,94 @@ +import React from 'react' +import configureStore from 'redux-mock-store' +import assert from 'assert' +import sinon from 'sinon' +import { mountWithRouter } from '../../../../../../test/lib/render-helpers' +import MenuBar from '../index' +import { Provider } from 'react-redux' + +describe('MenuBar', () => { + let wrapper + + const mockStore = { + metamask: { + network: '1', + selectedAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + identities: { + '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { + address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + name: 'Account 1', + }, + }, + keyrings: [ + { + type: 'HD Key Tree', + accounts: [ + '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + ], + }, + ], + frequentRpcListDetail: [], + }, + appState: { + sidebar: { + isOpen: false, + }, + }, + } + + const store = configureStore()(mockStore) + + afterEach(() => { + sinon.restore() + }) + + it('shows side bar when sidbarOpen is set to false', () => { + const props = { + showSidebar: sinon.spy(), + } + + wrapper = mountWithRouter( + + + , store + ) + + const sidebarButton = wrapper.find('.menu-bar__sidebar-button') + sidebarButton.simulate('click') + assert(props.showSidebar.calledOnce) + }) + + it('hides side when sidebarOpen is set to true', () => { + const props = { + showSidebar: sinon.spy(), + hideSidebar: sinon.spy(), + sidebarOpen: true, + } + + wrapper = mountWithRouter( + + + , store + ) + + const sidebarButton = wrapper.find('.menu-bar__sidebar-button') + sidebarButton.prop('onClick')() + assert(props.hideSidebar.calledOnce) + }) + + it('opens account detail menu when account options is clicked', () => { + const accountOptions = wrapper.find('.menu-bar__open-in-browser') + accountOptions.simulate('click') + assert.equal(wrapper.find('MenuBar').instance().state.accountDetailsMenuOpen, true) + }) + + it('sets accountDetailsMenuOpen to false when closed', () => { + wrapper.find('MenuBar').instance().setState({ accountDetailsMenuOpen: true }) + wrapper.update() + + const accountDetailsMenu = wrapper.find('AccountDetailsDropdown') + accountDetailsMenu.prop('onClose')() + + assert.equal(wrapper.find('MenuBar').instance().state.accountDetailsMenuOpen, false) + }) +}) diff --git a/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js b/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js new file mode 100644 index 000000000..ce0d49013 --- /dev/null +++ b/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js @@ -0,0 +1,58 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { mount } from 'enzyme' +import ConfirmDeleteNetwork from '../index' + +describe('Confirm Delete Network', () => { + let wrapper + + const props = { + hideModal: sinon.spy(), + delRpcTarget: sinon.stub().resolves(), + onConfirm: sinon.spy(), + target: '', + } + + beforeEach(() => { + wrapper = mount( + , { + context: { + t: str => str, + }, + } + ) + }) + + afterEach(() => { + props.hideModal.resetHistory() + props.delRpcTarget.resetHistory() + props.onConfirm.resetHistory() + }) + + it('renders delete network modal title', () => { + const modalTitle = wrapper.find('.modal-content__title') + assert.equal(modalTitle.text(), 'deleteNetwork') + }) + + it('clicks cancel to hide modal', () => { + const cancelButton = wrapper.find('.button.btn-default.modal-container__footer-button') + cancelButton.simulate('click') + + assert(props.hideModal.calledOnce) + + }) + + it('clicks delete to delete the target and hides modal', () => { + const deleteButton = wrapper.find('.button.btn-danger.modal-container__footer-button') + + deleteButton.simulate('click') + + setImmediate(() => { + assert(props.delRpcTarget.calledOnce) + assert(props.hideModal.calledOnce) + assert(props.onConfirm.calledOnce) + }) + }) + +}) diff --git a/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js b/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js new file mode 100644 index 000000000..0a6eb828d --- /dev/null +++ b/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js @@ -0,0 +1,82 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { Provider } from 'react-redux' +import assert from 'assert' +import sinon from 'sinon' +import configureStore from 'redux-mock-store' +import { mount } from 'enzyme' +import ConfirmRemoveAccount from '../index' + +describe('Confirm Remove Account', () => { + let wrapper + + const state = { + metamask: { + + }, + } + + const props = { + hideModal: sinon.spy(), + removeAccount: sinon.stub().resolves(), + network: '101', + identity: { + address: '0xAddress', + name: 'Account 1', + }, + } + + + const mockStore = configureStore() + const store = mockStore(state) + + beforeEach(() => { + + wrapper = mount( + + + , { + context: { + t: str => str, + store, + }, + childContextTypes: { + t: PropTypes.func, + store: PropTypes.object, + }, + } + ) + }) + + afterEach(() => { + props.hideModal.resetHistory() + }) + + it('nevermind', () => { + const nevermind = wrapper.find({ type: 'default' }) + nevermind.simulate('click') + + assert(props.hideModal.calledOnce) + }) + + it('remove', (done) => { + const remove = wrapper.find({ type: 'secondary' }) + remove.simulate('click') + + assert(props.removeAccount.calledOnce) + assert.equal(props.removeAccount.getCall(0).args[0], props.identity.address) + + setImmediate(() => { + assert(props.hideModal.calledOnce) + done() + }) + + }) + + it('closes', () => { + const close = wrapper.find('.modal-container__header-close') + close.simulate('click') + + assert(props.hideModal.calledOnce) + }) +}) diff --git a/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js b/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js new file mode 100644 index 000000000..175a38158 --- /dev/null +++ b/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js @@ -0,0 +1,46 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { mount } from 'enzyme' +import ConfirmResetAccount from '../index' + +describe('Confirm Reset Account', () => { + let wrapper + + const props = { + hideModal: sinon.spy(), + resetAccount: sinon.stub().resolves(), + } + + beforeEach(() => { + wrapper = mount( + , { + context: { + t: str => str, + }, + } + ) + }) + + afterEach(() => { + props.hideModal.resetHistory() + }) + + it('hides modal when nevermind button is clicked', () => { + const nevermind = wrapper.find('.btn-default.modal-container__footer-button') + nevermind.simulate('click') + + assert(props.hideModal.calledOnce) + }) + + it('resets account and hidels modal when reset button is clicked', (done) => { + const reset = wrapper.find('.btn-danger.modal-container__footer-button') + reset.simulate('click') + + setImmediate(() => { + assert(props.resetAccount.calledOnce) + assert(props.hideModal.calledOnce) + done() + }) + }) +}) diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js b/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js new file mode 100644 index 000000000..2bae8f9b1 --- /dev/null +++ b/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js @@ -0,0 +1,55 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { mount } from 'enzyme' +import MetaMetricsOptIn from '../index' + +describe('MetaMetrics Opt In', () => { + let wrapper + + const props = { + setParticipateInMetaMetrics: sinon.stub().resolves(), + hideModal: sinon.spy(), + participateInMetaMetrics: null, + } + + beforeEach(() => { + wrapper = mount( + , { + context: { + metricsEvent: () => {}, + }, + } + ) + }) + + afterEach(() => { + props.setParticipateInMetaMetrics.resetHistory() + props.hideModal.resetHistory() + }) + + it('passes false to setParticipateInMetaMetrics and hides modal', (done) => { + const noThanks = wrapper.find('.btn-default.page-container__footer-button') + noThanks.simulate('click') + + setImmediate(() => { + assert(props.setParticipateInMetaMetrics.calledOnce) + assert.equal(props.setParticipateInMetaMetrics.getCall(0).args[0], false) + assert(props.hideModal.calledOnce) + done() + }) + }) + + it('passes true to setParticipateInMetaMetrics and hides modal', (done) => { + const iAgree = wrapper.find('.btn-primary.page-container__footer-button') + iAgree.simulate('click') + + setImmediate(() => { + assert(props.setParticipateInMetaMetrics.calledOnce) + assert.equal(props.setParticipateInMetaMetrics.getCall(0).args[0], true) + assert(props.hideModal.calledOnce) + done() + }) + }) + +}) diff --git a/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js b/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js new file mode 100644 index 000000000..505e9a05e --- /dev/null +++ b/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js @@ -0,0 +1,48 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { mount } from 'enzyme' +import RejectTransactionsModal from '../index' + +describe('Reject Transactions Model', () => { + let wrapper + + const props = { + onSubmit: sinon.spy(), + hideModal: sinon.spy(), + unapprovedTxCount: 2, + } + + beforeEach(() => { + wrapper = mount( + , { + context: { + t: str => str, + }, + } + ) + }) + + afterEach(() => { + props.hideModal.resetHistory() + }) + + it('hides modal when cancel button is clicked', () => { + const cancelButton = wrapper.find('.btn-default.modal-container__footer-button') + cancelButton.simulate('click') + + assert(props.hideModal.calledOnce) + }) + + it('onSubmit is called and hides modal when reject all clicked', (done) => { + const rejectAllButton = wrapper.find('.btn-secondary.modal-container__footer-button') + rejectAllButton.simulate('click') + + setImmediate(() => { + assert(props.onSubmit.calledOnce) + assert(props.hideModal.calledOnce) + done() + }) + + }) +}) diff --git a/ui/app/components/app/modals/tests/account-details-modal.test.js b/ui/app/components/app/modals/tests/account-details-modal.test.js new file mode 100644 index 000000000..24fe0eee4 --- /dev/null +++ b/ui/app/components/app/modals/tests/account-details-modal.test.js @@ -0,0 +1,82 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { shallow } from 'enzyme' +import AccountDetailsModal from '../account-details-modal' + +describe('Account Details Modal', () => { + let wrapper + + global.platform = { openWindow: sinon.spy() } + + const props = { + hideModal: sinon.spy(), + setAccountLabel: sinon.spy(), + showExportPrivateKeyModal: sinon.spy(), + showQrView: sinon.spy(), + network: 'test', + rpcPrefs: {}, + selectedIdentity: { + address: '0xAddress', + name: 'Account 1', + }, + keyrings: [ + { + type: 'HD Key Tree', + accounts: [ + '0xAddress', + ], + }, + ], + identities: { + '0xAddress': { + address: '0xAddress', + name: 'Account 1', + }, + }, + } + + beforeEach(() => { + wrapper = shallow( + , { + context: { + t: str => str, + }, + } + ) + }) + + it('sets account label when changing default account label', () => { + const accountLabel = wrapper.find('.account-modal__name').first() + accountLabel.simulate('submit', 'New Label') + + assert(props.setAccountLabel.calledOnce) + assert.equal(props.setAccountLabel.getCall(0).args[1], 'New Label') + }) + + it('opens new window when view block explorer is clicked', () => { + const modalButton = wrapper.find('.account-modal__button') + const etherscanLink = modalButton.first() + + etherscanLink.simulate('click') + assert(global.platform.openWindow.calledOnce) + }) + + it('shows export private key modal when clicked', () => { + const modalButton = wrapper.find('.account-modal__button') + const etherscanLink = modalButton.last() + + etherscanLink.simulate('click') + assert(props.showExportPrivateKeyModal.calledOnce) + }) + + it('sets blockexplorerview text when block explorer url in rpcPrefs exists', () => { + const blockExplorerUrl = 'https://block.explorer' + wrapper.setProps({ rpcPrefs: { blockExplorerUrl } }) + + const modalButton = wrapper.find('.account-modal__button') + const blockExplorerLink = modalButton.first() + + assert.equal(blockExplorerLink.html(), '') + }) +}) diff --git a/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js b/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js new file mode 100644 index 000000000..7d4debfd7 --- /dev/null +++ b/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js @@ -0,0 +1,32 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { mount } from 'enzyme' +import TransactionConfirmed from '../index' + +describe('Transaction Confirmed', () => { + let wrapper + + const props = { + onSubmit: sinon.spy(), + hideModal: sinon.spy(), + } + + beforeEach(() => { + wrapper = mount( + , { + context: { + t: str => str, + }, + } + ) + }) + + it('clicks ok to submit and hide modal', () => { + const submit = wrapper.find('.btn-secondary.modal-container__footer-button') + submit.simulate('click') + + assert(props.onSubmit.calledOnce) + assert(props.hideModal.calledOnce) + }) +}) diff --git a/ui/app/components/app/tests/signature-request.test.js b/ui/app/components/app/tests/signature-request.test.js new file mode 100644 index 000000000..eda054c16 --- /dev/null +++ b/ui/app/components/app/tests/signature-request.test.js @@ -0,0 +1,69 @@ +import React from 'react' +import { Provider } from 'react-redux' +import assert from 'assert' +import sinon from 'sinon' +import configureMockStore from 'redux-mock-store' +import { mountWithRouter } from '../../../../../test/lib/render-helpers' +import SignatureRequest from '../signature-request' + +describe('Signature Request', () => { + let wrapper + + const mockStore = { + metamask: { + provider: { + type: 'test', + }, + }, + } + const store = configureMockStore()(mockStore) + + const props = { + selectedAccount: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', + history: { + push: sinon.spy(), + }, + clearConfirmTransaction: sinon.spy(), + cancelMessage: sinon.spy(), + cancel: sinon.stub().resolves(), + sign: sinon.stub().resolves(), + txData: { + msgParams: { + id: 1, + data: '{"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Person":[{"name":"name","type":"string"},{"name":"wallet","type":"address"}],"Mail":[{"name":"from","type":"Person"},{"name":"to","type":"Person"},{"name":"contents","type":"string"}]},"primaryType":"Mail","domain":{"name":"Ether Mail","version":"1","chainId":"4","verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"},"message":{"from":{"name":"Cow","wallet":"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"},"to":{"name":"Bob","wallet":"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"},"contents":"Hello, Bob!"}}', + from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', + origin: 'test.domain', + }, + status: 'unapproved', + time: 1, + type: 'eth_sign', + }, + } + + beforeEach(() => { + wrapper = mountWithRouter( + + + , store + ) + }) + + afterEach(() => { + props.clearConfirmTransaction.resetHistory() + }) + + it('cancel', () => { + const cancelButton = wrapper.find('button.btn-default') + cancelButton.simulate('click') + + assert(props.cancel.calledOnce) + }) + + it('sign', () => { + const signButton = wrapper.find('button.btn-primary') + signButton.simulate('click') + + assert(props.sign.calledOnce) + }) + +}) diff --git a/ui/app/components/app/tests/token-cell.spec.js b/ui/app/components/app/tests/token-cell.spec.js new file mode 100644 index 000000000..877713e4c --- /dev/null +++ b/ui/app/components/app/tests/token-cell.spec.js @@ -0,0 +1,69 @@ +import React from 'react' +import assert from 'assert' +import thunk from 'redux-thunk' +import { Provider } from 'react-redux' +import configureMockStore from 'redux-mock-store' +import { mount } from 'enzyme' + +import TokenCell from '../token-cell' +import Identicon from '../../ui/identicon' + +describe('Token Cell', () => { + let wrapper + + const state = { + metamask: { + network: 'test', + currentCurrency: 'usd', + selectedTokenAddress: '0xToken', + selectedAddress: '0xAddress', + contractExchangeRates: { + '0xAnotherToken': 0.015, + }, + conversionRate: 7.00, + }, + appState: { + sidebar: { + isOpen: true, + }, + }, + } + + const middlewares = [thunk] + const mockStore = configureMockStore(middlewares) + const store = mockStore(state) + + beforeEach(() => { + wrapper = mount( + + + + ) + }) + + it('renders Identicon with props from token cell', () => { + assert.equal(wrapper.find(Identicon).prop('address'), '0xAnotherToken') + assert.equal(wrapper.find(Identicon).prop('network'), 'test') + assert.equal(wrapper.find(Identicon).prop('image'), './test-image') + }) + + it('renders token balance', () => { + assert.equal(wrapper.find('.token-list-item__token-balance').text(), '5.000') + }) + + it('renders token symbol', () => { + assert.equal(wrapper.find('.token-list-item__token-symbol').text(), 'TEST') + }) + + it('renders converted fiat amount', () => { + assert.equal(wrapper.find('.token-list-item__fiat-amount').text(), '0.52 USD') + }) + +}) diff --git a/ui/app/components/ui/alert/tests/alert.test.js b/ui/app/components/ui/alert/tests/alert.test.js new file mode 100644 index 000000000..d3de51bfb --- /dev/null +++ b/ui/app/components/ui/alert/tests/alert.test.js @@ -0,0 +1,43 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { shallow } from 'enzyme' +import Alert from '../index' + +describe('Alert', () => { + let wrapper + + beforeEach(() => { + wrapper = shallow( + + ) + }) + + it('renders nothing with no visible boolean in state', () => { + const alert = wrapper.find('.global-alert') + assert.equal(alert.length, 0) + }) + + it('renders when visible in state is true, and message', () => { + const errorMessage = 'Error Message' + + wrapper.setState({ visible: true, msg: errorMessage }) + + const alert = wrapper.find('.global-alert') + assert.equal(alert.length, 1) + + const errorText = wrapper.find('.msg') + assert.equal(errorText.text(), errorMessage) + }) + + it('calls component method when componentWillReceiveProps is called', () => { + const animateInSpy = sinon.stub(wrapper.instance(), 'animateIn') + const animateOutSpy = sinon.stub(wrapper.instance(), 'animateOut') + + wrapper.setProps({ visible: true }) + assert(animateInSpy.calledOnce) + + wrapper.setProps({ visible: false }) + assert(animateOutSpy.calledOnce) + }) +}) diff --git a/ui/app/helpers/higher-order-components/with-token-tracker/tests/with-token-tracker.component.test.js b/ui/app/helpers/higher-order-components/with-token-tracker/tests/with-token-tracker.component.test.js new file mode 100644 index 000000000..c7d22242d --- /dev/null +++ b/ui/app/helpers/higher-order-components/with-token-tracker/tests/with-token-tracker.component.test.js @@ -0,0 +1,44 @@ +import React from 'react' +import assert from 'assert' +import { shallow } from 'enzyme' +import withTokenTracker from '../with-token-tracker.component' +import TokenBalance from '../../../../components/ui/token-balance/token-balance.component' +// import sinon from 'sinon' +import TokenTracker from 'eth-token-tracker' + +const { createTestProviderTools } = require('../../../../../../test/stub/provider') + +const provider = createTestProviderTools({ scaffold: {} }).provider + +describe('WithTokenTracker HOC', () => { + let wrapper + + beforeEach(() => { + const TokenTracker = withTokenTracker(TokenBalance) + wrapper = shallow( + + ) + }) + + it('#setError', () => { + wrapper.instance().setError('test') + assert.equal(wrapper.props().error, 'test') + }) + + it('#updateBalance', () => { + wrapper.instance().tracker = new TokenTracker({ + provider, + }) + wrapper.instance().updateBalance([{ string: 'test string', symbol: 'test symbol' }]) + assert.equal(wrapper.props().string, 'test string') + assert.equal(wrapper.props().symbol, 'test symbol') + }) + +}) diff --git a/ui/app/pages/add-token/tests/add-token.test.js b/ui/app/pages/add-token/tests/add-token.test.js new file mode 100644 index 000000000..67465752b --- /dev/null +++ b/ui/app/pages/add-token/tests/add-token.test.js @@ -0,0 +1,100 @@ +import React from 'react' +import { Provider } from 'react-redux' +import assert from 'assert' +import sinon from 'sinon' +import configureMockStore from 'redux-mock-store' +import { mountWithRouter } from '../../../../../test/lib/render-helpers' +import AddToken from '../index' + +describe('Add Token', () => { + let wrapper + + const state = { + metamask: { + tokens: [], + }, + } + + const mockStore = configureMockStore() + const store = mockStore(state) + + const props = { + history: { + push: sinon.stub().callsFake(() => {}), + }, + setPendingTokens: sinon.spy(), + clearPendingTokens: sinon.spy(), + tokens: [], + identities: {}, + } + + before(() => { + wrapper = mountWithRouter( + + + , store + ) + + wrapper.find({ name: 'customToken' }).simulate('click') + }) + + afterEach(() => { + props.history.push.reset() + }) + + describe('Add Token', () => { + + it('next button is disabled when no fields are populated', () => { + const nextButton = wrapper.find('.button.btn-secondary.page-container__footer-button') + + assert.equal(nextButton.props().disabled, true) + }) + + it('edits token address', () => { + const tokenAddress = '0x617b3f8050a0BD94b6b1da02B4384eE5B4DF13F4' + const event = { target: { value: tokenAddress } } + const customAddress = wrapper.find('input#custom-address') + + customAddress.simulate('change', event) + assert.equal(wrapper.find('AddToken').instance().state.customAddress, tokenAddress) + }) + + + it('edits token symbol', () => { + const tokenSymbol = 'META' + const event = { target: { value: tokenSymbol } } + const customAddress = wrapper.find('#custom-symbol') + customAddress.last().simulate('change', event) + + assert.equal(wrapper.find('AddToken').instance().state.customSymbol, tokenSymbol) + }) + + it('edits token decimal precision', () => { + const tokenPrecision = '2' + const event = { target: { value: tokenPrecision } } + const customAddress = wrapper.find('#custom-decimals') + customAddress.last().simulate('change', event) + + assert.equal(wrapper.find('AddToken').instance().state.customDecimals, tokenPrecision) + + }) + + it('next', () => { + const nextButton = wrapper.find('.button.btn-secondary.page-container__footer-button') + nextButton.simulate('click') + + assert(props.setPendingTokens.calledOnce) + assert(props.history.push.calledOnce) + assert.equal(props.history.push.getCall(0).args[0], '/confirm-add-token') + }) + + it('cancels', () => { + const cancelButton = wrapper.find('button.btn-default.page-container__footer-button') + cancelButton.simulate('click') + + assert(props.clearPendingTokens.calledOnce) + assert.equal(props.history.push.getCall(0).args[0], '/') + }) + }) + +}) diff --git a/ui/app/pages/create-account/tests/create-account.test.js b/ui/app/pages/create-account/tests/create-account.test.js new file mode 100644 index 000000000..b68a2241e --- /dev/null +++ b/ui/app/pages/create-account/tests/create-account.test.js @@ -0,0 +1,46 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { mountWithRouter } from '../../../../../test/lib/render-helpers' +import CreateAccountPage from '../index' + +describe('Create Account Page', () => { + let wrapper + + const props = { + history: { + push: sinon.spy(), + }, + location: { + pathname: '/new-account', + }, + } + + before(() => { + wrapper = mountWithRouter( + + ) + }) + + afterEach(() => { + props.history.push.resetHistory() + }) + + it('clicks create account and routes to new-account path', () => { + const createAccount = wrapper.find('.new-account__tabs__tab').at(0) + createAccount.simulate('click') + assert.equal(props.history.push.getCall(0).args[0], '/new-account') + }) + + it('clicks import account and routes to import new account path', () => { + const importAccount = wrapper.find('.new-account__tabs__tab').at(1) + importAccount.simulate('click') + assert.equal(props.history.push.getCall(0).args[0], '/new-account/import') + }) + + it('clicks connect HD Wallet and routes to connect new account path', () => { + const connectHdWallet = wrapper.find('.new-account__tabs__tab').at(2) + connectHdWallet.simulate('click') + assert.equal(props.history.push.getCall(0).args[0], '/new-account/connect') + }) +}) diff --git a/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js b/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js new file mode 100644 index 000000000..23cebc68c --- /dev/null +++ b/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js @@ -0,0 +1,39 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { mountWithRouter } from '../../../../../../test/lib/render-helpers' +import { DEFAULT_ROUTE } from '../../../../helpers/constants/routes' +import EndOfFlowScreen from '../index' + +describe('End of Flow Screen', () => { + let wrapper + + const props = { + history: { + push: sinon.spy(), + }, + completeOnboarding: sinon.spy(), + } + + beforeEach(() => { + wrapper = mountWithRouter( + + ) + }) + + it('renders', () => { + assert.equal(wrapper.length, 1) + }) + + it('', (done) => { + const endOfFlowButton = wrapper.find('.btn-primary.first-time-flow__button') + endOfFlowButton.simulate('click') + + setImmediate(() => { + assert(props.completeOnboarding.calledOnce) + assert(props.history.push.calledOnce) + assert.equal(props.history.push.getCall(0).args[0], DEFAULT_ROUTE) + done() + }) + }) +}) diff --git a/ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js b/ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js new file mode 100644 index 000000000..4c2b60727 --- /dev/null +++ b/ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js @@ -0,0 +1,73 @@ +import React from 'react' +import assert from 'assert' +import { mountWithRouter } from '../../../../../../test/lib/render-helpers' +import { + DEFAULT_ROUTE, + LOCK_ROUTE, + INITIALIZE_WELCOME_ROUTE, + INITIALIZE_UNLOCK_ROUTE, +} from '../../../../helpers/constants/routes' +import FirstTimeFlowSwitch from '../index' + +describe('FirstTimeFlowSwitch', () => { + + it('redirects to /welcome route with no props', () => { + const wrapper = mountWithRouter( + + ) + assert.equal(wrapper.find('Lifecycle').find({ to: { pathname: INITIALIZE_WELCOME_ROUTE } }).length, 1) + }) + + it('redirects to / route when completedOnboarding is true', () => { + const props = { + completedOnboarding: true, + } + const wrapper = mountWithRouter( + + ) + + assert.equal(wrapper.find('Lifecycle').find({ to: { pathname: DEFAULT_ROUTE } }).length, 1) + }) + + it('redirects to /lock route when isUnlocked is true ', () => { + const props = { + completedOnboarding: false, + isUnlocked: true, + } + + const wrapper = mountWithRouter( + + ) + + assert.equal(wrapper.find('Lifecycle').find({ to: { pathname: LOCK_ROUTE } }).length, 1) + }) + + it('redirects to /welcome route when isInitialized is false', () => { + const props = { + completedOnboarding: false, + isUnlocked: false, + isInitialized: false, + } + + const wrapper = mountWithRouter( + + ) + + assert.equal(wrapper.find('Lifecycle').find({ to: { pathname: INITIALIZE_WELCOME_ROUTE } }).length, 1) + }) + + it('redirects to /unlock route when isInitialized is true', () => { + const props = { + completedOnboarding: false, + isUnlocked: false, + isInitialized: true, + } + + const wrapper = mountWithRouter( + + ) + + assert.equal(wrapper.find('Lifecycle').find({ to: { pathname: INITIALIZE_UNLOCK_ROUTE } }).length, 1) + }) + +}) diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js b/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js new file mode 100644 index 000000000..3d70debda --- /dev/null +++ b/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js @@ -0,0 +1,43 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import configureMockStore from 'redux-mock-store' +import { mountWithRouter } from '../../../../../../test/lib/render-helpers' +import MetaMetricsOptIn from '../index' + +describe('MetaMetricsOptIn', () => { + let wrapper + + const props = { + history: { + push: sinon.spy(), + }, + setParticipateInMetaMetrics: sinon.stub().resolves(), + participateInMetaMetrics: false, + } + + const mockStore = { + metamask: {}, + } + + const store = configureMockStore()(mockStore) + + beforeEach(() => { + wrapper = mountWithRouter( + , store + ) + }) + + afterEach(() => { + props.setParticipateInMetaMetrics.resetHistory() + }) + + it('opt out of metametrics', () => { + const noThanksButton = wrapper.find('.btn-default.page-container__footer-button') + noThanksButton.simulate('click') + + assert(props.setParticipateInMetaMetrics.calledOnce) + assert.equal(props.setParticipateInMetaMetrics.getCall(0).args[0], false) + }) + +}) diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js new file mode 100644 index 000000000..41d170b5d --- /dev/null +++ b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js @@ -0,0 +1,48 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { mount } from 'enzyme' +import RevealSeedPhrase from '../index' + +describe('Reveal Seed Phrase', () => { + let wrapper + + const TEST_SEED = 'debris dizzy just program just float decrease vacant alarm reduce speak stadium' + + const props = { + history: { + push: sinon.spy(), + }, + seedPhrase: TEST_SEED, + setSeedPhraseBackedUp: sinon.spy(), + setCompletedOnboarding: sinon.spy(), + } + + beforeEach(() => { + wrapper = mount( + , { + context: { + t: str => str, + metricsEvent: () => {}, + }, + } + ) + }) + + it('seed phrase', () => { + const seedPhrase = wrapper.find('.reveal-seed-phrase__secret-words--hidden') + assert.equal(seedPhrase.length, 1) + assert.equal(seedPhrase.text(), TEST_SEED) + }) + + it('clicks to reveal', () => { + const reveal = wrapper.find('.reveal-seed-phrase__secret-blocker') + + assert.equal(wrapper.state().isShowingSeedPhrase, false) + reveal.simulate('click') + assert.equal(wrapper.state().isShowingSeedPhrase, true) + + const showSeed = wrapper.find('.reveal-seed-phrase__secret-words') + assert.equal(showSeed.length, 1) + }) +}) diff --git a/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js b/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js new file mode 100644 index 000000000..fe88c9a0b --- /dev/null +++ b/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js @@ -0,0 +1,46 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { mountWithRouter } from '../../../../../../test/lib/render-helpers' +import SelectAction from '../index' + +describe('Selection Action', () => { + let wrapper + + const props = { + isInitialized: false, + setFirstTimeFlowType: sinon.spy(), + history: { + push: sinon.spy(), + }, + } + + beforeEach(() => { + wrapper = mountWithRouter( + + ) + }) + + afterEach(() => { + props.setFirstTimeFlowType.resetHistory() + props.history.push.resetHistory() + }) + + it('clicks import wallet to route to import FTF', () => { + const importWalletButton = wrapper.find('.btn-primary.first-time-flow__button').at(0) + importWalletButton.simulate('click') + + assert(props.setFirstTimeFlowType.calledOnce) + assert.equal(props.setFirstTimeFlowType.getCall(0).args[0], 'import') + assert(props.history.push.calledOnce) + }) + + it('clicks create wallet to route to create FTF ', () => { + const createWalletButton = wrapper.find('.btn-primary.first-time-flow__button').at(1) + createWalletButton.simulate('click') + + assert(props.setFirstTimeFlowType.calledOnce) + assert.equal(props.setFirstTimeFlowType.getCall(0).args[0], 'create') + assert(props.history.push.calledOnce) + }) +}) diff --git a/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js b/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js new file mode 100644 index 000000000..3649cef11 --- /dev/null +++ b/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js @@ -0,0 +1,55 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import configureMockStore from 'redux-mock-store' +import { mountWithRouter } from '../../../../../../test/lib/render-helpers' +import Welcome from '../index' + +describe('Welcome', () => { + const mockStore = { + metamask: {}, + } + + const store = configureMockStore()(mockStore) + + after(() => { + sinon.restore() + }) + + it('routes to select action when participateInMetaMetrics is not initialized', () => { + + const props = { + history: { + push: sinon.spy(), + }, + } + + const wrapper = mountWithRouter( + , store + ) + + const getStartedButton = wrapper.find('.btn-primary.first-time-flow__button') + getStartedButton.simulate('click') + assert.equal(props.history.push.getCall(0).args[0], '/initialize/select-action') + + }) + + it('routes to correct password when participateInMetaMetrics is initialized', () => { + + const props = { + welcomeScreenSeen: true, + participateInMetaMetrics: false, + history: { + push: sinon.spy(), + }, + } + + const wrapper = mountWithRouter( + , store + ) + + const getStartedButton = wrapper.find('.btn-primary.first-time-flow__button') + getStartedButton.simulate('click') + assert.equal(props.history.push.getCall(0).args[0], '/initialize/create-password') + }) +}) diff --git a/ui/app/pages/keychains/tests/reveal-seed.test.js b/ui/app/pages/keychains/tests/reveal-seed.test.js new file mode 100644 index 000000000..f63c5ae03 --- /dev/null +++ b/ui/app/pages/keychains/tests/reveal-seed.test.js @@ -0,0 +1,31 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { mount } from 'enzyme' +import RevealSeedPage from '../reveal-seed' + +describe('Reveal Seed Page', () => { + let wrapper + + const props = { + history: { + push: sinon.spy(), + }, + requestRevealSeedWords: sinon.stub().resolves(), + } + + beforeEach(() => { + wrapper = mount( + , { + context: { + t: str => str, + }, + } + ) + }) + + it('form submit', () => { + wrapper.find('form').simulate('submit') + assert(props.requestRevealSeedWords.calledOnce) + }) +}) diff --git a/ui/app/pages/lock/tests/lock.test.js b/ui/app/pages/lock/tests/lock.test.js new file mode 100644 index 000000000..ba412ebf8 --- /dev/null +++ b/ui/app/pages/lock/tests/lock.test.js @@ -0,0 +1,48 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { mountWithRouter } from '../../../../../test/lib/render-helpers' +import Lock from '../index' + +describe('Lock', () => { + + it('replaces history with default route when isUnlocked false', () => { + + const props = { + isUnlocked: false, + history: { + replace: sinon.spy(), + }, + } + + mountWithRouter( + + ) + + assert.equal(props.history.replace.getCall(0).args[0], '/') + + }) + + it('locks and pushes history with default route when isUnlocked true', (done) => { + + const props = { + isUnlocked: true, + lockMetamask: sinon.stub(), + history: { + push: sinon.spy(), + }, + } + + props.lockMetamask.resolves() + + mountWithRouter( + + ) + + assert(props.lockMetamask.calledOnce) + setImmediate(() => { + assert.equal(props.history.push.getCall(0).args[0], '/') + done() + }) + }) +}) diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/test/gas-fee-display.component.test.js b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js similarity index 100% rename from ui/app/pages/send/send-content/send-gas-row/gas-fee-display/test/gas-fee-display.component.test.js rename to ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js diff --git a/ui/app/pages/settings/security-tab/tests/security-tab.test.js b/ui/app/pages/settings/security-tab/tests/security-tab.test.js new file mode 100644 index 000000000..51080cb54 --- /dev/null +++ b/ui/app/pages/settings/security-tab/tests/security-tab.test.js @@ -0,0 +1,55 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { mount } from 'enzyme' +import SecurityTab from '../index' + +describe('Security Tab', () => { + let wrapper + + const props = { + revealSeedConfirmation: sinon.spy(), + showClearApprovalModal: sinon.spy(), + setParticipateInMetaMetrics: sinon.spy(), + displayWarning: sinon.spy(), + setShowIncomingTransactionsFeatureFlag: sinon.spy(), + history: { + push: sinon.spy(), + }, + privacyMode: true, + warning: '', + participateInMetaMetrics: false, + } + + beforeEach(() => { + wrapper = mount( + , { + context: { + t: str => str, + metricsEvent: () => {}, + }, + } + ) + }) + + it('navigates to reveal seed words page', () => { + const seedWords = wrapper.find('.button.btn-danger.btn--large') + + seedWords.simulate('click') + assert(props.history.push.calledOnce) + assert.equal(props.history.push.getCall(0).args[0], '/seed') + }) + + it('toggles incoming txs', () => { + const incomingTxs = wrapper.find({ type: 'checkbox' }).at(0) + incomingTxs.simulate('click') + assert(props.setShowIncomingTransactionsFeatureFlag.calledOnce) + }) + + it('toggles metaMetrics', () => { + const metaMetrics = wrapper.find({ type: 'checkbox' }).at(1) + + metaMetrics.simulate('click') + assert(props.setParticipateInMetaMetrics.calledOnce) + }) +}) diff --git a/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js b/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js new file mode 100644 index 000000000..6481b908d --- /dev/null +++ b/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js @@ -0,0 +1,61 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { mount } from 'enzyme' +import SettingsTab from '../index' + +describe('Settings Tab', () => { + let wrapper + + const props = { + setCurrentCurrency: sinon.spy(), + displayWarning: sinon.spy(), + setUseBlockie: sinon.spy(), + updateCurrentLocale: sinon.spy(), + setUseNativeCurrencyAsPrimaryCurrencyPreference: sinon.spy(), + warning: '', + currentLocale: 'en', + useBlockie: false, + currentCurrency: 'usd', + conversionDate: 1, + nativeCurrency: 'eth', + useNativeCurrencyAsPrimaryCurrency: true, + } + beforeEach(() => { + wrapper = mount( + , { + context: { + t: str => str, + }, + } + ) + }) + + it('selects currency', async () => { + const selectCurrency = wrapper.find({ placeholder: 'selectCurrency' }) + + selectCurrency.props().onSelect('eur') + assert(props.setCurrentCurrency.calledOnce) + }) + + it('selects locale', async () => { + const selectLocale = wrapper.find({ placeholder: 'selectLocale' }) + + await selectLocale.props().onSelect('ja') + assert(props.updateCurrentLocale.calledOnce) + }) + + it('sets fiat primary currency', () => { + const selectFiat = wrapper.find('#fiat-primary-currency') + + selectFiat.simulate('change') + assert(props.setUseNativeCurrencyAsPrimaryCurrencyPreference.calledOnce) + }) + + it('toggles blockies', () => { + const toggleBlockies = wrapper.find({ type: 'checkbox' }) + + toggleBlockies.simulate('click') + assert(props.setUseBlockie.calledOnce) + }) +}) diff --git a/ui/app/pages/unlock-page/tests/unlock-page.test.js b/ui/app/pages/unlock-page/tests/unlock-page.test.js new file mode 100644 index 000000000..8b1e05729 --- /dev/null +++ b/ui/app/pages/unlock-page/tests/unlock-page.test.js @@ -0,0 +1,69 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { mount } from 'enzyme' +import UnlockPage from '../index' + +describe('Unlock Page', () => { + let wrapper + + const props = { + history: { + push: sinon.spy(), + }, + isUnlocked: false, + onImport: sinon.spy(), + onRestore: sinon.spy(), + onSubmit: sinon.spy(), + forceUpdateMetamaskState: sinon.spy(), + showOptInModal: sinon.spy(), + } + + + beforeEach(() => { + + wrapper = mount( + , { + context: { + t: str => str, + }, + } + ) + + }) + + after(() => { + sinon.restore() + }) + + it('renders', () => { + assert.equal(wrapper.length, 1) + }) + + it('changes password and submits', () => { + const passwordField = wrapper.find({ type: 'password', id: 'password' }) + const loginButton = wrapper.find({ type: 'submit' }).last() + + const event = { target: { value: 'password' } } + assert.equal(wrapper.instance().state.password, '') + passwordField.last().simulate('change', event) + assert.equal(wrapper.instance().state.password, 'password') + + loginButton.simulate('click') + assert(props.onSubmit.calledOnce) + }) + + it('clicks imports seed button', () => { + const importSeedButton = wrapper.find('.unlock-page__link--import') + + importSeedButton.simulate('click') + assert(props.onImport.calledOnce) + + }) + + it('clicks restore', () => { + const restoreFromSeedButton = wrapper.find('.unlock-page__link').at(0) + restoreFromSeedButton.simulate('click') + assert(props.onRestore.calledOnce) + }) +}) diff --git a/ui/app/pages/unlock-page/unlock-page.component.js b/ui/app/pages/unlock-page/unlock-page.component.js index 346257a3a..2b6916bd7 100644 --- a/ui/app/pages/unlock-page/unlock-page.component.js +++ b/ui/app/pages/unlock-page/unlock-page.component.js @@ -94,13 +94,15 @@ export default class UnlockPage extends Component { this.setState({ password: target.value, error: null }) // tell mascot to look at page action - const element = target - const boundingRect = element.getBoundingClientRect() - const coordinates = getCaretCoordinates(element, element.selectionEnd) - this.animationEventEmitter.emit('point', { - x: boundingRect.left + coordinates.left - element.scrollLeft, - y: boundingRect.top + coordinates.top - element.scrollTop, - }) + if (target.getBoundingClientRect) { + const element = target + const boundingRect = element.getBoundingClientRect() + const coordinates = getCaretCoordinates(element, element.selectionEnd) + this.animationEventEmitter.emit('point', { + x: boundingRect.left + coordinates.left - element.scrollLeft, + y: boundingRect.top + coordinates.top - element.scrollTop, + }) + } } renderSubmitButton () { diff --git a/ui/app/selectors/tests/confirm-transaction.test.js b/ui/app/selectors/tests/confirm-transaction.test.js new file mode 100644 index 000000000..db8772868 --- /dev/null +++ b/ui/app/selectors/tests/confirm-transaction.test.js @@ -0,0 +1,159 @@ +import assert from 'assert' +import { + unconfirmedTransactionsCountSelector, + tokenAmountAndToAddressSelector, + approveTokenAmountAndToAddressSelector, + sendTokenTokenAmountAndToAddressSelector, + contractExchangeRateSelector, +} from '../confirm-transaction' + +describe('Confirm Transaction Selector', () => { + + describe('unconfirmedTransactionsCountSelector', () => { + + const state = { + metamask: { + unapprovedTxs: { + 1: { + metamaskNetworkId: 'test', + }, + 2: { + metmaskNetworkId: 'other network', + }, + }, + unapprovedMsgCount: 1, + unapprovedPersonalMsgCount: 1, + unapprovedTypedMessagesCount: 1, + network: 'test', + }, + } + + it('returns number of txs in unapprovedTxs state with the same network plus unapproved signing method counts', () => { + assert.equal(unconfirmedTransactionsCountSelector(state), 4) + }) + + }) + + describe('tokenAmountAndToAddressSelector', () => { + + const state = { + confirmTransaction: { + tokenData: { + name: 'transfer', + params: [ + { + name: '_to', + value: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + type: 'address', + }, + { + name: '_value', + value: '1', + type: 'uint256', + }, + ], + }, + tokenProps: { + tokenDecimals: '2', + tokenSymbol: 'META', + }, + }, + } + + it('returns calulcated token amount based on token value and token decimals and recipient address', () => { + assert.deepEqual(tokenAmountAndToAddressSelector(state), + { toAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', tokenAmount: 0.01 }) + }) + + }) + + describe('approveTokenAmountAndToAddressSelector', () => { + + const state = { + confirmTransaction: { + tokenData: { + name: 'approve', + params: [ + { + name: '_spender', + value: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + type: 'address', + }, + { + name: '_value', + value: '1', + type: 'uint256', + }, + ], + }, + tokenProps: { + tokenDecimals: '2', + tokenSymbol: 'META', + }, + }, + } + + it('returns token amount and recipient for approve token allocation spending', () => { + assert.deepEqual(approveTokenAmountAndToAddressSelector(state), + { toAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', tokenAmount: 0.01 }) + }) + + }) + + describe('sendTokenTokenAmountAndToAddressSelector', () => { + + const state = { + confirmTransaction: { + tokenData: { + name: 'transfer', + params: [ + { + name: '_to', + value: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + type: 'address', + }, + { + name: '_value', + value: '1', + type: 'uint256', + }, + ], + }, + tokenProps: { + tokenDecimals: '2', + tokenSymbol: 'META', + }, + }, + } + + it('returns token address and calculated token amount', () => { + assert.deepEqual(sendTokenTokenAmountAndToAddressSelector(state), + { toAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', tokenAmount: 0.01 }) + }) + + }) + + describe('contractExchangeRateSelector', () => { + + const state = { + metamask: { + contractExchangeRates: { + '0xTokenAddress': '10', + }, + }, + confirmTransaction: { + txData: { + txParams: { + to: '0xTokenAddress', + }, + }, + }, + } + + it('returns contract exchange rate in metamask state based on confirm transaction txParams token recipient', () => { + assert.equal(contractExchangeRateSelector(state), 10) + }) + + }) +}) + diff --git a/ui/app/selectors/tests/tokens.test.js b/ui/app/selectors/tests/tokens.test.js new file mode 100644 index 000000000..d058f4a05 --- /dev/null +++ b/ui/app/selectors/tests/tokens.test.js @@ -0,0 +1,28 @@ +import assert from 'assert' +import { selectedTokenSelector } from '../tokens' + +const metaToken = { + 'address': '0x617b3f8050a0bd94b6b1da02b4384ee5b4df13f4', + 'symbol': 'META', + 'decimals': 18, +} + +const state = { + metamask: { + selectedTokenAddress: '0x617b3f8050a0bd94b6b1da02b4384ee5b4df13f4', + tokens: [ + { + 'address': '0x06012c8cf97bead5deae237070f9587f8e7a266d', + 'symbol': 'CK', + 'decimals': 0, + }, + metaToken, + ], + }, +} +describe('Selected Token Selector', () => { + it('selects token info from tokens based on selectedTokenAddress in state', () => { + const tokenInfo = selectedTokenSelector(state) + assert.equal(tokenInfo, metaToken) + }) +}) diff --git a/ui/app/selectors/tests/transactions.test.js b/ui/app/selectors/tests/transactions.test.js new file mode 100644 index 000000000..3ab1be47c --- /dev/null +++ b/ui/app/selectors/tests/transactions.test.js @@ -0,0 +1,356 @@ +import assert from 'assert' +import { + unapprovedMessagesSelector, + transactionsSelector, + nonceSortedTransactionsSelector, + nonceSortedPendingTransactionsSelector, + nonceSortedCompletedTransactionsSelector, + submittedPendingTransactionsSelector, +} from '../transactions' + +describe('Transaction Selectors', () => { + + describe('unapprovedMessagesSelector', () => { + it('returns eth sign msg from unapprovedMsgs', () => { + + const msg = { + id: 1, + msgParams: { + from: '0xAddress', + data: '0xData', + origin: 'origin', + }, + time: 1, + status: 'unapproved', + type: 'eth_sign', + } + + const state = { + metamask: { + unapprovedMsgs: { + 1: msg, + }, + }, + } + + const msgSelector = unapprovedMessagesSelector(state) + + assert(Array.isArray(msgSelector)) + assert.deepEqual(msgSelector, [msg]) + }) + + it('returns personal sign from unapprovedPersonalMsgsSelector', () => { + + const msg = { + id: 1, + msgParams: { + from: '0xAddress', + data: '0xData', + origin: 'origin', + }, + time: 1, + status: 'unapproved', + type: 'personal_sign', + } + + const state = { + metamask: { + unapprovedPersonalMsgs: { + 1: msg, + }, + }, + } + + const msgSelector = unapprovedMessagesSelector(state) + + assert(Array.isArray(msgSelector)) + assert.deepEqual(msgSelector, [msg]) + }) + + it('returns typed message from unapprovedTypedMessagesSelector', () => { + + const msg = { + id: 1, + msgParams: { + data: '0xData', + from: '0xAddress', + version: 'V3', + origin: 'origin', + }, + time: 1, + status: 'unapproved', + type: 'eth_signTypedData', + } + + const state = { + metamask: { + unapprovedTypedMessages: { + 1: msg, + }, + }, + } + + const msgSelector = unapprovedMessagesSelector(state) + + assert(Array.isArray(msgSelector)) + assert.deepEqual(msgSelector, [msg]) + + }) + }) + + describe('transactionsSelector', () => { + + it('selectedAddressTxList', () => { + + const state = { + metamask: { + featureFlags: { + showIncomingTransactions: false, + }, + selectedAddressTxList: [ + { + id: 0, + time: 0, + txParams: { + from: '0xAddress', + to: '0xRecipient', + }, + }, + { + id: 1, + time: 1, + txParams: { + from: '0xAddress', + to: '0xRecipient', + }, + }, + ], + }, + } + + const orderedTxlist = state.metamask.selectedAddressTxList.sort((a, b) => b.time - a.time) + + const txSelector = transactionsSelector(state) + + assert(Array.isArray(txSelector)) + assert.deepEqual(txSelector, orderedTxlist) + }) + + it('returns token tx from selectedAddressTxList when selectedTokenAddress is valid', () => { + + const state = { + metamask: { + featureFlags: { + showIncomingTransactions: false, + }, + selectedTokenAddress: '0xToken', + selectedAddressTxList: [ + { + id: 0, + time: 0, + txParams: { + from: '0xAddress', + to: '0xToken', + }, + }, + { + id: 1, + time: 1, + txParams: { + from: '0xAddress', + to: '0xToken', + }, + }, + ], + }, + + } + + const orderedTxlist = state.metamask.selectedAddressTxList.sort((a, b) => b.time - a.time) + + const txSelector = transactionsSelector(state) + + assert(Array.isArray(txSelector)) + assert.deepEqual(txSelector, orderedTxlist) + + }) + + }) + + describe('nonceSortedTransactionsSelector', () => { + + it('returns transaction group nonce sorted tx from from selectedTxList wit', () => { + + const tx1 = { + id: 0, + time: 0, + txParams: { + from: '0xAddress', + to: '0xRecipient', + nonce: '0x0', + }, + } + + const tx2 = { + id: 1, + time: 1, + txParams: { + from: '0xAddress', + to: '0xRecipient', + nonce: '0x1', + }, + } + + const state = { + metamask: { + featureFlags: { + showIncomingTransactions: false, + }, + selectedAddressTxList: [ + tx1, + tx2, + ], + }, + } + + const expectedResult = [ + { + nonce: '0x0', + transactions: [ tx1 ], + initialTransaction: tx1, + primaryTransaction: tx1, + hasRetried: false, + hasCancelled: false, + }, + { + nonce: '0x1', + transactions: [ tx2 ], + initialTransaction: tx2, + primaryTransaction: tx2, + hasRetried: false, + hasCancelled: false, + }, + ] + + assert.deepEqual(nonceSortedTransactionsSelector(state), expectedResult) + }) + }) + + describe('Sorting Transactions Selectors', () => { + + const submittedTx = { + id: 0, + time: 0, + txParams: { + from: '0xAddress', + to: '0xRecipient', + nonce: '0x0', + }, + status: 'submitted', + } + + const unapprovedTx = { + id: 1, + time: 1, + txParams: { + from: '0xAddress', + to: '0xRecipient', + nonce: '0x1', + }, + status: 'unapproved', + } + + const approvedTx = { + id: 2, + time: 2, + txParams: { + from: '0xAddress', + to: '0xRecipient', + nonce: '0x2', + }, + status: 'approved', + } + + const confirmedTx = { + id: 3, + time: 3, + txParams: { + from: '0xAddress', + to: '0xRecipient', + nonce: '0x3', + }, + status: 'confirmed', + } + + const state = { + metamask: { + featureFlags: { + showIncomingTransactions: false, + }, + selectedAddressTxList: [ + submittedTx, + unapprovedTx, + approvedTx, + confirmedTx, + ], + }, + } + + it('nonceSortedPendingTransactionsSelector', () => { + + const expectedResult = [ + { + nonce: submittedTx.txParams.nonce, + transactions: [ submittedTx ], + initialTransaction: submittedTx, + primaryTransaction: submittedTx, + hasRetried: false, + hasCancelled: false, + }, + { + nonce: unapprovedTx.txParams.nonce, + transactions: [ unapprovedTx ], + initialTransaction: unapprovedTx, + primaryTransaction: unapprovedTx, + hasRetried: false, + hasCancelled: false, + }, + { + nonce: approvedTx.txParams.nonce, + transactions: [ approvedTx ], + initialTransaction: approvedTx, + primaryTransaction: approvedTx, + hasRetried: false, + hasCancelled: false, + }, + ] + + assert.deepEqual(nonceSortedPendingTransactionsSelector(state), expectedResult) + }) + + it('nonceSortedCompletedTransactionsSelector', () => { + + const expectedResult = [ + { + nonce: confirmedTx.txParams.nonce, + transactions: [ confirmedTx ], + initialTransaction: confirmedTx, + primaryTransaction: confirmedTx, + hasRetried: false, + hasCancelled: false, + }, + ] + + assert.deepEqual(nonceSortedCompletedTransactionsSelector(state), expectedResult) + }) + + it('submittedPendingTransactionsSelector', () => { + + const expectedResult = [ submittedTx ] + assert.deepEqual(submittedPendingTransactionsSelector(state), expectedResult) + + }) + + }) + +}) From 6747b7f02ddb742ed2a884b2e724b6785a5190be Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 30 Jan 2020 18:30:56 -0330 Subject: [PATCH 229/689] Update ethereum-ens-network-map in lockfile (#7959) * Update yarn.lock cross-spawn versions * Use ethereum-ens-network-map@1.0.2 --- yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 232efa3f3..33e57ec82 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7913,7 +7913,7 @@ cross-spawn@^4: lru-cache "^4.0.1" which "^1.2.9" -cross-spawn@^5.0.1, cross-spawn@^5.1.0: +cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= @@ -10815,9 +10815,9 @@ ethereum-common@^0.0.18: integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= ethereum-ens-network-map@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ethereum-ens-network-map/-/ethereum-ens-network-map-1.0.0.tgz#43cd7669ce950a789e151001118d4d65f210eeb7" - integrity sha1-Q812ac6VCnieFRABEY1NZfIQ7rc= + version "1.0.2" + resolved "https://registry.yarnpkg.com/ethereum-ens-network-map/-/ethereum-ens-network-map-1.0.2.tgz#4e27bad18dae7bd95d84edbcac2c9e739fc959b9" + integrity sha512-5qwJ5n3YhjSpE6O/WEBXCAb2nagUgyagJ6C0lGUBWC4LjKp/rRzD+pwtDJ6KCiITFEAoX4eIrWOjRy0Sylq5Hg== ethereumjs-abi@0.6.5, ethereumjs-abi@^0.6.4, ethereumjs-abi@^0.6.5: version "0.6.5" From b80afc6493d887af19a168a9d0e775ca3754fc17 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 31 Jan 2020 09:56:50 -0330 Subject: [PATCH 230/689] Use ethereum-ens-network-map for network support (#7960) --- app/scripts/controllers/ens/ens.js | 2 +- package.json | 1 + .../send/send-content/add-recipient/ens-input.component.js | 2 +- yarn.lock | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/scripts/controllers/ens/ens.js b/app/scripts/controllers/ens/ens.js index e57d16bc6..becdb148a 100644 --- a/app/scripts/controllers/ens/ens.js +++ b/app/scripts/controllers/ens/ens.js @@ -1,5 +1,5 @@ import EthJsEns from 'ethjs-ens' -import ensNetworkMap from 'ethjs-ens/lib/network-map.json' +import ensNetworkMap from 'ethereum-ens-network-map' class Ens { static getNetworkEnsSupport (network) { diff --git a/package.json b/package.json index c02cb393e..e5715b4f8 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,7 @@ "eth-sig-util": "^2.3.0", "eth-token-tracker": "^1.1.10", "eth-trezor-keyring": "^0.4.0", + "ethereum-ens-network-map": "^1.0.2", "ethereumjs-abi": "^0.6.4", "ethereumjs-tx": "1.3.7", "ethereumjs-util": "5.1.0", diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js index 4efea98de..f0b14516c 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js +++ b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js @@ -7,7 +7,7 @@ import { ellipsify } from '../../send.utils' import { debounce } from 'lodash' import copyToClipboard from 'copy-to-clipboard/index' import ENS from 'ethjs-ens' -import networkMap from 'ethjs-ens/lib/network-map.json' +import networkMap from 'ethereum-ens-network-map' import log from 'loglevel' diff --git a/yarn.lock b/yarn.lock index 33e57ec82..789f5a236 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10814,7 +10814,7 @@ ethereum-common@^0.0.18: resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= -ethereum-ens-network-map@^1.0.0: +ethereum-ens-network-map@^1.0.0, ethereum-ens-network-map@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/ethereum-ens-network-map/-/ethereum-ens-network-map-1.0.2.tgz#4e27bad18dae7bd95d84edbcac2c9e739fc959b9" integrity sha512-5qwJ5n3YhjSpE6O/WEBXCAb2nagUgyagJ6C0lGUBWC4LjKp/rRzD+pwtDJ6KCiITFEAoX4eIrWOjRy0Sylq5Hg== From d6009bbfb7fe1fd72265c5cd627f7d28bf832a95 Mon Sep 17 00:00:00 2001 From: Alice Henshaw <34962750+alicevhenshaw@users.noreply.github.com> Date: Mon, 3 Feb 2020 15:15:53 -0500 Subject: [PATCH 231/689] Updating deprecated Etherscam link (#7464) Co-authored-by: Whymarrh Whitby --- app/phishing.html | 2 +- app/scripts/phishing-detect.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/phishing.html b/app/phishing.html index 1e1c4d11c..515beea81 100644 --- a/app/phishing.html +++ b/app/phishing.html @@ -47,7 +47,7 @@ Ethereum Phishing Detector. Domains on these warning lists may include outright malicious websites and legitimate websites that have been compromised by a malicious actor.

    -

    To read more about this site please review the domain on Etherscam.

    +

    To read more about this site please search for the domain on CryptoScamDB.

    Note that this warning list is compiled on a voluntary basis. This list may be inaccurate or incomplete. Just because a domain does not appear on this list is not an implicit guarantee of that domain's safety. diff --git a/app/scripts/phishing-detect.js b/app/scripts/phishing-detect.js index 554e4bbbb..112b1b0b0 100644 --- a/app/scripts/phishing-detect.js +++ b/app/scripts/phishing-detect.js @@ -14,7 +14,7 @@ function start () { const hash = window.location.hash.substring(1) const suspect = querystring.parse(hash) - document.getElementById('esdbLink').href = `https://etherscamdb.info/domain/${suspect.hostname}` + document.getElementById('csdbLink').href = `https://cryptoscamdb.org/search` global.platform = new ExtensionPlatform() global.METAMASK_UI_TYPE = windowType From 313ee0c5e1a4fe5f079ccc8425138938b22e5e25 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 4 Feb 2020 10:39:59 -0330 Subject: [PATCH 232/689] Use envify@4.1.0 (#7983) --- package.json | 2 +- yarn.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e5715b4f8..7b36bfef1 100644 --- a/package.json +++ b/package.json @@ -203,7 +203,7 @@ "css-loader": "^2.1.1", "del": "^3.0.0", "deps-dump": "^1.1.0", - "envify": "^4.0.0", + "envify": "^4.1.0", "enzyme": "^3.10.0", "enzyme-adapter-react-16": "^1.15.1", "eslint": "^6.0.1", diff --git a/yarn.lock b/yarn.lock index 789f5a236..b4981e4a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9767,7 +9767,7 @@ env-paths@^1.0.0: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0" integrity sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA= -envify@^4.0.0: +envify@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/envify/-/envify-4.1.0.tgz#f39ad3db9d6801b4e6b478b61028d3f0b6819f7e" integrity sha512-IKRVVoAYr4pIx4yIWNsz9mOsboxlNXiu7TNBnem/K/uTHdkyzXWDzHCK7UTolqBbgaBz0tQHsD3YNls0uIIjiw== From 8610c1cf4708ebf1dfbea8383c4fd7a02ad75eac Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 4 Feb 2020 10:41:10 -0330 Subject: [PATCH 233/689] Use eth-json-rpc-infura@4.0.2 (#7981) --- package.json | 2 +- yarn.lock | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 7b36bfef1..4a18cfe5f 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "eth-ens-namehash": "^2.0.8", "eth-json-rpc-errors": "^2.0.0", "eth-json-rpc-filters": "^4.1.1", - "eth-json-rpc-infura": "^4.0.1", + "eth-json-rpc-infura": "^4.0.2", "eth-json-rpc-middleware": "^4.4.0", "eth-keyring-controller": "^5.3.0", "eth-ledger-bridge-keyring": "^0.2.0", diff --git a/yarn.lock b/yarn.lock index b4981e4a1..0d995f35a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10555,16 +10555,15 @@ eth-json-rpc-infura@^3.1.0: json-rpc-error "^2.0.0" tape "^4.8.0" -eth-json-rpc-infura@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-4.0.1.tgz#41159b7e90cb0a5a3d75e855339a05639ed4aa6d" - integrity sha512-7pZfz6bKy4KO5mYVZ1dqsqaTsbo0sQUNo4C11NuTJ0BPjzNRJpQhBTNgRpK0Hpys0jJe898KYqdSWxuaWuc18A== +eth-json-rpc-infura@^4.0.1, eth-json-rpc-infura@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-4.0.2.tgz#8af1a1a2e9a0a82aaa302bbc96fb1a4c15d69b83" + integrity sha512-dvgOrci9lZqpjpp0hoC3Zfedhg3aIpLFVDH0TdlKxRlkhR75hTrKTwxghDrQwE0bn3eKrC8RsN1m/JdnIWltpw== dependencies: cross-fetch "^2.1.1" eth-json-rpc-errors "^1.0.1" eth-json-rpc-middleware "^4.1.4" json-rpc-engine "^5.1.3" - tape "^4.8.0" eth-json-rpc-middleware@^1.5.0: version "1.6.0" From 75769e580995209a02a497dad7a38a8ae52c7b93 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 4 Feb 2020 10:41:34 -0330 Subject: [PATCH 234/689] Use eth-keyring-controller@5.5.0 (#7980) --- package.json | 2 +- yarn.lock | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 4a18cfe5f..06794d9dc 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "eth-json-rpc-filters": "^4.1.1", "eth-json-rpc-infura": "^4.0.2", "eth-json-rpc-middleware": "^4.4.0", - "eth-keyring-controller": "^5.3.0", + "eth-keyring-controller": "^5.5.0", "eth-ledger-bridge-keyring": "^0.2.0", "eth-method-registry": "^1.2.0", "eth-phishing-detect": "^1.1.4", diff --git a/yarn.lock b/yarn.lock index 0d995f35a..aaf546002 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10504,14 +10504,14 @@ eth-ens-namehash@^1.0.2: idna-uts46 "^1.0.1" js-sha3 "^0.5.7" -eth-hd-keyring@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/eth-hd-keyring/-/eth-hd-keyring-3.4.0.tgz#288e73041f2b3f047b4151fb4b5ab5ad5710b9a6" - integrity sha512-MMKSSwDWuEfItEM/826LHrs2HVjy57qQQfcgSxIYOCJY0vykw++LH8d6QJOBrGFe+xu/gtbHBRMURrFGdqfevw== +eth-hd-keyring@^3.4.0, eth-hd-keyring@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/eth-hd-keyring/-/eth-hd-keyring-3.5.0.tgz#3976d83a27b24305481c389178f290d9264e839d" + integrity sha512-Ix1LcWYxHMxCCSIMz+TLXLtt50zF6ZDd/TRVXthdw91IwOk1ajuf7QHg3bCDcfeUpdf9oEpwIPbL3xjDqEEjYw== dependencies: bip39 "^2.2.0" eth-sig-util "^2.4.4" - eth-simple-keyring "^3.4.0" + eth-simple-keyring "^3.5.0" ethereumjs-abi "^0.6.5" ethereumjs-util "^5.1.1" ethereumjs-wallet "^0.6.0" @@ -10624,17 +10624,17 @@ eth-json-rpc-middleware@^4.4.0: pify "^3.0.0" safe-event-emitter "^1.0.1" -eth-keyring-controller@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-5.3.0.tgz#8d85a67b894360ab7d601222ca71df8ed5f456c6" - integrity sha512-aoqYjKUbdOSgS1s63IsTp69QAMtLPTCqR4VAbCULps71o3yuaA9JRx2W+GAxqVNBtIdyZllxoOJlvErkO4iWNw== +eth-keyring-controller@^5.3.0, eth-keyring-controller@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-5.5.0.tgz#f8b78f69a0b0005873af2d1a6b2c655d6de51351" + integrity sha512-kWaukiHLMYNYtB/1vZyj1r1G6wU8u+DIYVMq8QUyFAxwcBnemsKISVPIXgltgXkuUiB/t9oXsA54bWBredgrVg== dependencies: bip39 "^2.4.0" bluebird "^3.5.0" browser-passworder "^2.0.3" - eth-hd-keyring "^3.4.0" + eth-hd-keyring "^3.5.0" eth-sig-util "^1.4.0" - eth-simple-keyring "^3.4.0" + eth-simple-keyring "^3.5.0" ethereumjs-util "^5.1.2" loglevel "^1.5.0" obs-store "^4.0.3" @@ -10740,10 +10740,10 @@ eth-sig-util@^2.4.4, eth-sig-util@^2.5.0: tweetnacl "^1.0.0" tweetnacl-util "^0.15.0" -eth-simple-keyring@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/eth-simple-keyring/-/eth-simple-keyring-3.4.0.tgz#01464234b070af42a343a3c451dd58b00ae1a042" - integrity sha512-g/ObWqWaTHikrhhm7fNinpkkpEPqBRz02oBXcH81mc3VFkOLb3pjfvNg1Da6Jh+A4wA0kBE4vkiiG7BUwF1zNg== +eth-simple-keyring@^3.4.0, eth-simple-keyring@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/eth-simple-keyring/-/eth-simple-keyring-3.5.0.tgz#c7fa285ca58d31ef44bc7db678b689f9ffd7b453" + integrity sha512-z9IPt9aoMWAw5Zc3Jk/HKbWPJNc7ivZ5ECNtl3ZoQUGRnwoWO71W5+liVPJtXFNacGOOGsBfqTqrXL9C4EnYYQ== dependencies: eth-sig-util "^2.5.0" ethereumjs-abi "^0.6.5" From 2aa22fa9d7c0b97ef58a2380fa2301b363935087 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 4 Feb 2020 11:04:21 -0330 Subject: [PATCH 235/689] Use gulp@4.0.2 (#7982) --- package.json | 2 +- yarn.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 06794d9dc..8885e6d4f 100644 --- a/package.json +++ b/package.json @@ -220,7 +220,7 @@ "ganache-core": "2.8.0", "geckodriver": "^1.19.1", "get-port": "^5.1.0", - "gulp": "^4.0.0", + "gulp": "^4.0.2", "gulp-autoprefixer": "^5.0.0", "gulp-babel": "^7.0.0", "gulp-debug": "^3.2.0", diff --git a/yarn.lock b/yarn.lock index aaf546002..516e1eef7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13667,7 +13667,7 @@ gulp-zip@^4.0.0: vinyl "^2.1.0" yazl "^2.1.0" -gulp@^4.0.0, gulp@^4.0.2: +gulp@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/gulp/-/gulp-4.0.2.tgz#543651070fd0f6ab0a0650c6a3e6ff5a7cb09caa" integrity sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA== From 59937fe35a5f69a5151c26651137481bf66eac92 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 4 Feb 2020 11:24:03 -0330 Subject: [PATCH 236/689] Remove redundant eth-*-keyring versions from yarn.lock (#7984) --- yarn.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index 516e1eef7..9e47248d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10504,7 +10504,7 @@ eth-ens-namehash@^1.0.2: idna-uts46 "^1.0.1" js-sha3 "^0.5.7" -eth-hd-keyring@^3.4.0, eth-hd-keyring@^3.5.0: +eth-hd-keyring@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/eth-hd-keyring/-/eth-hd-keyring-3.5.0.tgz#3976d83a27b24305481c389178f290d9264e839d" integrity sha512-Ix1LcWYxHMxCCSIMz+TLXLtt50zF6ZDd/TRVXthdw91IwOk1ajuf7QHg3bCDcfeUpdf9oEpwIPbL3xjDqEEjYw== @@ -10740,7 +10740,7 @@ eth-sig-util@^2.4.4, eth-sig-util@^2.5.0: tweetnacl "^1.0.0" tweetnacl-util "^0.15.0" -eth-simple-keyring@^3.4.0, eth-simple-keyring@^3.5.0: +eth-simple-keyring@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/eth-simple-keyring/-/eth-simple-keyring-3.5.0.tgz#c7fa285ca58d31ef44bc7db678b689f9ffd7b453" integrity sha512-z9IPt9aoMWAw5Zc3Jk/HKbWPJNc7ivZ5ECNtl3ZoQUGRnwoWO71W5+liVPJtXFNacGOOGsBfqTqrXL9C4EnYYQ== From 6969e3984b23e509955fac97b5041b464b0d8dea Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Tue, 4 Feb 2020 14:49:53 -0800 Subject: [PATCH 237/689] Fixes #5706 - Adds Dai/Sai to currency display (#7986) With the change from infura to cryptocompare https://github.com/MetaMask/gaba/pull/30/files#diff-50c3c47cc5fa12e5213a6cc900476f41L41-R48 we have numerous conversion rates to go through and add if we like to. --- ui/app/helpers/constants/available-conversions.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ui/app/helpers/constants/available-conversions.json b/ui/app/helpers/constants/available-conversions.json index 37da642da..913e8795f 100644 --- a/ui/app/helpers/constants/available-conversions.json +++ b/ui/app/helpers/constants/available-conversions.json @@ -238,5 +238,13 @@ { "code": "zec", "name": "Zcash" + }, + { + "code": "dai", + "name": "DAI" + }, + { + "code": "sai", + "name": "SAI" } ] From 25bcdfcac82740a655b9ee3b02f0b7cedaaab3be Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 5 Feb 2020 09:45:46 -0330 Subject: [PATCH 238/689] Fix SendAmountRow tests (#7968) * Rewrite SendAmountRow tests to avoid flakiness * Use sinon@5.0.1 * Dedupe supports-color versions --- .../tests/send-amount-row-component.test.js | 226 +++++++++--------- yarn.lock | 44 ++-- 2 files changed, 127 insertions(+), 143 deletions(-) diff --git a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js index 41474acf2..f1ef75bc9 100644 --- a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js @@ -8,100 +8,55 @@ import SendRowWrapper from '../../send-row-wrapper/send-row-wrapper.component' import AmountMaxButton from '../amount-max-button/amount-max-button.container' import UserPreferencedTokenInput from '../../../../../components/app/user-preferenced-token-input' -import timeout from '../../../../../../lib/test-timeout' - -const propsMethodSpies = { - setMaxModeTo: sinon.spy(), - updateSendAmount: sinon.spy(), - updateSendAmountError: sinon.spy(), - updateGas: sinon.spy(), - updateGasFeeError: sinon.spy(), -} - -sinon.spy(SendAmountRow.prototype, 'updateAmount') -sinon.spy(SendAmountRow.prototype, 'validateAmount') -sinon.spy(SendAmountRow.prototype, 'updateGas') - describe('SendAmountRow Component', function () { - let wrapper - let instance - - beforeEach(() => { - wrapper = shallow(( - - ), { context: { t: str => str + '_t' } }) - instance = wrapper.instance() - }) - - afterEach(() => { - propsMethodSpies.setMaxModeTo.resetHistory() - propsMethodSpies.updateSendAmount.resetHistory() - propsMethodSpies.updateSendAmountError.resetHistory() - propsMethodSpies.updateGasFeeError.resetHistory() - SendAmountRow.prototype.validateAmount.resetHistory() - SendAmountRow.prototype.updateAmount.resetHistory() - }) - describe('validateAmount', () => { - it('should call updateSendAmountError with the correct params', () => { - assert.equal(propsMethodSpies.updateSendAmountError.callCount, 0) + const { instance, propsMethodSpies: { updateSendAmountError } } = shallowRenderSendAmountRow() + + assert.equal(updateSendAmountError.callCount, 0) + instance.validateAmount('someAmount') - assert.equal(propsMethodSpies.updateSendAmountError.callCount, 1) - assert.deepEqual( - propsMethodSpies.updateSendAmountError.getCall(0).args, - [{ - amount: 'someAmount', - amountConversionRate: 'mockAmountConversionRate', - balance: 'mockBalance', - conversionRate: 7, - gasTotal: 'mockGasTotal', - primaryCurrency: 'mockPrimaryCurrency', - selectedToken: { address: 'mockTokenAddress' }, - tokenBalance: 'mockTokenBalance', - }] - ) + + assert.ok(updateSendAmountError.calledOnceWithExactly({ + amount: 'someAmount', + amountConversionRate: 'mockAmountConversionRate', + balance: 'mockBalance', + conversionRate: 7, + gasTotal: 'mockGasTotal', + primaryCurrency: 'mockPrimaryCurrency', + selectedToken: { address: 'mockTokenAddress' }, + tokenBalance: 'mockTokenBalance', + })) }) it('should call updateGasFeeError if selectedToken is truthy', () => { - assert.equal(propsMethodSpies.updateGasFeeError.callCount, 0) + const { instance, propsMethodSpies: { updateGasFeeError } } = shallowRenderSendAmountRow() + + assert.equal(updateGasFeeError.callCount, 0) + instance.validateAmount('someAmount') - assert.equal(propsMethodSpies.updateGasFeeError.callCount, 1) - assert.deepEqual( - propsMethodSpies.updateGasFeeError.getCall(0).args, - [{ - amountConversionRate: 'mockAmountConversionRate', - balance: 'mockBalance', - conversionRate: 7, - gasTotal: 'mockGasTotal', - primaryCurrency: 'mockPrimaryCurrency', - selectedToken: { address: 'mockTokenAddress' }, - tokenBalance: 'mockTokenBalance', - }] - ) + + assert.ok(updateGasFeeError.calledOnceWithExactly({ + amountConversionRate: 'mockAmountConversionRate', + balance: 'mockBalance', + conversionRate: 7, + gasTotal: 'mockGasTotal', + primaryCurrency: 'mockPrimaryCurrency', + selectedToken: { address: 'mockTokenAddress' }, + tokenBalance: 'mockTokenBalance', + })) }) it('should call not updateGasFeeError if selectedToken is falsey', () => { + const { wrapper, instance, propsMethodSpies: { updateGasFeeError } } = shallowRenderSendAmountRow() + wrapper.setProps({ selectedToken: null }) - assert.equal(propsMethodSpies.updateGasFeeError.callCount, 0) + + assert.equal(updateGasFeeError.callCount, 0) + instance.validateAmount('someAmount') - assert.equal(propsMethodSpies.updateGasFeeError.callCount, 0) + + assert.equal(updateGasFeeError.callCount, 0) }) }) @@ -109,33 +64,36 @@ describe('SendAmountRow Component', function () { describe('updateAmount', () => { it('should call setMaxModeTo', () => { - assert.equal(propsMethodSpies.setMaxModeTo.callCount, 0) + const { instance, propsMethodSpies: { setMaxModeTo } } = shallowRenderSendAmountRow() + + assert.equal(setMaxModeTo.callCount, 0) + instance.updateAmount('someAmount') - assert.equal(propsMethodSpies.setMaxModeTo.callCount, 1) - assert.deepEqual( - propsMethodSpies.setMaxModeTo.getCall(0).args, - [false] - ) + + assert.ok(setMaxModeTo.calledOnceWithExactly(false)) }) it('should call updateSendAmount', () => { - assert.equal(propsMethodSpies.updateSendAmount.callCount, 0) + const { instance, propsMethodSpies: { updateSendAmount } } = shallowRenderSendAmountRow() + + assert.equal(updateSendAmount.callCount, 0) + instance.updateAmount('someAmount') - assert.equal(propsMethodSpies.updateSendAmount.callCount, 1) - assert.deepEqual( - propsMethodSpies.updateSendAmount.getCall(0).args, - ['someAmount'] - ) + + assert.ok(updateSendAmount.calledOnceWithExactly('someAmount')) }) }) describe('render', () => { it('should render a SendRowWrapper component', () => { + const { wrapper } = shallowRenderSendAmountRow() + assert.equal(wrapper.find(SendRowWrapper).length, 1) }) it('should pass the correct props to SendRowWrapper', () => { + const { wrapper } = shallowRenderSendAmountRow() const { errorType, label, @@ -143,47 +101,87 @@ describe('SendAmountRow Component', function () { } = wrapper.find(SendRowWrapper).props() assert.equal(errorType, 'amount') - assert.equal(label, 'amount_t:') - assert.equal(showError, false) }) it('should render an AmountMaxButton as the first child of the SendRowWrapper', () => { + const { wrapper } = shallowRenderSendAmountRow() + assert(wrapper.find(SendRowWrapper).childAt(0).is(AmountMaxButton)) }) it('should render a UserPreferencedTokenInput as the second child of the SendRowWrapper', () => { + const { wrapper } = shallowRenderSendAmountRow() + assert(wrapper.find(SendRowWrapper).childAt(1).is(UserPreferencedTokenInput)) }) - it('should render the UserPreferencedTokenInput with the correct props', async () => { + it('should render the UserPreferencedTokenInput with the correct props', () => { + const { wrapper, instanceSpies: { updateGas, updateAmount, validateAmount } } = shallowRenderSendAmountRow() const { onChange, error, value, } = wrapper.find(SendRowWrapper).childAt(1).props() + assert.equal(error, false) assert.equal(value, 'mockAmount') - assert.equal(SendAmountRow.prototype.updateGas.callCount, 0) - assert.equal(SendAmountRow.prototype.updateAmount.callCount, 0) - assert.equal(SendAmountRow.prototype.validateAmount.callCount, 0) + assert.equal(updateGas.callCount, 0) + assert.equal(updateAmount.callCount, 0) + assert.equal(validateAmount.callCount, 0) + onChange('mockNewAmount') - await timeout(501) - assert.deepEqual( - SendAmountRow.prototype.updateGas.getCall(0).args, - ['mockNewAmount'] - ) - assert.equal(SendAmountRow.prototype.updateAmount.callCount, 1) - assert.deepEqual( - SendAmountRow.prototype.updateAmount.getCall(0).args, - ['mockNewAmount'] - ) - assert.equal(SendAmountRow.prototype.validateAmount.callCount, 1) - assert.deepEqual( - SendAmountRow.prototype.validateAmount.getCall(0).args, - ['mockNewAmount'] - ) + + assert.ok(updateGas.calledOnceWithExactly('mockNewAmount')) + assert.ok(updateAmount.calledOnceWithExactly('mockNewAmount')) + assert.ok(validateAmount.calledOnceWithExactly('mockNewAmount')) }) }) }) + +function shallowRenderSendAmountRow () { + const setMaxModeTo = sinon.spy() + const updateGasFeeError = sinon.spy() + const updateSendAmount = sinon.spy() + const updateSendAmountError = sinon.spy() + const wrapper = shallow(( + {}} + /> + ), { context: { t: str => str + '_t' } }) + const instance = wrapper.instance() + const updateAmount = sinon.spy(instance, 'updateAmount') + const updateGas = sinon.spy(instance, 'updateGas') + const validateAmount = sinon.spy(instance, 'validateAmount') + + return { + instance, + wrapper, + propsMethodSpies: { + setMaxModeTo, + updateGasFeeError, + updateSendAmount, + updateSendAmountError, + }, + instanceSpies: { + updateAmount, + updateGas, + validateAmount, + }, + } +} diff --git a/yarn.lock b/yarn.lock index 9e47248d2..98a8ee2ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2301,6 +2301,13 @@ dependencies: type-detect "4.0.8" +"@sinonjs/formatio@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2" + integrity sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg== + dependencies: + samsam "1.3.0" + "@sinonjs/formatio@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.1.0.tgz#6ac9d1eb1821984d84c4996726e45d1646d8cce5" @@ -12425,13 +12432,6 @@ format@^0.2.2: resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= -formatio@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb" - integrity sha1-87IWfZBoxGmKjVH092CjmlTYGOs= - dependencies: - samsam "1.x" - formidable@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.1.tgz#70fb7ca0290ee6ff961090415f4b3df3d2082659" @@ -24976,7 +24976,7 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -samsam@1.x: +samsam@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" integrity sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg== @@ -25663,16 +25663,16 @@ single-line-log@^1.1.2: string-width "^1.0.1" sinon@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-5.0.0.tgz#e6de3b3f7fed338b470f8779dc4bab9fca058894" - integrity sha512-dMX7ZB2E1iQ5DOEOePoNJQp03uyhdMfb+kLXlNPbquv2FwfezD+0GbbHSgCw4MFhpSSS9NMoYJfOPMjCMJtXWA== + version "5.0.1" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-5.0.1.tgz#e399e00b30df53abf816f16cfc8f3aa0a480ada2" + integrity sha512-xhPMTWl8dusKsa/4Px+K0FCHsAhcpxjMurofDzPr6BF1I5C2G6r4JLIaHKSOcMnXkt7X4Md0OZgJuuIqlw9ieA== dependencies: + "@sinonjs/formatio" "^2.0.0" diff "^3.1.0" - formatio "1.2.0" lodash.get "^4.4.2" lolex "^2.2.0" nise "^1.2.0" - supports-color "^4.4.0" + supports-color "^5.1.0" type-detect "^4.0.5" sisteransi@^1.0.3: @@ -26933,34 +26933,20 @@ supports-color@^2.0.0: resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= -supports-color@^4.0.0, supports-color@^4.4.0, supports-color@^4.5.0: +supports-color@^4.0.0, supports-color@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" integrity sha1-vnoN5ITexcXN34s9WRJQRJEvY1s= dependencies: has-flag "^2.0.0" -supports-color@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" - integrity sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg== - dependencies: - has-flag "^3.0.0" - -supports-color@^5.3.0: +supports-color@^5.1.0, supports-color@^5.2.0, supports-color@^5.3.0, supports-color@^5.4.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" -supports-color@^5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== - dependencies: - has-flag "^3.0.0" - supports-color@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" From 667f4fa5f85ef04eeb92bc451fd07580fca6a4ae Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 5 Feb 2020 20:20:06 -0330 Subject: [PATCH 239/689] Revert CircleCI Node image (#7996) This changeset "reverts" the image version of the CircleCI node image, to work around a chromedriver/Chrome/WebDriver error. We were seeing the following errors: ``` WebDriverError: unknown error: Chrome failed to start: exited abnormally (unknown error: DevToolsActivePort file doesn't exist) (The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.) ``` I can surmise that the content changes in the Docker image, from (1) to (2), below did result in this breakage: 1. https://hub.docker.com/layers/circleci/node/10.18-browsers/images/sha256-e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 2. https://hub.docker.com/layers/circleci/node/10.18-browsers/images/sha256-14d76b9e092ca03543328409223a2d2fba29e3ee5b8274c90b0c98b80005ecf2 Alternative links: 1. circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 2. circleci/node@sha256:14d76b9e092ca03543328409223a2d2fba29e3ee5b8274c90b0c98b80005ecf2 --- .circleci/config.yml | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index cd60aa0d0..bc1cbd820 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -92,7 +92,7 @@ workflows: jobs: create_release_pull_request: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - run: @@ -104,7 +104,7 @@ jobs: prep-deps: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - run: @@ -123,7 +123,7 @@ jobs: prep-build: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: @@ -142,7 +142,7 @@ jobs: prep-build-test: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: @@ -160,7 +160,7 @@ jobs: prep-scss: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: @@ -179,7 +179,7 @@ jobs: test-lint: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: @@ -203,7 +203,7 @@ jobs: test-lint-lockfile: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: @@ -214,7 +214,7 @@ jobs: test-deps: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: @@ -225,7 +225,7 @@ jobs: test-e2e-chrome: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: @@ -243,7 +243,7 @@ jobs: test-e2e-firefox: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - run: @@ -264,7 +264,7 @@ jobs: benchmark: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: @@ -285,7 +285,7 @@ jobs: job-publish-prerelease: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: @@ -315,7 +315,7 @@ jobs: job-publish-release: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: @@ -332,7 +332,7 @@ jobs: command: .circleci/scripts/release-create-master-pr # job-publish-storybook: # docker: - # - image: circleci/node:10.18-browsers + # - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 # steps: # - checkout # - attach_workspace: @@ -343,7 +343,7 @@ jobs: test-unit: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: @@ -358,7 +358,7 @@ jobs: - coverage test-unit-global: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: @@ -368,7 +368,7 @@ jobs: command: yarn test:unit:global test-mozilla-lint: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: @@ -379,7 +379,7 @@ jobs: test-integration-flat-firefox: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: @@ -395,7 +395,7 @@ jobs: environment: browsers: '["Chrome"]' docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: @@ -406,7 +406,7 @@ jobs: all-tests-pass: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - run: name: All Tests Passed @@ -414,7 +414,7 @@ jobs: coveralls-upload: docker: - - image: circleci/node:10.18-browsers + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 steps: - checkout - attach_workspace: From 08c7322203deb52b2292a826a182c3f38ed53df0 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 6 Feb 2020 12:22:40 -0330 Subject: [PATCH 240/689] Remove last remaining usages of `npm run` (#7994) * Remove last remaining usages of `npm run` * Use nyc@15.0.0 --- package.json | 4 +- test/e2e/run-all.sh | 2 +- yarn.lock | 833 +++++++++++++++----------------------------- 3 files changed, 287 insertions(+), 552 deletions(-) diff --git a/package.json b/package.json index 8885e6d4f..e4d096c58 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "test:web3:chrome": "SELENIUM_BROWSER=chrome test/e2e/run-web3.sh", "test:web3:firefox": "SELENIUM_BROWSER=firefox test/e2e/run-web3.sh", "test:e2e:firefox": "SELENIUM_BROWSER=firefox test/e2e/run-all.sh", - "test:coverage": "nyc --reporter=text --reporter=html npm run test:unit", + "test:coverage": "nyc --reporter=text --reporter=html yarn test:unit", "test:coveralls-upload": "if [ \"$COVERALLS_REPO_TOKEN\" ]; then nyc report --reporter=text-lcov | coveralls; fi", "test:flat": "yarn test:flat:build && karma start test/flat.conf.js", "test:flat:build": "yarn test:flat:build:ui && yarn test:flat:build:tests && yarn test:flat:build:locales", @@ -251,7 +251,7 @@ "nock": "^9.0.14", "node-fetch": "^2.6.0", "node-sass": "^4.12.0", - "nyc": "^13.0.0", + "nyc": "^15.0.0", "polyfill-crypto.getrandomvalues": "^1.0.0", "proxyquire": "2.0.1", "qs": "^6.2.0", diff --git a/test/e2e/run-all.sh b/test/e2e/run-all.sh index c89f3f232..f19f8f803 100755 --- a/test/e2e/run-all.sh +++ b/test/e2e/run-all.sh @@ -60,7 +60,7 @@ concurrently --kill-others \ --names 'sendwithprivatedapp,e2e' \ --prefix '[{time}][{name}]' \ --success first \ - 'npm run sendwithprivatedapp' \ + 'yarn sendwithprivatedapp' \ 'mocha test/e2e/incremental-security.spec' concurrently --kill-others \ diff --git a/yarn.lock b/yarn.lock index 98a8ee2ef..f0fdc0582 100644 --- a/yarn.lock +++ b/yarn.lock @@ -54,13 +54,6 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/code-frame@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.51.tgz#bd71d9b192af978df915829d39d4094456439a0c" - integrity sha1-vXHZsZKvl435FYKdOdQJRFZDmgw= - dependencies: - "@babel/highlight" "7.0.0-beta.51" - "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" @@ -156,68 +149,17 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.51.tgz#6c7575ffde761d07485e04baedc0392c6d9e30f6" - integrity sha1-bHV1/952HQdIXgS67cA5LG2eMPY= - dependencies: - "@babel/types" "7.0.0-beta.51" - jsesc "^2.5.1" - lodash "^4.17.5" - source-map "^0.5.0" - trim-right "^1.0.1" - -"@babel/generator@^7.4.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.4.4.tgz#174a215eb843fc392c7edcaabeaa873de6e8f041" - integrity sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ== - dependencies: - "@babel/types" "^7.4.4" - jsesc "^2.5.1" - lodash "^4.17.11" - source-map "^0.5.0" - trim-right "^1.0.1" - -"@babel/generator@^7.4.4", "@babel/generator@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.5.5.tgz#873a7f936a3c89491b43536d12245b626664e3cf" - integrity sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ== - dependencies: - "@babel/types" "^7.5.5" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - trim-right "^1.0.1" - -"@babel/generator@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.0.tgz#e2c21efbfd3293ad819a2359b448f002bfdfda56" - integrity sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA== - dependencies: - "@babel/types" "^7.6.0" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - trim-right "^1.0.1" - -"@babel/generator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.3.tgz#0e22c005b0a94c1c74eafe19ef78ce53a4d45c03" - integrity sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug== +"@babel/generator@^7.4.0", "@babel/generator@^7.4.4", "@babel/generator@^7.5.5", "@babel/generator@^7.6.0", "@babel/generator@^7.8.3": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.4.tgz#35bbc74486956fe4251829f9f6c48330e8d0985e" + integrity sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA== dependencies: "@babel/types" "^7.8.3" jsesc "^2.5.1" lodash "^4.17.13" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" - integrity sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-annotate-as-pure@^7.8.3": +"@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== @@ -249,18 +191,6 @@ "@babel/traverse" "^7.4.4" "@babel/types" "^7.4.4" -"@babel/helper-create-class-features-plugin@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.5.5.tgz#401f302c8ddbc0edd36f7c6b2887d8fa1122e5a4" - integrity sha512-ZsxkyYiRA7Bg+ZTRpPvB6AbOFKTFFK4LrvTet8lInm0V468MWCaSYJE+I7v2z2r8KNLtYiV+K5kTCnR7dvyZjg== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-member-expression-to-functions" "^7.5.5" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.5.5" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/helper-create-class-features-plugin@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz#5b94be88c255f140fd2c10dd151e7f98f4bff397" @@ -273,16 +203,7 @@ "@babel/helper-replace-supers" "^7.8.3" "@babel/helper-split-export-declaration" "^7.8.3" -"@babel/helper-define-map@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz#6969d1f570b46bdc900d1eba8e5d59c48ba2c12a" - integrity sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/types" "^7.4.4" - lodash "^4.17.11" - -"@babel/helper-define-map@^7.5.5": +"@babel/helper-define-map@^7.4.4", "@babel/helper-define-map@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz#3dec32c2046f37e09b28c93eb0b103fd2a25d369" integrity sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg== @@ -299,25 +220,7 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-function-name@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.51.tgz#21b4874a227cf99ecafcc30a90302da5a2640561" - integrity sha1-IbSHSiJ8+Z7K/MMKkDAtpaJkBWE= - dependencies: - "@babel/helper-get-function-arity" "7.0.0-beta.51" - "@babel/template" "7.0.0-beta.51" - "@babel/types" "7.0.0-beta.51" - -"@babel/helper-function-name@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" - integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== - dependencies: - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-function-name@^7.8.3": +"@babel/helper-function-name@^7.1.0", "@babel/helper-function-name@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA== @@ -326,21 +229,7 @@ "@babel/template" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-get-function-arity@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.51.tgz#3281b2d045af95c172ce91b20825d85ea4676411" - integrity sha1-MoGy0EWvlcFyzpGyCCXYXqRnZBE= - dependencies: - "@babel/types" "7.0.0-beta.51" - -"@babel/helper-get-function-arity@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" - integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-get-function-arity@^7.8.3": +"@babel/helper-get-function-arity@^7.0.0", "@babel/helper-get-function-arity@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== @@ -354,20 +243,6 @@ dependencies: "@babel/types" "^7.4.4" -"@babel/helper-member-expression-to-functions@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz#8cd14b0a0df7ff00f009e7d7a436945f47c7a16f" - integrity sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-member-expression-to-functions@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz#1fb5b8ec4453a93c439ee9fe3aeea4a84b76b590" - integrity sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA== - dependencies: - "@babel/types" "^7.5.5" - "@babel/helper-member-expression-to-functions@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" @@ -436,27 +311,7 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-replace-supers@^7.1.0", "@babel/helper-replace-supers@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz#aee41783ebe4f2d3ab3ae775e1cc6f1a90cefa27" - integrity sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.0.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/traverse" "^7.4.4" - "@babel/types" "^7.4.4" - -"@babel/helper-replace-supers@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz#f84ce43df031222d2bad068d2626cb5799c34bc2" - integrity sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.5.5" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" - -"@babel/helper-replace-supers@^7.8.3": +"@babel/helper-replace-supers@^7.1.0", "@babel/helper-replace-supers@^7.4.4", "@babel/helper-replace-supers@^7.5.5", "@babel/helper-replace-supers@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz#91192d25f6abbcd41da8a989d4492574fb1530bc" integrity sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA== @@ -474,21 +329,7 @@ "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-split-export-declaration@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.51.tgz#8a6c3f66c4d265352fc077484f9f6e80a51ab978" - integrity sha1-imw/ZsTSZTUvwHdIT59ugKUauXg= - dependencies: - "@babel/types" "7.0.0-beta.51" - -"@babel/helper-split-export-declaration@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" - integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== - dependencies: - "@babel/types" "^7.4.4" - -"@babel/helper-split-export-declaration@^7.8.3": +"@babel/helper-split-export-declaration@^7.4.4", "@babel/helper-split-export-declaration@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== @@ -505,25 +346,7 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.2.0" -"@babel/helpers@^7.4.4", "@babel/helpers@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.5.5.tgz#63908d2a73942229d1e6685bc2a0e730dde3b75e" - integrity sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g== - dependencies: - "@babel/template" "^7.4.4" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" - -"@babel/helpers@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.6.0.tgz#21961d16c6a3c3ab597325c34c465c0887d31c6e" - integrity sha512-W9kao7OBleOjfXtFGgArGRX6eCP0UEcA2ZWEWNkJdRZnHhW4eEbeswbG3EwaRsnQUAEGWYgMq1HsIXuNNNy2eQ== - dependencies: - "@babel/template" "^7.6.0" - "@babel/traverse" "^7.6.0" - "@babel/types" "^7.6.0" - -"@babel/helpers@^7.8.3": +"@babel/helpers@^7.4.4", "@babel/helpers@^7.5.5", "@babel/helpers@^7.6.0", "@babel/helpers@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.3.tgz#382fbb0382ce7c4ce905945ab9641d688336ce85" integrity sha512-LmU3q9Pah/XyZU89QvBgGt+BCsTPoQa+73RxAQh8fb8qkDyIfeQnmgs+hvzhTCKTzqOyk7JTkS3MS1S8Mq5yrQ== @@ -532,25 +355,7 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/highlight@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.51.tgz#e8844ae25a1595ccfd42b89623b4376ca06d225d" - integrity sha1-6IRK4loVlcz9QriWI7Q3bKBtIl0= - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^3.0.0" - -"@babel/highlight@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" - integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^4.0.0" - -"@babel/highlight@^7.8.3": +"@babel/highlight@^7.0.0", "@babel/highlight@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg== @@ -559,30 +364,10 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.0.0-beta.51.tgz#27cec2df409df60af58270ed8f6aa55409ea86f6" - integrity sha1-J87C30Cd9gr1gnDtj2qlVAnqhvY= - -"@babel/parser@^7.0.0", "@babel/parser@^7.4.4", "@babel/parser@^7.4.5", "@babel/parser@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.5.tgz#02f077ac8817d3df4a832ef59de67565e71cca4b" - integrity sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g== - -"@babel/parser@^7.1.0", "@babel/parser@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.3.tgz#790874091d2001c9be6ec426c2eed47bc7679081" - integrity sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ== - -"@babel/parser@^7.4.3": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.5.tgz#04af8d5d5a2b044a2a1bffacc1e5e6673544e872" - integrity sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew== - -"@babel/parser@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.0.tgz#3e05d0647432a8326cb28d0de03895ae5a57f39b" - integrity sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ== +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.4.4", "@babel/parser@^7.4.5", "@babel/parser@^7.5.5", "@babel/parser@^7.6.0", "@babel/parser@^7.7.5", "@babel/parser@^7.8.3": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8" + integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw== "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" @@ -593,15 +378,7 @@ "@babel/helper-remap-async-to-generator" "^7.1.0" "@babel/plugin-syntax-async-generators" "^7.2.0" -"@babel/plugin-proposal-class-properties@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.5.tgz#a974cfae1e37c3110e71f3c6a2e48b8e71958cd4" - integrity sha512-AF79FsnWFxjlaosgdi421vmYG6/jg79bVD0dpD44QdgobzHKuLZ6S3vl8la9qIeSwGi8i1fS0O1mfuDAAdo1/A== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.5.5" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-proposal-class-properties@^7.7.0": +"@babel/plugin-proposal-class-properties@^7.5.5", "@babel/plugin-proposal-class-properties@^7.7.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz#5e06654af5cd04b608915aada9b2a6788004464e" integrity sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA== @@ -1303,16 +1080,6 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/template@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.51.tgz#9602a40aebcf357ae9677e2532ef5fc810f5fbff" - integrity sha1-lgKkCuvPNXrpZ34lMu9fyBD1+/8= - dependencies: - "@babel/code-frame" "7.0.0-beta.51" - "@babel/parser" "7.0.0-beta.51" - "@babel/types" "7.0.0-beta.51" - lodash "^4.17.5" - "@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237" @@ -1331,7 +1098,7 @@ "@babel/parser" "^7.6.0" "@babel/types" "^7.6.0" -"@babel/template@^7.8.3": +"@babel/template@^7.7.4", "@babel/template@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8" integrity sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ== @@ -1340,68 +1107,7 @@ "@babel/parser" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/traverse@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.51.tgz#981daf2cec347a6231d3aa1d9e1803b03aaaa4a8" - integrity sha1-mB2vLOw0emIx06odnhgDsDqqpKg= - dependencies: - "@babel/code-frame" "7.0.0-beta.51" - "@babel/generator" "7.0.0-beta.51" - "@babel/helper-function-name" "7.0.0-beta.51" - "@babel/helper-split-export-declaration" "7.0.0-beta.51" - "@babel/parser" "7.0.0-beta.51" - "@babel/types" "7.0.0-beta.51" - debug "^3.1.0" - globals "^11.1.0" - invariant "^2.2.0" - lodash "^4.17.5" - -"@babel/traverse@^7.0.0", "@babel/traverse@^7.4.4", "@babel/traverse@^7.4.5", "@babel/traverse@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.5.5.tgz#f664f8f368ed32988cd648da9f72d5ca70f165bb" - integrity sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.5.5" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.5.5" - "@babel/types" "^7.5.5" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.4.5.tgz#4e92d1728fd2f1897dafdd321efbff92156c3216" - integrity sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.4.4" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.4.5" - "@babel/types" "^7.4.4" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.11" - -"@babel/traverse@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.0.tgz#389391d510f79be7ce2ddd6717be66d3fed4b516" - integrity sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.6.0" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.6.0" - "@babel/types" "^7.6.0" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/traverse@^7.8.3": +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.4.5", "@babel/traverse@^7.5.5", "@babel/traverse@^7.6.0", "@babel/traverse@^7.7.4", "@babel/traverse@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.3.tgz#a826215b011c9b4f73f3a893afbc05151358bf9a" integrity sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg== @@ -1416,43 +1122,7 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/types@7.0.0-beta.51": - version "7.0.0-beta.51" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.51.tgz#d802b7b543b5836c778aa691797abf00f3d97ea9" - integrity sha1-2AK3tUO1g2x3iqaReXq/APPZfqk= - dependencies: - esutils "^2.0.2" - lodash "^4.17.5" - to-fast-properties "^2.0.0" - -"@babel/types@^7.0.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.5.tgz#97b9f728e182785909aa4ab56264f090a028d18a" - integrity sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw== - dependencies: - esutils "^2.0.2" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - -"@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.4.tgz#8db9e9a629bb7c29370009b4b779ed93fe57d5f0" - integrity sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ== - dependencies: - esutils "^2.0.2" - lodash "^4.17.11" - to-fast-properties "^2.0.0" - -"@babel/types@^7.6.0": - version "7.6.1" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.1.tgz#53abf3308add3ac2a2884d539151c57c4b3ac648" - integrity sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g== - dependencies: - esutils "^2.0.2" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - -"@babel/types@^7.8.3": +"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0", "@babel/types@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg== @@ -1963,6 +1633,21 @@ resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw== +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b" + integrity sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" + integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== + "@jest/console@^24.7.1", "@jest/console@^24.9.0": version "24.9.0" resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0" @@ -3943,12 +3628,12 @@ append-buffer@^1.0.2: dependencies: buffer-equal "^1.0.0" -append-transform@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" - integrity sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw== +append-transform@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" + integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== dependencies: - default-require-extensions "^2.0.0" + default-require-extensions "^3.0.0" aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" @@ -6534,14 +6219,15 @@ cachedown@1.0.0: abstract-leveldown "^2.4.1" lru-cache "^3.2.0" -caching-transform@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-1.0.1.tgz#6dbdb2f20f8d8fbce79f3e94e9d1742dcdf5c0a1" - integrity sha1-bb2y8g+Nj7znnz6U6dF0Lc31wKE= +caching-transform@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" + integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== dependencies: - md5-hex "^1.2.0" - mkdirp "^0.5.1" - write-file-atomic "^1.1.4" + hasha "^5.0.0" + make-dir "^3.0.0" + package-hash "^4.0.0" + write-file-atomic "^3.0.0" call-me-maybe@^1.0.1: version "1.0.1" @@ -7385,7 +7071,7 @@ commander@^2.15.0, commander@^2.16.0, commander@^2.19.0, commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== -commander@^2.9.0, commander@~2.20.3: +commander@^2.9.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -7912,14 +7598,6 @@ cross-spawn@^3.0.0: lru-cache "^4.0.1" which "^1.2.9" -cross-spawn@^4: - version "4.0.2" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" - integrity sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE= - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" @@ -7929,6 +7607,15 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" + integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + crypto-browserify@3.12.0, crypto-browserify@^3.0.0, crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -8529,11 +8216,6 @@ debug-fabulous@1.X: memoizee "0.4.X" object-assign "4.X" -debug-log@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" - integrity sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8= - debug@2, debug@2.6.9, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -8718,12 +8400,12 @@ default-compare@^1.0.0: dependencies: kind-of "^5.0.2" -default-require-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7" - integrity sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc= +default-require-extensions@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.0.tgz#e03f93aac9b2b6443fc52e5e4a37b3ad9ad8df96" + integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg== dependencies: - strip-bom "^3.0.0" + strip-bom "^4.0.0" default-resolution@^2.0.0: version "2.0.0" @@ -10002,6 +9684,11 @@ es5-shim@^4.5.13: resolved "https://registry.yarnpkg.com/es5-shim/-/es5-shim-4.5.13.tgz#5d88062de049f8969f83783f4a4884395f21d28b" integrity sha512-xi6hh6gsvDE0MaW4Vp1lgNEBpVcCXRWfPXj5egDvtgLz4L9MEvNwYEMdJH+JJinWkwa8c3c3o5HduV7dB/e1Hw== +es6-error@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" @@ -12095,15 +11782,6 @@ finalhandler@1.1.2, finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-cache-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f" - integrity sha1-kojj6ePMN0hxfTnq3hfPcfww7m8= - dependencies: - commondir "^1.0.1" - make-dir "^1.0.0" - pkg-dir "^2.0.0" - find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" @@ -12382,13 +12060,13 @@ foreach@^2.0.5: resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= -foreground-child@^1.5.6: - version "1.5.6" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" - integrity sha1-T9ca0t/elnibmApcCilZN8svXOk= +foreground-child@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" + integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== dependencies: - cross-spawn "^4" - signal-exit "^3.0.0" + cross-spawn "^7.0.0" + signal-exit "^3.0.2" forever-agent@~0.6.1: version "0.6.1" @@ -12467,7 +12145,7 @@ from@~0: resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= -fromentries@^1.1.0: +fromentries@^1.1.0, fromentries@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.2.0.tgz#e6aa06f240d6267f913cea422075ef88b63e7897" integrity sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ== @@ -13081,6 +12759,18 @@ glob@^6.0.4: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + global-dirs@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" @@ -13699,17 +13389,6 @@ hamt-sharding@~0.0.2: dependencies: sparse-array "^1.3.1" -handlebars@^4.0.11: - version "4.5.3" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" - integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA== - dependencies: - neo-async "^2.6.0" - optimist "^0.6.1" - source-map "^0.6.1" - optionalDependencies: - uglify-js "^3.1.4" - hapi-pino@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/hapi-pino/-/hapi-pino-6.0.1.tgz#f6e851099f2f68df43817f165240f8b36a969114" @@ -13886,6 +13565,14 @@ hasha@^2.2.0: is-stream "^1.0.1" pinkie-promise "^2.0.0" +hasha@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.1.0.tgz#dd05ccdfcfe7dab626247ce2a58efe461922f4ca" + integrity sha512-OFPDWmzPN1l7atOV1TgBVmNtBxaIysToK6Ve9DK+vT6pYuklw/nPNT+HJbZi0KDcI6vWB+9tgvZ5YD7fA3CXcA== + dependencies: + is-stream "^2.0.0" + type-fest "^0.8.0" + hashlru@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/hashlru/-/hashlru-2.3.0.tgz#5dc15928b3f6961a2056416bb3a4910216fdfb51" @@ -14748,7 +14435,7 @@ invariant@2.2.4, invariant@^2.2.3, invariant@^2.2.4: dependencies: loose-envify "^1.0.0" -invariant@^2.0.0, invariant@^2.1.0, invariant@^2.2.0, invariant@^2.2.2: +invariant@^2.0.0, invariant@^2.1.0, invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" integrity sha1-nh9WrArNtr8wMwbzOL47IErmA2A= @@ -16106,35 +15793,22 @@ isstream@0.1.x, isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -istanbul-lib-coverage@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.0.tgz#905e71212052ffb34f2eb008102230bff03940b5" - integrity sha512-yMSw5xLIbdaxiVXHk3amfNM2WeBxLrwH/BCyZ9HvA/fylwziAIJOG2rKqWyLqEJqwKT725vxxqidv+SyynnGAA== - -istanbul-lib-coverage@^2.0.1, istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.5: +istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== -istanbul-lib-hook@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.0.tgz#e3df34bb7f3d7b5c34722c7d8675dd451fabfc89" - integrity sha512-qm3dt628HKpCVtIjbdZLuQyXn0+LO8qz+YHQDfkeXuSk5D+p299SEV5DrnUUnPi2SXvdMmWapMYWiuE75o2rUQ== - dependencies: - append-transform "^1.0.0" +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== -istanbul-lib-instrument@^2.2.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-2.3.2.tgz#b287cbae2b5f65f3567b05e2e29b275eaf92d25e" - integrity sha512-l7TD/VnBsIB2OJvSyxaLW/ab1+92dxZNH9wLH7uHPPioy3JZ8tnx2UXUdKmdkgmP2EFPzg64CToUP6dAS3U32Q== - dependencies: - "@babel/generator" "7.0.0-beta.51" - "@babel/parser" "7.0.0-beta.51" - "@babel/template" "7.0.0-beta.51" - "@babel/traverse" "7.0.0-beta.51" - "@babel/types" "7.0.0-beta.51" - istanbul-lib-coverage "^2.0.1" - semver "^5.5.0" +istanbul-lib-hook@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" + integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== + dependencies: + append-transform "^2.0.0" istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.3.0: version "3.3.0" @@ -16149,14 +15823,31 @@ istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.3.0: istanbul-lib-coverage "^2.0.5" semver "^6.0.0" -istanbul-lib-report@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.0.tgz#99c161979ec202f4a638abd8dc77fab8f9abce53" - integrity sha512-RiELmy9oIRYUv36ITOAhVum9PUvuj6bjyXVEKEHNiD1me6qXtxfx7vSEJWnjOGk2QmYw/GRFjLXWJv3qHpLceQ== +istanbul-lib-instrument@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.1.tgz#61f13ac2c96cfefb076fe7131156cc05907874e6" + integrity sha512-imIchxnodll7pvQBYOqUu88EufLCU56LMeFPZZM/fJZ1irYcYdqroaV+ACK1Ila8ls09iEYArp+nqyC6lW1Vfg== dependencies: - istanbul-lib-coverage "^2.0.0" - make-dir "^1.3.0" - supports-color "^5.4.0" + "@babel/core" "^7.7.5" + "@babel/parser" "^7.7.5" + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" + +istanbul-lib-processinfo@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz#e1426514662244b2f25df728e8fd1ba35fe53b9c" + integrity sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw== + dependencies: + archy "^1.0.0" + cross-spawn "^7.0.0" + istanbul-lib-coverage "^3.0.0-alpha.1" + make-dir "^3.0.0" + p-map "^3.0.0" + rimraf "^3.0.0" + uuid "^3.3.3" istanbul-lib-report@^2.0.4: version "2.0.8" @@ -16167,16 +15858,14 @@ istanbul-lib-report@^2.0.4: make-dir "^2.1.0" supports-color "^6.1.0" -istanbul-lib-source-maps@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-2.0.0.tgz#4f66403bdbf9f468ccfadd4557878077c26335ba" - integrity sha512-jenUeC0gMSSMGkvqD9xuNfs3nD7XWeXLhqaIkqHsNZ3DJBWPdlKEydE7Ya5aTgdWjrEQhrCYTv+J606cGC2vuQ== +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== dependencies: - debug "^3.1.0" - istanbul-lib-coverage "^2.0.0" - make-dir "^1.3.0" - rimraf "^2.6.2" - source-map "^0.6.1" + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" istanbul-lib-source-maps@^3.0.1: version "3.0.6" @@ -16189,12 +15878,14 @@ istanbul-lib-source-maps@^3.0.1: rimraf "^2.6.3" source-map "^0.6.1" -istanbul-reports@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.0.tgz#c6c2867fa65f59eb7dcedb7f845dfc76aaee70f9" - integrity sha512-HeZG0WHretI9FXBni5wZ9DOgNziqDCEwetxnme5k1Vv5e81uTqcsy3fMH99gXGDGKr1ea87TyGseDMa2h4HEUA== +istanbul-lib-source-maps@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" + integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== dependencies: - handlebars "^4.0.11" + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" istanbul-reports@^2.2.6: version "2.2.7" @@ -16203,6 +15894,14 @@ istanbul-reports@^2.2.6: dependencies: html-escaper "^2.0.0" +istanbul-reports@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.0.tgz#d4d16d035db99581b6194e119bbf36c963c5eb70" + integrity sha512-2osTcC8zcOSUkImzN2EWQta3Vdi4WjjKw99P2yWx5mLnigAM0Rd5uYFn1cf2i/Ois45GkNjaoTqc5CxgMSX80A== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + istextorbinary@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-1.0.2.tgz#ace19354d1a9a0173efeb1084ce0f87b0ad7decf" @@ -18807,7 +18506,7 @@ magic-string@^0.22.4: dependencies: vlq "^0.2.2" -make-dir@^1.0.0, make-dir@^1.2.0, make-dir@^1.3.0: +make-dir@^1.0.0, make-dir@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== @@ -18937,25 +18636,6 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.1.tgz#6dff66c99d55ecf739ca53c492e626f1d12a33cc" integrity sha512-pWB896KPGSGkp1XtyzRBftpTzwSOL0Gfk0wLvxt4f2mgzjY19o0LxJ3U25vNWTzsh7da+KTbuXQoQ3lOJZ8WHw== -md5-hex@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-1.3.0.tgz#d2c4afe983c4370662179b8cad145219135046c4" - integrity sha1-0sSv6YPENwZiF5uMrRRSGRNQRsQ= - dependencies: - md5-o-matic "^0.1.1" - -md5-hex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-2.0.0.tgz#d0588e9f1c74954492ecd24ac0ac6ce997d92e33" - integrity sha1-0FiOnxx0lUSS7NJKwKxs6ZfZLjM= - dependencies: - md5-o-matic "^0.1.1" - -md5-o-matic@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" - integrity sha1-givM1l4RfFFPqxdrJZRdVBAKA8M= - md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -19141,13 +18821,6 @@ merge-source-map@1.0.4: dependencies: source-map "^0.5.6" -merge-source-map@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" - integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw== - dependencies: - source-map "^0.6.1" - merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -19986,7 +19659,7 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: +neo-async@^2.5.0, neo-async@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== @@ -20220,6 +19893,13 @@ node-pre-gyp@^0.13.0: semver "^5.3.0" tar "^4" +node-preload@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" + integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== + dependencies: + process-on-spawn "^1.0.0" + node-releases@^1.1.13: version "1.1.23" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.23.tgz#de7409f72de044a2fa59c097f436ba89c39997f0" @@ -20508,36 +20188,39 @@ nwsapi@^2.0.7: resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== -nyc@^13.0.0: - version "13.0.0" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-13.0.0.tgz#e00c26e9bd33ab5e81ede992bbe49308485899b6" - integrity sha512-aQo5UssY25uCJ6M3yNjem0C3KJ1z4IYLp9iR2KqRsuwAII1YofEnRDrHOzp/0Zk2YMYXXxuvWUzjr24i4nmfDA== +nyc@^15.0.0: + version "15.0.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.0.0.tgz#eb32db2c0f29242c2414fe46357f230121cfc162" + integrity sha512-qcLBlNCKMDVuKb7d1fpxjPR8sHeMVX0CHarXAVzrVWoFrigCkYR8xcrjfXSPi5HXM7EU78L6ywO7w1c5rZNCNg== dependencies: - archy "^1.0.0" - arrify "^1.0.1" - caching-transform "^1.0.1" - convert-source-map "^1.5.1" - debug-log "^1.0.1" - find-cache-dir "^1.0.0" - find-up "^2.1.0" - foreground-child "^1.5.6" - glob "^7.1.2" - istanbul-lib-coverage "^2.0.0" - istanbul-lib-hook "^2.0.0" - istanbul-lib-instrument "^2.2.0" - istanbul-lib-report "^2.0.0" - istanbul-lib-source-maps "^2.0.0" - istanbul-reports "^1.5.0" - make-dir "^1.3.0" - md5-hex "^2.0.0" - merge-source-map "^1.1.0" - resolve-from "^4.0.0" - rimraf "^2.6.2" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + caching-transform "^4.0.0" + convert-source-map "^1.7.0" + decamelize "^1.2.0" + find-cache-dir "^3.2.0" + find-up "^4.1.0" + foreground-child "^2.0.0" + glob "^7.1.6" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-hook "^3.0.0" + istanbul-lib-instrument "^4.0.0" + istanbul-lib-processinfo "^2.0.2" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.0" + js-yaml "^3.13.1" + make-dir "^3.0.0" + node-preload "^0.2.0" + p-map "^3.0.0" + process-on-spawn "^1.0.0" + resolve-from "^5.0.0" + rimraf "^3.0.0" signal-exit "^3.0.2" - spawn-wrap "^1.4.2" - test-exclude "^4.2.2" - yargs "11.1.0" - yargs-parser "^9.0.2" + spawn-wrap "^2.0.0" + test-exclude "^6.0.0" + uuid "^3.3.3" + yargs "^15.0.2" oauth-sign@~0.8.2: version "0.8.2" @@ -21353,6 +21036,16 @@ pac-resolver@^3.0.0: netmask "^1.0.6" thunkify "^2.1.2" +package-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" + integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== + dependencies: + graceful-fs "^4.1.15" + hasha "^5.0.0" + lodash.flattendeep "^4.4.0" + release-zalgo "^1.0.0" + package-json@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" @@ -21619,6 +21312,11 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + path-parse@^1.0.5, path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" @@ -22433,6 +22131,13 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +process-on-spawn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.0.0.tgz#95b05a23073d30a17acfdc92a440efd2baefdc93" + integrity sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg== + dependencies: + fromentries "^1.2.0" + process@^0.11.10, process@~0.11.0: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" @@ -24264,6 +23969,13 @@ relaxed-json@1.0.3: chalk "^2.4.2" commander "^2.6.0" +release-zalgo@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" + integrity sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA= + dependencies: + es6-error "^4.0.1" + remark-parse@^6.0.0: version "6.0.3" resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-6.0.3.tgz#c99131052809da482108413f87b0ee7f52180a3a" @@ -24774,7 +24486,7 @@ rfdc@^1.1.2: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2" integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug== -rimraf@2, rimraf@^2.2.8, rimraf@^2.4.4, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.2: +rimraf@2, rimraf@^2.2.8, rimraf@^2.4.4, rimraf@^2.5.4, rimraf@^2.6.0: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== @@ -24795,6 +24507,13 @@ rimraf@^2.6.3, rimraf@^2.7.1: dependencies: glob "^7.1.3" +rimraf@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.1.tgz#48d3d4cb46c80d388ab26cd61b1b466ae9ae225a" + integrity sha512-IQ4ikL8SjBiEDZfk+DFVwqRK8md24RWMEJkdSlgNLkyyAImcjf8SWvU1qFMDOb4igBClbTQ/ugPqXcRwdFTxZw== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -25529,11 +25248,23 @@ shebang-command@^1.2.0: dependencies: shebang-regex "^1.0.0" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + shell-quote@1.6.1, shell-quote@^1.4.2, shell-quote@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" @@ -25709,7 +25440,7 @@ slice-ansi@^2.1.0: astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" -slide@^1.1.5, slide@~1.1.3: +slide@~1.1.3: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc= @@ -26087,17 +25818,17 @@ spawn-command@^0.0.2-1: resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A= -spawn-wrap@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.4.2.tgz#cff58e73a8224617b6561abdc32586ea0c82248c" - integrity sha512-vMwR3OmmDhnxCVxM8M+xO/FtIp6Ju/mNaDfCMMW7FDcLRTPFWUswec4LXJHTJE2hwTI9O0YBfygu4DalFl7Ylg== +spawn-wrap@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" + integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== dependencies: - foreground-child "^1.5.6" - mkdirp "^0.5.0" - os-homedir "^1.0.1" - rimraf "^2.6.2" + foreground-child "^2.0.0" + is-windows "^1.0.2" + make-dir "^3.0.0" + rimraf "^3.0.0" signal-exit "^3.0.2" - which "^1.3.0" + which "^2.0.1" spdx-correct@~1.0.0: version "1.0.2" @@ -26712,6 +26443,11 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + strip-color@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/strip-color/-/strip-color-0.1.0.tgz#106f65d3d3e6a2d9401cac0eb0ce8b8a702b4f7b" @@ -27349,16 +27085,6 @@ terser@^4.1.4: source-map "~0.6.1" source-map-support "~0.5.12" -test-exclude@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.2.tgz#8b67aa8408f84afc225b06669e25c510f8582820" - integrity sha512-2kTGf+3tykCfrWVREgyTR0bmVO0afE6i7zVXi/m+bZZ8ujV89Aulxdcdv32yH+unVFg3Y5o6GA8IzsHnGQuFgQ== - dependencies: - arrify "^1.0.1" - minimatch "^3.0.4" - read-pkg-up "^3.0.0" - require-main-filename "^1.0.1" - test-exclude@^5.2.3: version "5.2.3" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" @@ -27369,6 +27095,15 @@ test-exclude@^5.2.3: read-pkg-up "^4.0.0" require-main-filename "^2.0.0" +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + testem@^2.16.0: version "2.16.0" resolved "https://registry.yarnpkg.com/testem/-/testem-2.16.0.tgz#da2682f3e02459212b8670b88f9d7cd4d4b0aebb" @@ -27945,7 +27680,7 @@ type-fest@^0.3.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== -type-fest@^0.8.1: +type-fest@^0.8.0, type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== @@ -28025,14 +27760,6 @@ uglify-js@3.4.x: commander "~2.19.0" source-map "~0.6.1" -uglify-js@^3.1.4: - version "3.7.3" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.3.tgz#f918fce9182f466d5140f24bb0ff35c2d32dcc6a" - integrity sha512-7tINm46/3puUA4hCkKYo4Xdts+JDaVC9ZPRcG8Xw9R4nhO/gZgUM3TENq8IF4Vatk8qCig4MzP/c8G4u2BkVQg== - dependencies: - commander "~2.20.3" - source-map "~0.6.1" - uid-number@0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" @@ -29421,6 +29148,13 @@ which@^1.2.9, which@^1.3.1: dependencies: isexe "^2.0.0" +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + wide-align@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" @@ -29525,15 +29259,6 @@ write-file-atomic@2.4.1: imurmurhash "^0.1.4" signal-exit "^3.0.2" -write-file-atomic@^1.1.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" - integrity sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8= - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - slide "^1.1.5" - write-file-atomic@^2.0.0: version "2.4.3" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" @@ -29543,6 +29268,16 @@ write-file-atomic@^2.0.0: imurmurhash "^0.1.4" signal-exit "^3.0.2" +write-file-atomic@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.1.tgz#558328352e673b5bb192cf86500d60b230667d4b" + integrity sha512-JPStrIyyVJ6oCSz/691fAjFtefZ6q+fP6tm+OS4Qw6o+TGQxNp1ziY2PgS+X/m0V8OWhZiO/m4xSj+Pr4RrZvw== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + write@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" From 8e307f8d714bfd06051f68add4ef03af7eb8226b Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Thu, 6 Feb 2020 07:57:54 -0800 Subject: [PATCH 241/689] update inpage-provider; minor fixes (#7997) --- app/scripts/inpage.js | 6 +++--- app/scripts/lib/auto-reload.js | 4 ++-- package.json | 2 +- yarn.lock | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 3fcc3bbaf..af6450e9b 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -36,7 +36,7 @@ import log from 'loglevel' import LocalMessageDuplexStream from 'post-message-stream' import MetamaskInpageProvider from 'metamask-inpage-provider' -// TODO:deprecate:2020-01-13 +// TODO:deprecate:Q1-2020 import 'web3/dist/web3.min.js' import setupDappAutoReload from './lib/auto-reload.js' @@ -70,7 +70,7 @@ const proxiedInpageProvider = new Proxy(inpageProvider, { }) // -// TODO:deprecate:2020-01-13 +// TODO:deprecate:Q1-2020 // // setup web3 @@ -95,7 +95,7 @@ proxiedInpageProvider._web3Ref = web3.eth setupDappAutoReload(web3, inpageProvider._publicConfigStore) // -// end deprecate:2020-01-13 +// end deprecate:Q1-2020 // window.ethereum = proxiedInpageProvider diff --git a/app/scripts/lib/auto-reload.js b/app/scripts/lib/auto-reload.js index e5b82bf4a..ba6f27765 100644 --- a/app/scripts/lib/auto-reload.js +++ b/app/scripts/lib/auto-reload.js @@ -1,5 +1,5 @@ -// TODO:deprecate:2020-01-13 +// TODO:deprecate:Q1-2020 export default setupDappAutoReload @@ -16,7 +16,7 @@ function setupDappAutoReload (web3, observable) { lastTimeUsed = Date.now() // show warning once on web3 access if (!hasBeenWarned && key !== 'currentProvider') { - console.warn(`MetaMask: On 2020-01-13, MetaMask will no longer inject web3. For more information, see: https://medium.com/metamask/no-longer-injecting-web3-js-4a899ad6e59e`) + console.warn(`MetaMask: In Q1 2020, MetaMask will no longer inject web3. For more information, see: https://medium.com/metamask/no-longer-injecting-web3-js-4a899ad6e59e`) hasBeenWarned = true } // return value normally diff --git a/package.json b/package.json index e4d096c58..e7e9e9211 100644 --- a/package.json +++ b/package.json @@ -123,7 +123,7 @@ "lodash": "^4.17.15", "loglevel": "^1.4.1", "luxon": "^1.8.2", - "metamask-inpage-provider": "^4.0.3", + "metamask-inpage-provider": "^4.0.4", "metamask-logo": "^2.1.4", "multihashes": "^0.4.12", "nanoid": "^2.1.6", diff --git a/yarn.lock b/yarn.lock index f0fdc0582..88a2e1388 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18868,10 +18868,10 @@ mersenne-twister@^1.0.1, mersenne-twister@^1.1.0: resolved "https://registry.yarnpkg.com/mersenne-twister/-/mersenne-twister-1.1.0.tgz#f916618ee43d7179efcf641bec4531eb9670978a" integrity sha1-+RZhjuQ9cXnvz2Qb7EUx65Zwl4o= -metamask-inpage-provider@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/metamask-inpage-provider/-/metamask-inpage-provider-4.0.3.tgz#856698255c2153b82203402c6b5337ca6363d9b0" - integrity sha512-JKbGkkR7qg+Z5Dayg6rpfXXzSVcXcp3BENbk2zgWwp/Aa70Sf9MHC7m364FeyIIio9A2r9OuJKV0Bcwmz0h+xg== +metamask-inpage-provider@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/metamask-inpage-provider/-/metamask-inpage-provider-4.0.4.tgz#697121873bf686a1fddc671832d9adbceda4c9ae" + integrity sha512-DCuqQ1NpAScesjvJac+8k4SbKzgcbmP78sAvo96i04qIszzH0LMg0dZLEViTz6/uqM7nU6JO3NIAcNF3iA2Lpw== dependencies: eth-json-rpc-errors "^2.0.0" fast-deep-equal "^2.0.1" From 8196818f2e1e2d412766ea51a80817d7323dcb56 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 6 Feb 2020 12:52:12 -0330 Subject: [PATCH 242/689] Delete multi_vault_planning.md (#7988) --- docs/multi_vault_planning.md | 188 ----------------------------------- 1 file changed, 188 deletions(-) delete mode 100644 docs/multi_vault_planning.md diff --git a/docs/multi_vault_planning.md b/docs/multi_vault_planning.md deleted file mode 100644 index fdde2bc50..000000000 --- a/docs/multi_vault_planning.md +++ /dev/null @@ -1,188 +0,0 @@ -https://hackmd.io/JwIwDMDGKQZgtAFgKZjEgbARhPAhgKxZbwAcA7LAWOQCaKEgFA==?edit - -Subscribablez(initState) - .subscribe() - .emitUpdate(newState) - //.getState() - - -var initState = fromDisk() -ReduxStore(reducer, initState) -.reduce(action) -> .emitUpdate() - -ReduxStore.subscribe(toDisk) - - -### KeyChainManager / idStore 2.0 (maybe just in MetaMaskController) - keychains: [] - getAllAccounts(cb) - getAllKeychainViewStates(cb) -> returns [ KeyChainViewState] - -#### Old idStore external methods, for feature parity: - -- init(configManager) -- setStore(ethStore) -- getState() -- getSelectedAddres() -- setSelectedAddress() -- createNewVault() -- recoverFromSeed() -- submitPassword() -- approveTransaction() -- cancelTransaction() -- addUnconfirmedMessage(msgParams, cb) -- signMessage() -- cancelMessage() -- setLocked() -- clearSeedWordCache() -- exportAccount() -- revealAccount() -- saveAccountLabel() -- tryPassword() -- recoverSeed() -- getNetwork() - -##### Of those methods - -Where they should end up: - -##### MetaMaskController - -- getNetwork() - -##### KeyChainManager - -- init(configManager) -- setStore(ethStore) -- getState() // Deprecate for unidirectional flow -- on('update', cb) -- createNewVault(password) -- getSelectedAddres() -- setSelectedAddress() -- submitPassword() -- tryPassword() -- approveTransaction() -- cancelTransaction() -- signMessage() -- cancelMessage() -- setLocked() -- exportAccount() - -##### Bip44 KeyChain - -- getState() // Deprecate for unidirectional flow -- on('update', cb) - -If we adopt a ReactStore style unidirectional action dispatching data flow, these methods will be unified under a `dispatch` method, and rather than having a cb will emit an update to the UI: - -- createNewKeyChain(entropy) -- recoverFromSeed() -- approveTransaction() -- signMessage() -- clearSeedWordCache() -- exportAccount() -- revealAccount() -- saveAccountLabel() -- recoverSeed() - -Additional methods, new to this: -- serialize() - - Returns pojo with optional `secret` key whose contents will be encrypted with the users' password and salt when written to disk. - - The isolation of secrets is to preserve performance when decrypting user data. -- deserialize(pojo) - -### KeyChain (ReduxStore?) - // attributes - @name - - signTx(txParams, cb) - signMsg(msg, cb) - - getAddressList(cb) - - getViewState(cb) -> returns KeyChainViewState - - serialize(cb) -> obj - deserialize(obj) - - dispatch({ type: , value: }) - - -### KeyChainViewState - // The serialized, renderable keychain data - accountList: [], - typeName: 'uPort', - iconAddress: 'uport.gif', - internal: {} // Subclass-defined metadata - -### KeyChainReactComponent - // takes a KeyChainViewState - - // Subclasses of this: - - KeyChainListItemComponent - - KeyChainInitComponent - Maybe part of the List Item - - KeyChainAccountHeaderComponent - - KeyChainConfirmationComponent - // Account list item, tx confirmation extra data (like a QR code), - // Maybe an options screen, init screen, - - how to send actions? - emitAction(keychains..didInit) - - -gimmeRemoteKeychain((err, remoteKeychain)=> - -) - - - - - -KeyChainReactComponent({ - keychain -}) - -Keychain: - methods:{}, - cachedAccountList: [], - name: '', - - -CoinbaseKeychain - getAccountList - - -CoinbaseKeychainComponent - isLoading = true - keychain.getAccountList(()=>{ - isLoading=false - accountList=accounts - }) - - - - - -KeyChainViewState { - attributes: { - //mandatory: - accountList: [], - typeName: 'uPort', - iconAddress: 'uport.gif', - - internal: { - // keychain-specific metadata - proxyAddresses: { - 0xReal: '0xProxy' - } - }, - }, - methods: { - // arbitrary, internal - } -} - -## A note on the security of arbitrary action dispatchers - -Since keychains will be dispatching actions that are then passed through the background process to be routed, we should not trust or require them to include their own keychain ID as a prefix to their action, but we should tack it on ourselves, so that no action dispatched by a KeyChainComponent ever reaches any KeyChain other than its own. - From 6f8d65cc61f4646e9d3607cecce75de7627585d9 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 6 Feb 2020 12:58:18 -0330 Subject: [PATCH 243/689] Delete video_script.txt (#7989) --- docs/video_script.txt | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 docs/video_script.txt diff --git a/docs/video_script.txt b/docs/video_script.txt deleted file mode 100644 index d9e37a4e2..000000000 --- a/docs/video_script.txt +++ /dev/null @@ -1,34 +0,0 @@ -Hi, and welcome to MetaMask. - -Today we’re happy to share our gift to the Ethereum ecosystem. - -The MetaMask browser extension turns Google Chrome into an Ethereum browser, letting websites retrieve data from the blockchain, and letting users securely manage identities and sign transactions. - -When you start up MetaMask, you are given a seed phrase that can be used to restore all the accounts you ever create within MetaMask. - -You can switch the current account with the switch account button in the top right, and you can add more accounts at the bottom of the account list. - -Your account vault is encrypted and locally stored within your browser, meaning no account information ever touches our servers. However, with your secret phrase, you can easily restore your vault with the same accounts. - -At first glance, Metamask enables you to send ether like a normal wallet application, but Metamask's true strength lies in enabling your browser to visit Ethereum enabled websites. - -Here’s a simple Ethereum distributed app, or Ðapp, called Tokens, that lets you easily deploy your own currency. - -When you visit a Dapp like Tokens with MetaMask installed, that website has access to the Ethereum blockchain via the standard Web3 Javascript API. When it wants to write to the blockchain, it asks web3 to send the transaction, prompting MetaMask to ask for user confirmation. - -After you submit a transaction, wait for the next block for the change to be reflected on the website...and there it is! - -Now I have my own MetaMaskCoins! I can check my balance or, if I want to send some to another account, I can click the copy link on it. I check its balance, see it has none, then send it some meta-coins! - -This has been nice, but it’s all been on the Morden test net. But with Metamask, I can always switch what network I’m working on, say the main network, and I’m ready issue a token with the full security of the main Ethereum blockchain. - -MetaMask connects to these blockchains with no synchronization time because we host blockchain nodes by default. You can always point MetaMask at your own Ethereum RPC Server, and fully control your connection to the blockchain. - -And that’s how MetaMask lets ordinary websites talk to a trusted Ethereum provider, all while letting the user store and manage their own private keys. We hope this will make it easier than ever for people to get started creating and using a new wave of blockchain-enabled websites. - -If you’d like to get started with Metamask right now, go ahead and click here to get the Chrome extension. - -If you’d like to learn more about MetaMask, you can visit our website at metamask.io. - -You’re also welcome to join our slack, follow our twitter or read our source code. You can find all of those links and more at Metamask.io - From 7e04be9b58ba4d30c40522576623e27fdfa4dcad Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 6 Feb 2020 13:07:48 -0330 Subject: [PATCH 244/689] Delete send-screen-QA-checklist.md (#7998) --- docs/send-screen-QA-checklist.md | 96 -------------------------------- 1 file changed, 96 deletions(-) delete mode 100644 docs/send-screen-QA-checklist.md diff --git a/docs/send-screen-QA-checklist.md b/docs/send-screen-QA-checklist.md deleted file mode 100644 index 52167b50b..000000000 --- a/docs/send-screen-QA-checklist.md +++ /dev/null @@ -1,96 +0,0 @@ -# Send screen QA checklist: - -This checklist can be to guide QA of the send screen. It can also be used to guide e2e tests for the send screen. - -Once all of these are QA verified on master, resolutions to any bugs related to the send screen should include and update to this list. - -Additional features or functionality on the send screen should include an update to this list. - -## Send Eth mode - - [ ] **Header** _It should:_ - - [ ] have title "Send ETH" - - [ ] have sub title "Only send ETH to an Ethereum address." - - [ ] return user to main screen when top right X is clicked - - [ ] **From row** _It should:_ - - [ ] show the currently selected account by default - - [ ] show a dropdown with all of the users accounts - - [ ] contain the following info for each account: identicon, account name, balance in ETH, balance in current currency - - [ ] change the account selected in the dropdown (but not the app-wide selected account) when one in the dropdown is clicked - - [ ] close the dropdown, without changing the dropdown selected account, when the dropdown is open and then a click happens outside it - - [ ] **To row** _It should:_ - - [ ] Show a placeholder with the text 'Recipient Address' by default - - [ ] Show, when clicked, a dropdown list of all 'to accounts': the users accounts, plus any other accounts they have previously sent to - - [ ] Show account address, and account name if it exists, of each item in the dropdown list - - [ ] Show a dropdown list of all to accounts (see above) whose address matches an address currently being typed in - - [ ] Set the input text to the address of an account clicked in the dropdown list, and also hide the dropdown - - [ ] Hide the dropdown without changing what is in the input if the user clicks outside the dropdown list while it is open - - [ ] Select the text in the input (i.e. the address) if an address is displayed and then clicked - - [ ] Show a 'required' error if the dropdown is opened but no account is selected - - [ ] Show an 'invalid address' error if text is entered in the input that cannot be a valid hex address or ens address - - [ ] Support ens names. (enter dinodan.eth on mainnet) After entering the plain text address, the hex address should appear in the input with a green checkmark beside - - [ ] Should show a 'no such address' error if a non-existent ens address is entered - - [ ] **Amount row** _It should:_ - - [ ] allow user to enter any rational number >= 0 - - [ ] allow user to copy and paste into the field - - [ ] show an insufficient funds error if an amount > balance - gas fee - - [ ] display 'ETH' after the number amount. The position of 'ETH' should change as the length of the input amount text changes - - [ ] display the value of the amount of ETH in the current currency, formatted in that currency - - [ ] show a 'max' but if amount < balance - gas fee - - [ ] show no max button or error if amount === balance - gas fee - - [ ] set the amount to balance - gas fee if the 'max' button is clicked - - [ ] **Gas Fee Display row** _It should:_ - - [ ] Default to the fee given by the estimated gas price - - [ ] display the fee in ETH and the current currency - - [ ] update when changes are made using the customize gas modal - - [ ] **Cancel button** _It should:_ - - [ ] Take the user back to the main screen - - [ ] **submit button** _It should:_ - - [ ] be disabled if no recipient address is provided or if any field is in error - - [ ] sign a transaction with the info in the above form, and display the details of that transaction on the confirm screen - -## Send token mode -- [ ] **Header** _It should:_ - - [ ] have title "Send Tokens" - - [ ] have sub title "Only send [token symbol] to an Ethereum address." - - [ ] return user to main screen when top right X is clicked -- [ ] **From row** _It should:_ - - [ ] Behave the same as 'Send ETH mode' (see above) -- [ ] **To row** _It should:_ - - [ ] Behave the same as 'Send ETH mode' (see above) -- [ ] **Amount row** _It should:_ - - [ ] allow user to enter any rational number >= 0 - - [ ] allow user to copy and paste into the field - - [ ] show an 'insufficient tokens' error if an amount > token balance - - [ ] show an 'insufficient funds' error if an gas fee > eth balance - - [ ] display [token symbol] after the number amount. The position of [token symbol] should change as the length of the input amount text changes - - [ ] display the value of the amount of tokens in the current currency, formatted in that currency - - [ ] show a 'max' but if amount < token balance - - [ ] show no max button or error if amount === token balance - - [ ] set the amount to token balance if the 'max' button is clicked -- [ ] **Gas Fee Display row** _It should:_ - - [ ] Behave the same as 'Send ETH mode' (see above) -- [ ] **Cancel button** _It should:_ - - [ ] Take the user back to the main screen -- [ ] **submit button** _It should:_ - - [ ] be disabled if no recipient address is provided or if any field is in error - - [ ] sign a token transaction with the info in the above form, and display the details of that transaction on the confirm screen - -## Edit send Eth mode - - [ ] Say 'Editing transaction' in the header - - [ ] display a button to go back to the confirmation screen without applying update - - [ ] say 'update transaction' on the submit button - - [ ] update the existing transaction, instead of signing a new one, when clicking the submit button - - [ ] Otherwise, behave the same as 'Send ETH mode' (see above) - -## Edit send token mode - - [ ] Behave the same as 'Edit send Eth mode' (see above) - -## Specific cases to test - - [ ] Send eth to a hex address - - [ ] Send eth to an ENS address - - [ ] Donate to the faucet at https://faucet.metamask.io/ and edit the transaction before confirming - - [ ] Send a token that is available on the 'Add Token' screen search to a hex address - - [ ] Create a custom token at https://tokenfactory.surge.sh/ and send it to a hex address - - [ ] Send a token to an ENS address - - [ ] Create a token transaction using https://tokenfactory.surge.sh/#/, and edit the transaction before confirming - - [ ] Send each of MKR, EOS and ICON using myetherwallet, and edit the transaction before confirming From dea8f0f24d74dbb2df570152a2c9c60a80bce356 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 6 Feb 2020 13:08:14 -0330 Subject: [PATCH 245/689] Use combineReducers for rootReducer (#7964) --- app/scripts/ui.js | 4 +- development/mock-dev.js | 13 +- test/lib/example-code.json | 3 - test/lib/mock-simple-keychain.js | 40 ------- test/lib/mock-store.js | 12 -- test/unit/actions/tx_test.js | 17 +-- test/unit/ui/app/actions.spec.js | 62 +++++----- test/unit/ui/app/reducers/app.spec.js | 87 ++++---------- test/unit/ui/app/reducers/metamask.spec.js | 92 ++------------ ui/app/ducks/app/app.js | 113 ++---------------- .../confirm-transaction.duck.js | 52 ++++---- .../confirm-transaction.duck.test.js | 106 +++++++--------- ui/app/ducks/gas/gas-duck.test.js | 80 ++++--------- ui/app/ducks/gas/gas.duck.js | 43 ++++--- ui/app/ducks/index.js | 107 +++-------------- ui/app/ducks/locale/locale.js | 14 +-- ui/app/ducks/metamask/metamask.js | 38 +----- ui/app/ducks/send/send-duck.test.js | 77 ++++-------- ui/app/ducks/send/send.duck.js | 19 ++- ui/app/pages/confirm-transaction/conf-tx.js | 7 +- ui/app/store/actions.js | 34 ++++-- ui/index.js | 46 +++++-- 22 files changed, 338 insertions(+), 728 deletions(-) delete mode 100644 test/lib/example-code.json delete mode 100644 test/lib/mock-simple-keychain.js delete mode 100644 test/lib/mock-store.js diff --git a/app/scripts/ui.js b/app/scripts/ui.js index f96d95955..571da940d 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -43,7 +43,9 @@ async function start () { // provide app state to append to error logs function getState () { // get app state - const state = window.getCleanAppState() + const state = window.getCleanAppState + ? window.getCleanAppState() + : {} // remove unnecessary data delete state.localeMessages delete state.metamask.recentBlocks diff --git a/development/mock-dev.js b/development/mock-dev.js index 957b930f3..ebc1cd6d5 100644 --- a/development/mock-dev.js +++ b/development/mock-dev.js @@ -13,11 +13,13 @@ import log from 'loglevel' import React from 'react' import { render } from 'react-dom' +import { createStore, applyMiddleware } from 'redux' +import thunkMiddleware from 'redux-thunk' import * as qs from 'qs' import Selector from './selector' import * as actions from '../ui/app/store/actions' import Root from '../ui/app/pages' -import configureStore from '../ui/app/store/store' +import rootReducer from '../ui/app/ducks' import MetamaskController from '../app/scripts/metamask-controller' import firstTimeState from '../app/scripts/first-time-state' import ExtensionPlatform from '../app/scripts/platforms/extension' @@ -92,7 +94,14 @@ function modifyBackgroundConnection (backgroundConnectionModifier) { } // parse opts -const store = configureStore(firstState) +const store = createStore( + (state, action) => + (action.type === 'GLOBAL_FORCE_UPDATE' + ? action.value + : rootReducer(state, action)), + firstState, + applyMiddleware(thunkMiddleware), +) // start app startApp() diff --git a/test/lib/example-code.json b/test/lib/example-code.json deleted file mode 100644 index b76d37a4c..000000000 --- a/test/lib/example-code.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "delegateCallCode": "0x606060405260e060020a60003504637bd703e8811461003157806390b98a111461005c578063f8b2cb4f1461008e575b005b6100b4600435600073f28c53067227848f8145355c455da5cfdd20e3136396e4ee3d6100da84610095565b6100c660043560243533600160a060020a03166000908152602081905260408120548290101561011f57506000610189565b6100b46004355b600160a060020a0381166000908152602081905260409020545b919050565b60408051918252519081900360200190f35b604080519115158252519081900360200190f35b60026040518360e060020a02815260040180838152602001828152602001925050506020604051808303818660325a03f4156100025750506040515191506100af9050565b33600160a060020a0390811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060015b9291505056" -} diff --git a/test/lib/mock-simple-keychain.js b/test/lib/mock-simple-keychain.js deleted file mode 100644 index 6d2603653..000000000 --- a/test/lib/mock-simple-keychain.js +++ /dev/null @@ -1,40 +0,0 @@ -const fakeWallet = { - privKey: '0x123456788890abcdef', - address: '0xfedcba0987654321', -} -const type = 'Simple Key Pair' - -export default class MockSimpleKeychain { - - static type () { - return type - } - - constructor (opts) { - this.type = type - this.opts = opts || {} - this.wallets = [] - } - - serialize () { - return [ fakeWallet.privKey ] - } - - deserialize (data) { - if (!Array.isArray(data)) { - throw new Error('Simple keychain deserialize requires a privKey array.') - } - this.wallets = [ fakeWallet ] - } - - addAccounts (n = 1) { - for (let i = 0; i < n; i++) { - this.wallets.push(fakeWallet) - } - } - - getAccounts () { - return this.wallets.map(w => w.address) - } - -} diff --git a/test/lib/mock-store.js b/test/lib/mock-store.js deleted file mode 100644 index b37d42c51..000000000 --- a/test/lib/mock-store.js +++ /dev/null @@ -1,12 +0,0 @@ -import { applyMiddleware, createStore } from 'redux' -import thunkMiddleware from 'redux-thunk' - -const rootReducer = function () {} - -export default configureStore - -const createStoreWithMiddleware = applyMiddleware(thunkMiddleware)(createStore) - -function configureStore (initialState) { - return createStoreWithMiddleware(rootReducer, initialState) -} diff --git a/test/unit/actions/tx_test.js b/test/unit/actions/tx_test.js index 50b54d43e..d0581294b 100644 --- a/test/unit/actions/tx_test.js +++ b/test/unit/actions/tx_test.js @@ -10,9 +10,6 @@ describe('tx confirmation screen', function () { const txId = 1457634084250832 const initialState = { appState: { - currentView: { - name: 'confTx', - }, }, metamask: { unapprovedTxs: { @@ -43,14 +40,12 @@ describe('tx confirmation screen', function () { done() }) - it('creates COMPLETED_TX with the cancelled transaction ID', function (done) { - store.dispatch(actions.cancelTx({ id: txId })) - .then(() => { - const storeActions = store.getActions() - const completedTxAction = storeActions.find(({ type }) => type === actions.actionConstants.COMPLETED_TX) - assert.equal(completedTxAction.value, txId) - done() - }) + it('creates COMPLETED_TX with the cancelled transaction ID', async function () { + await store.dispatch(actions.cancelTx({ id: txId })) + const storeActions = store.getActions() + const completedTxAction = storeActions.find(({ type }) => type === actions.actionConstants.COMPLETED_TX) + const { id } = completedTxAction.value + assert.equal(id, txId) }) }) }) diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js index b3aedd5a4..f25b71de4 100644 --- a/test/unit/ui/app/actions.spec.js +++ b/test/unit/ui/app/actions.spec.js @@ -1,9 +1,4 @@ -/* eslint-disable */ -// Used to inspect long objects -// util.inspect({JSON}, false, null)) -// const util = require('util') import assert from 'assert' - import sinon from 'sinon' import { cloneDeep } from 'lodash' import nock from 'nock' @@ -14,14 +9,13 @@ import EthQuery from 'eth-query' import Eth from 'ethjs' import KeyringController from 'eth-keyring-controller' import { createTestProviderTools } from '../../../stub/provider' -const provider = createTestProviderTools({ scaffold: {}}).provider - import enLocale from '../../../../app/_locales/en/messages.json' import * as actions from '../../../../ui/app/store/actions' import MetaMaskController from '../../../../app/scripts/metamask-controller' import firstTimeState from '../../localhostState' import devState from '../../../data/2-state.json' +const provider = createTestProviderTools({ scaffold: {} }).provider const middleware = [thunk] const mockStore = configureStore(middleware) @@ -133,9 +127,9 @@ describe('Actions', () => { await store.dispatch(actions.tryUnlockMetamask('test')) assert.fail('Should have thrown error') } catch (_) { - const actions = store.getActions() - const warning = actions.filter(action => action.type === 'DISPLAY_WARNING') - const unlockFailed = actions.filter(action => action.type === 'UNLOCK_FAILED') + const actions1 = store.getActions() + const warning = actions1.filter(action => action.type === 'DISPLAY_WARNING') + const unlockFailed = actions1.filter(action => action.type === 'UNLOCK_FAILED') assert.deepEqual(warning, displayWarningError) assert.deepEqual(unlockFailed, unlockFailedError) } @@ -450,7 +444,7 @@ describe('Actions', () => { { type: 'DISPLAY_WARNING', value: 'error' }, ] - checkHardwareStatusSpy.callsFake((deviceName, hdPath, callback) => { + checkHardwareStatusSpy.callsFake((_, __, callback) => { callback(new Error('error')) }) @@ -492,7 +486,7 @@ describe('Actions', () => { { type: 'DISPLAY_WARNING', value: 'error' }, ] - forgetDeviceSpy.callsFake((deviceName, callback) => { + forgetDeviceSpy.callsFake((_, callback) => { callback(new Error('error')) }) @@ -534,7 +528,7 @@ describe('Actions', () => { { type: 'DISPLAY_WARNING', value: 'error' }, ] - connectHardwareSpy.callsFake((deviceName, page, hdPath, callback) => { + connectHardwareSpy.callsFake((_, __, ___, callback) => { callback(new Error('error')) }) @@ -568,7 +562,7 @@ describe('Actions', () => { }) - it('shows loading indicator and displays error', async() => { + it('shows loading indicator and displays error', async () => { const store = mockStore() const expectedActions = [ @@ -576,7 +570,7 @@ describe('Actions', () => { { type: 'DISPLAY_WARNING', value: 'error' }, ] - unlockHardwareWalletAccountSpy.callsFake((deviceName, page, hdPath, callback) => { + unlockHardwareWalletAccountSpy.callsFake((_, __, ___, callback) => { callback(new Error('error')) }) @@ -646,7 +640,9 @@ describe('Actions', () => { }) it('calls signMsg in background', () => { - const store = mockStore() + const store = mockStore({ + metamask: {}, + }) signMessageSpy = sinon.spy(background, 'signMessage') store.dispatch(actions.signMsg(msgParams)) @@ -655,7 +651,9 @@ describe('Actions', () => { }) it('errors when signMessage in background throws', async () => { - const store = mockStore() + const store = mockStore({ + metamask: {}, + }) const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'UPDATE_METAMASK_STATE', value: undefined }, @@ -700,7 +698,9 @@ describe('Actions', () => { }) it('calls signPersonalMessage', () => { - const store = mockStore() + const store = mockStore({ + metamask: {}, + }) signPersonalMessageSpy = sinon.spy(background, 'signPersonalMessage') @@ -741,19 +741,19 @@ describe('Actions', () => { data: JSON.stringify({ 'types': { 'EIP712Domain': [ - {'name': 'name', 'type': 'string'}, - {'name': 'version', 'type': 'string'}, - {'name': 'chainId', 'type': 'uint256'}, - {'name': 'verifyingContract', 'type': 'address'}, + { 'name': 'name', 'type': 'string' }, + { 'name': 'version', 'type': 'string' }, + { 'name': 'chainId', 'type': 'uint256' }, + { 'name': 'verifyingContract', 'type': 'address' }, ], 'Person': [ - {'name': 'name', 'type': 'string'}, - {'name': 'wallet', 'type': 'address'}, + { 'name': 'name', 'type': 'string' }, + { 'name': 'wallet', 'type': 'address' }, ], 'Mail': [ - {'name': 'from', 'type': 'Person'}, - {'name': 'to', 'type': 'Person'}, - {'name': 'contents', 'type': 'string'}, + { 'name': 'from', 'type': 'Person' }, + { 'name': 'to', 'type': 'Person' }, + { 'name': 'contents', 'type': 'string' }, ], }, 'primaryType': 'Mail', @@ -952,7 +952,7 @@ describe('Actions', () => { const txData = { id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: txParams } - beforeEach( async () => { + beforeEach(async () => { await metamaskController.txController.txStateManager.addTx(txData) }) @@ -976,7 +976,7 @@ describe('Actions', () => { const store = mockStore() updateTransactionSpy = sinon.stub(background, 'updateTransaction') - updateTransactionSpy.callsFake((res, callback) => { + updateTransactionSpy.callsFake((_, callback) => { callback(new Error('error')) }) @@ -1347,7 +1347,7 @@ describe('Actions', () => { nock('https://shapeshift.io') .defaultReplyHeaders({ 'access-control-allow-origin': '*' }) .get('/marketinfo/btc_eth') - .reply(200, {pair: 'BTC_ETH', rate: 25.68289016, minerFee: 0.00176, limit: 0.67748474, minimum: 0.00013569, maxLimit: 0.67758573}) + .reply(200, { pair: 'BTC_ETH', rate: 25.68289016, minerFee: 0.00176, limit: 0.67748474, minimum: 0.00013569, maxLimit: 0.67758573 }) nock('https://shapeshift.io') .defaultReplyHeaders({ 'access-control-allow-origin': '*' }) @@ -1515,7 +1515,7 @@ describe('Actions', () => { const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, - { type: 'SET_CURRENT_LOCALE', value: { locale: 'en', messages: enLocale }}, + { type: 'SET_CURRENT_LOCALE', value: { locale: 'en', messages: enLocale } }, { type: 'HIDE_LOADING_INDICATION' }, ] diff --git a/test/unit/ui/app/reducers/app.spec.js b/test/unit/ui/app/reducers/app.spec.js index ce0eea32a..ea4215f06 100644 --- a/test/unit/ui/app/reducers/app.spec.js +++ b/test/unit/ui/app/reducers/app.spec.js @@ -7,13 +7,11 @@ const actions = actionConstants describe('App State', () => { const metamaskState = { - metamask: { - selectedAddress: '0xAddress', - identities: { - '0xAddress': { - name: 'account 1', - address: '0xAddress', - }, + selectedAddress: '0xAddress', + identities: { + '0xAddress': { + name: 'account 1', + address: '0xAddress', }, }, } @@ -24,7 +22,7 @@ describe('App State', () => { assert(initState) }) - it('sets networkd dropdown to true', () => { + it('sets networkDropdownOpen dropdown to true', () => { const state = reduceApp(metamaskState, { type: actions.NETWORK_DROPDOWN_OPEN, }) @@ -32,7 +30,7 @@ describe('App State', () => { assert.equal(state.networkDropdownOpen, true) }) - it('sets networkd dropdown to false', () => { + it('sets networkDropdownOpen dropdown to false', () => { const dropdown = { networkDropdowopen: true } const state = { ...metamaskState, ...dropdown } const newState = reduceApp(state, { @@ -129,7 +127,7 @@ describe('App State', () => { assert.equal(newState.modal.modalState.name, null) }) - it('tansitions forwards', () => { + it('transitions forwards', () => { const state = reduceApp(metamaskState, { type: actions.TRANSITION_FORWARD, }) @@ -137,22 +135,11 @@ describe('App State', () => { assert.equal(state.transForward, true) }) - it('sets forgot password', () => { - const state = reduceApp(metamaskState, { - type: actions.FORGOT_PASSWORD, - value: true, - }) - - assert.equal(state.currentView.name, 'restoreVault') - }) - it('shows send token page', () => { const state = reduceApp(metamaskState, { type: actions.SHOW_SEND_TOKEN_PAGE, }) - assert.equal(state.currentView.name, 'sendToken') - assert.equal(state.currentView.context, '0xAddress') assert.equal(state.transForward, true) assert.equal(state.warning, null) }) @@ -173,8 +160,6 @@ describe('App State', () => { type: actions.LOCK_METAMASK, }) - assert.equal(state.currentView.name, 'accountDetail') - assert.equal(state.currentView.context, '0xAddress') assert.equal(state.transForward, false) assert.equal(state.warning, null) }) @@ -184,7 +169,6 @@ describe('App State', () => { type: actions.GO_HOME, }) - assert.equal(state.currentView.name, 'accountDetail') assert.equal(state.accountDetail.subview, 'transactions') assert.equal(state.accountDetail.accountExport, 'none') assert.equal(state.accountDetail.privateKey, '') @@ -199,8 +183,6 @@ describe('App State', () => { value: 'context address', }) assert.equal(state.forgottenPassword, null) // default - assert.equal(state.currentView.name, 'accountDetail') - assert.equal(state.currentView.context, 'context address') assert.equal(state.accountDetail.subview, 'transactions') // default assert.equal(state.accountDetail.accountExport, 'none') // default assert.equal(state.accountDetail.privateKey, '') // default @@ -213,7 +195,6 @@ describe('App State', () => { type: actions.SHOW_ACCOUNTS_PAGE, }) - assert.equal(state.currentView.name, 'accounts') assert.equal(state.transForward, true) assert.equal(state.isLoading, false) assert.equal(state.warning, null) @@ -232,17 +213,14 @@ describe('App State', () => { }, }, } - const oldState = { - metamask: { ...metamaskState.metamask, ...txs }, - } + const oldState = { ...metamaskState, ...txs } const state = reduceApp(oldState, { type: actions.SHOW_CONF_TX_PAGE, id: 2, transForward: false, }) - assert.equal(state.currentView.name, 'confTx') - assert.equal(state.currentView.context, 1) + assert.equal(state.txId, 2) assert.equal(state.transForward, false) assert.equal(state.warning, null) assert.equal(state.isLoading, false) @@ -261,17 +239,16 @@ describe('App State', () => { }, } - const oldState = { - metamask: { ...metamaskState, ...txs }, - } + const oldState = { ...metamaskState, ...txs } const state = reduceApp(oldState, { type: actions.COMPLETED_TX, - value: 1, + value: { + id: 1, + }, }) - assert.equal(state.currentView.name, 'confTx') - assert.equal(state.currentView.context, 0) + assert.equal(state.txId, null) assert.equal(state.transForward, false) assert.equal(state.warning, null) }) @@ -279,25 +256,17 @@ describe('App State', () => { it('returns to account detail page when no unconf actions completed tx', () => { const state = reduceApp(metamaskState, { type: actions.COMPLETED_TX, + value: { + unconfirmedActionsCount: 0, + }, }) - assert.equal(state.currentView.name, 'accountDetail') - assert.equal(state.currentView.context, '0xAddress') assert.equal(state.transForward, false) assert.equal(state.warning, null) assert.equal(state.accountDetail.subview, 'transactions') }) - it('sets error message in confTx view', () => { - const state = reduceApp(metamaskState, { - type: actions.TRANSACTION_ERROR, - }) - - assert.equal(state.currentView.name, 'confTx') - assert.equal(state.currentView.errorMessage, 'There was a problem submitting this transaction.') - }) - it('sets default warning when unlock fails', () => { const state = reduceApp(metamaskState, { type: actions.UNLOCK_FAILED, @@ -423,13 +392,11 @@ describe('App State', () => { } const appState = { - appState: { - buyView: { - buyAddress: '0xAddress', - amount: '12.00', - formView: { - coinOptions, - }, + buyView: { + buyAddress: '0xAddress', + amount: '12.00', + formView: { + coinOptions, }, }, } @@ -477,10 +444,8 @@ describe('App State', () => { it('shows qr view', () => { const appState = { - appState: { - currentView: { - context: 'accounts', - }, + currentView: { + context: 'accounts', }, } @@ -493,8 +458,6 @@ describe('App State', () => { }, }) - assert.equal(state.currentView.name, 'qr') - assert.equal(state.currentView.context, 'accounts') assert.equal(state.transForward, true) assert.equal(state.Qr.message, 'message') assert.equal(state.Qr.data, 'data') diff --git a/test/unit/ui/app/reducers/metamask.spec.js b/test/unit/ui/app/reducers/metamask.spec.js index 7a55407b3..68c467781 100644 --- a/test/unit/ui/app/reducers/metamask.spec.js +++ b/test/unit/ui/app/reducers/metamask.spec.js @@ -1,13 +1,11 @@ import assert from 'assert' import reduceMetamask from '../../../../../ui/app/ducks/metamask/metamask' -import { actionConstants } from '../../../../../ui/app/store/actions' - -const actions = actionConstants +import { actionConstants as actions } from '../../../../../ui/app/store/actions' describe('MetaMask Reducers', () => { it('init state', () => { - const initState = reduceMetamask({ metamask: {} }, {}) + const initState = reduceMetamask(undefined, {}) assert(initState) }) @@ -24,11 +22,9 @@ describe('MetaMask Reducers', () => { it('locks MetaMask', () => { const unlockMetaMaskState = { - metamask: { - isUnlocked: true, - isInitialzed: false, - selectedAddress: 'test address', - }, + isUnlocked: true, + isInitialzed: false, + selectedAddress: 'test address', } const lockMetaMask = reduceMetamask(unlockMetaMaskState, { type: actions.LOCK_METAMASK, @@ -55,70 +51,6 @@ describe('MetaMask Reducers', () => { assert.equal(state.provider.type, 'provider type') }) - describe('CompletedTx', () => { - const oldState = { - metamask: { - unapprovedTxs: { - 1: { - id: 1, - time: 1538495996507, - status: 'unapproved', - metamaskNetworkId: 4, - loadingDefaults: false, - txParams: { - from: '0xAddress', - to: '0xAddress2', - value: '0x16345785d8a0000', - gas: '0x5208', - gasPrice: '0x3b9aca00', - }, - type: 'standard', - }, - 2: { - test: 'Should persist', - }, - }, - unapprovedMsgs: { - 1: { - id: 2, - msgParams: { - from: '0xAddress', - data: '0xData', - origin: 'test origin', - }, - time: 1538498521717, - status: 'unapproved', - type: 'eth_sign', - }, - 2: { - test: 'Should Persist', - }, - }, - }, - } - - it('removes tx from new state if completed in action.', () => { - - const state = reduceMetamask(oldState, { - type: actions.COMPLETED_TX, - id: 1, - }) - - assert.equal(Object.keys(state.unapprovedTxs).length, 1) - assert.equal(state.unapprovedTxs[2].test, 'Should persist') - }) - - it('removes msg from new state if completed id in action', () => { - const state = reduceMetamask(oldState, { - type: actions.COMPLETED_TX, - id: 1, - }) - - assert.equal(Object.keys(state.unapprovedMsgs).length, 1) - assert.equal(state.unapprovedTxs[2].test, 'Should persist') - }) - }) - it('shows account detail', () => { const state = reduceMetamask({}, { @@ -342,14 +274,12 @@ describe('MetaMask Reducers', () => { it('updates value of tx by id', () => { const oldState = { - metamask: { - selectedAddressTxList: [ - { - id: 1, - txParams: 'foo', - }, - ], - }, + selectedAddressTxList: [ + { + id: 1, + txParams: 'foo', + }, + ], } const state = reduceMetamask(oldState, { diff --git a/ui/app/ducks/app/app.js b/ui/app/ducks/app/app.js index fb2e7ea1f..4f16b5a21 100644 --- a/ui/app/ducks/app/app.js +++ b/ui/app/ducks/app/app.js @@ -1,33 +1,9 @@ -import txHelper from '../../../lib/tx-helper' -import log from 'loglevel' -import { actionConstants } from '../../store/actions' - -const actions = actionConstants +import { actionConstants as actions } from '../../store/actions' // Actions const SET_THREEBOX_LAST_UPDATED = 'metamask/app/SET_THREEBOX_LAST_UPDATED' -export default function reduceApp (state, action) { - log.debug('App Reducer got ' + action.type) - // clone and defaults - const selectedAddress = state.metamask.selectedAddress - const hasUnconfActions = checkUnconfActions(state) - let name = 'accounts' - if (selectedAddress) { - name = 'accountDetail' - } - - if (hasUnconfActions) { - log.debug('pending txs detected, defaulting to conf-tx view.') - name = 'confTx' - } - - const defaultView = { - name, - detailView: null, - context: selectedAddress, - } - +export default function reduceApp (state = {}, action) { // default state const appState = Object.assign({ shouldClose: false, @@ -52,7 +28,6 @@ export default function reduceApp (state, action) { alertMessage: null, qrCodeData: null, networkDropdownOpen: false, - currentView: defaultView, accountDetail: { subview: 'transactions', }, @@ -79,7 +54,7 @@ export default function reduceApp (state, action) { requestAccountTabs: {}, openMetaMaskTabs: {}, currentWindowTab: {}, - }, state.appState) + }, state) switch (action.type) { // dropdown methods @@ -157,7 +132,7 @@ export default function reduceApp (state, action) { return { ...appState, modal: Object.assign( - state.appState.modal, + appState.modal, { open: false }, { modalState: { name: null, props: {} } }, { previousModalState: appState.modal.modalState }, @@ -172,26 +147,14 @@ export default function reduceApp (state, action) { } case actions.FORGOT_PASSWORD: - const newState = { + return { ...appState, forgottenPassword: action.value, } - if (action.value) { - newState.currentView = { - name: 'restoreVault', - } - } - - return newState - case actions.SHOW_SEND_TOKEN_PAGE: return { ...appState, - currentView: { - name: 'sendToken', - context: appState.currentView.context, - }, transForward: true, warning: null, } @@ -211,7 +174,6 @@ export default function reduceApp (state, action) { case actions.LOCK_METAMASK: return { ...appState, - currentView: defaultView, transForward: false, warning: null, } @@ -221,10 +183,6 @@ export default function reduceApp (state, action) { case actions.GO_HOME: return { ...appState, - currentView: { - ...appState.currentView, - name: 'accountDetail', - }, accountDetail: { subview: 'transactions', accountExport: 'none', @@ -238,10 +196,6 @@ export default function reduceApp (state, action) { return { ...appState, forgottenPassword: appState.forgottenPassword ? !appState.forgottenPassword : null, - currentView: { - name: 'accountDetail', - context: action.value, - }, accountDetail: { subview: 'transactions', accountExport: 'none', @@ -253,9 +207,6 @@ export default function reduceApp (state, action) { case actions.SHOW_ACCOUNTS_PAGE: return { ...appState, - currentView: { - name: 'accounts', - }, transForward: true, isLoading: false, warning: null, @@ -266,44 +217,28 @@ export default function reduceApp (state, action) { case actions.SHOW_CONF_TX_PAGE: return { ...appState, - currentView: { - name: 'confTx', - context: action.id ? indexForPending(state, action.id) : 0, - }, + txId: action.id, transForward: action.transForward, warning: null, isLoading: false, } case actions.COMPLETED_TX: - log.debug('reducing COMPLETED_TX for tx ' + action.value) - const otherUnconfActions = getUnconfActionList(state) - .filter(tx => tx.id !== action.value) - const hasOtherUnconfActions = otherUnconfActions.length > 0 - - if (hasOtherUnconfActions) { - log.debug('reducer detected txs - rendering confTx view') + if (action.value.unconfirmedActionsCount > 0) { return { ...appState, transForward: false, - currentView: { - name: 'confTx', - context: 0, - }, + txId: null, warning: null, } } else { - log.debug('attempting to close popup') return { ...appState, // indicate notification should close shouldClose: true, transForward: false, warning: null, - currentView: { - name: 'accountDetail', - context: state.metamask.selectedAddress, - }, + txId: null, accountDetail: { subview: 'transactions', }, @@ -313,10 +248,6 @@ export default function reduceApp (state, action) { case actions.TRANSACTION_ERROR: return { ...appState, - currentView: { - name: 'confTx', - errorMessage: 'There was a problem submitting this transaction.', - }, } case actions.UNLOCK_FAILED: @@ -421,10 +352,6 @@ export default function reduceApp (state, action) { case actions.SHOW_QR_VIEW: return { ...appState, - currentView: { - name: 'qr', - context: appState.currentView.context, - }, transForward: true, Qr: { message: action.value.message, @@ -525,25 +452,3 @@ export function setThreeBoxLastUpdated (lastUpdated) { value: lastUpdated, } } - -// Helpers -function checkUnconfActions (state) { - const unconfActionList = getUnconfActionList(state) - const hasUnconfActions = unconfActionList.length > 0 - return hasUnconfActions -} - -function getUnconfActionList (state) { - const { unapprovedTxs, unapprovedMsgs, - unapprovedPersonalMsgs, unapprovedTypedMessages, network } = state.metamask - - const unconfActionList = txHelper(unapprovedTxs, unapprovedMsgs, unapprovedPersonalMsgs, unapprovedTypedMessages, network) - return unconfActionList -} - -function indexForPending (state, txId) { - const unconfTxList = getUnconfActionList(state) - const match = unconfTxList.find((tx) => tx.id === txId) - const index = unconfTxList.indexOf(match) - return index -} diff --git a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js index b8d1a7e81..e05445441 100644 --- a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js +++ b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js @@ -66,102 +66,102 @@ const initState = { } // Reducer -export default function reducer ({ confirmTransaction: confirmState = initState }, action = {}) { +export default function reducer (state = initState, action = {}) { switch (action.type) { case UPDATE_TX_DATA: return { - ...confirmState, + ...state, txData: { ...action.payload, }, } case CLEAR_TX_DATA: return { - ...confirmState, + ...state, txData: {}, } case UPDATE_TOKEN_DATA: return { - ...confirmState, + ...state, tokenData: { ...action.payload, }, } case CLEAR_TOKEN_DATA: return { - ...confirmState, + ...state, tokenData: {}, } case UPDATE_METHOD_DATA: return { - ...confirmState, + ...state, methodData: { ...action.payload, }, } case CLEAR_METHOD_DATA: return { - ...confirmState, + ...state, methodData: {}, } case UPDATE_TRANSACTION_AMOUNTS: const { fiatTransactionAmount, ethTransactionAmount, hexTransactionAmount } = action.payload return { - ...confirmState, - fiatTransactionAmount: fiatTransactionAmount || confirmState.fiatTransactionAmount, - ethTransactionAmount: ethTransactionAmount || confirmState.ethTransactionAmount, - hexTransactionAmount: hexTransactionAmount || confirmState.hexTransactionAmount, + ...state, + fiatTransactionAmount: fiatTransactionAmount || state.fiatTransactionAmount, + ethTransactionAmount: ethTransactionAmount || state.ethTransactionAmount, + hexTransactionAmount: hexTransactionAmount || state.hexTransactionAmount, } case UPDATE_TRANSACTION_FEES: const { fiatTransactionFee, ethTransactionFee, hexTransactionFee } = action.payload return { - ...confirmState, - fiatTransactionFee: fiatTransactionFee || confirmState.fiatTransactionFee, - ethTransactionFee: ethTransactionFee || confirmState.ethTransactionFee, - hexTransactionFee: hexTransactionFee || confirmState.hexTransactionFee, + ...state, + fiatTransactionFee: fiatTransactionFee || state.fiatTransactionFee, + ethTransactionFee: ethTransactionFee || state.ethTransactionFee, + hexTransactionFee: hexTransactionFee || state.hexTransactionFee, } case UPDATE_TRANSACTION_TOTALS: const { fiatTransactionTotal, ethTransactionTotal, hexTransactionTotal } = action.payload return { - ...confirmState, - fiatTransactionTotal: fiatTransactionTotal || confirmState.fiatTransactionTotal, - ethTransactionTotal: ethTransactionTotal || confirmState.ethTransactionTotal, - hexTransactionTotal: hexTransactionTotal || confirmState.hexTransactionTotal, + ...state, + fiatTransactionTotal: fiatTransactionTotal || state.fiatTransactionTotal, + ethTransactionTotal: ethTransactionTotal || state.ethTransactionTotal, + hexTransactionTotal: hexTransactionTotal || state.hexTransactionTotal, } case UPDATE_TOKEN_PROPS: const { tokenSymbol = '', tokenDecimals = '' } = action.payload return { - ...confirmState, + ...state, tokenProps: { - ...confirmState.tokenProps, + ...state.tokenProps, tokenSymbol, tokenDecimals, }, } case UPDATE_NONCE: return { - ...confirmState, + ...state, nonce: action.payload, } case UPDATE_TO_SMART_CONTRACT: return { - ...confirmState, + ...state, toSmartContract: action.payload, } case FETCH_DATA_START: return { - ...confirmState, + ...state, fetchingData: true, } case FETCH_DATA_END: return { - ...confirmState, + ...state, fetchingData: false, } case CLEAR_CONFIRM_TRANSACTION: return initState default: - return confirmState + return state } } diff --git a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js index 9e26314e5..423925cb7 100644 --- a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js +++ b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js @@ -46,40 +46,35 @@ const CLEAR_CONFIRM_TRANSACTION = 'metamask/confirm-transaction/CLEAR_CONFIRM_TR describe('Confirm Transaction Duck', () => { describe('State changes', () => { const mockState = { - confirmTransaction: { - txData: { - id: 1, - }, - tokenData: { - name: 'abcToken', - }, - methodData: { - name: 'approve', - }, - tokenProps: { - tokenDecimals: '3', - tokenSymbol: 'ABC', - }, - fiatTransactionAmount: '469.26', - fiatTransactionFee: '0.01', - fiatTransactionTotal: '1.000021', - ethTransactionAmount: '1', - ethTransactionFee: '0.000021', - ethTransactionTotal: '469.27', - hexTransactionAmount: '', - hexTransactionFee: '0x1319718a5000', - hexTransactionTotal: '', - nonce: '0x0', - toSmartContract: false, - fetchingData: false, + txData: { + id: 1, + }, + tokenData: { + name: 'abcToken', }, + methodData: { + name: 'approve', + }, + tokenProps: { + tokenDecimals: '3', + tokenSymbol: 'ABC', + }, + fiatTransactionAmount: '469.26', + fiatTransactionFee: '0.01', + fiatTransactionTotal: '1.000021', + ethTransactionAmount: '1', + ethTransactionFee: '0.000021', + ethTransactionTotal: '469.27', + hexTransactionAmount: '', + hexTransactionFee: '0x1319718a5000', + hexTransactionTotal: '', + nonce: '0x0', + toSmartContract: false, + fetchingData: false, } it('should initialize state', () => { - assert.deepEqual( - ConfirmTransactionReducer({}), - initialState - ) + assert.deepEqual(ConfirmTransactionReducer(undefined, {}), initialState) }) it('should return state unchanged if it does not match a dispatched actions type', () => { @@ -88,7 +83,7 @@ describe('Confirm Transaction Duck', () => { type: 'someOtherAction', value: 'someValue', }), - { ...mockState.confirmTransaction }, + { ...mockState }, ) }) @@ -101,9 +96,9 @@ describe('Confirm Transaction Duck', () => { }, }), { - ...mockState.confirmTransaction, + ...mockState, txData: { - ...mockState.confirmTransaction.txData, + ...mockState.txData, id: 2, }, } @@ -116,7 +111,7 @@ describe('Confirm Transaction Duck', () => { type: CLEAR_TX_DATA, }), { - ...mockState.confirmTransaction, + ...mockState, txData: {}, } ) @@ -131,9 +126,9 @@ describe('Confirm Transaction Duck', () => { }, }), { - ...mockState.confirmTransaction, + ...mockState, tokenData: { - ...mockState.confirmTransaction.tokenData, + ...mockState.tokenData, name: 'defToken', }, } @@ -146,7 +141,7 @@ describe('Confirm Transaction Duck', () => { type: CLEAR_TOKEN_DATA, }), { - ...mockState.confirmTransaction, + ...mockState, tokenData: {}, } ) @@ -161,9 +156,9 @@ describe('Confirm Transaction Duck', () => { }, }), { - ...mockState.confirmTransaction, + ...mockState, methodData: { - ...mockState.confirmTransaction.methodData, + ...mockState.methodData, name: 'transferFrom', }, } @@ -176,7 +171,7 @@ describe('Confirm Transaction Duck', () => { type: CLEAR_METHOD_DATA, }), { - ...mockState.confirmTransaction, + ...mockState, methodData: {}, } ) @@ -193,7 +188,7 @@ describe('Confirm Transaction Duck', () => { }, }), { - ...mockState.confirmTransaction, + ...mockState, fiatTransactionAmount: '123.45', ethTransactionAmount: '.5', hexTransactionAmount: '0x1', @@ -212,7 +207,7 @@ describe('Confirm Transaction Duck', () => { }, }), { - ...mockState.confirmTransaction, + ...mockState, fiatTransactionFee: '123.45', ethTransactionFee: '.5', hexTransactionFee: '0x1', @@ -231,7 +226,7 @@ describe('Confirm Transaction Duck', () => { }, }), { - ...mockState.confirmTransaction, + ...mockState, fiatTransactionTotal: '123.45', ethTransactionTotal: '.5', hexTransactionTotal: '0x1', @@ -249,7 +244,7 @@ describe('Confirm Transaction Duck', () => { }, }), { - ...mockState.confirmTransaction, + ...mockState, tokenProps: { tokenSymbol: 'DEF', tokenDecimals: '1', @@ -265,7 +260,7 @@ describe('Confirm Transaction Duck', () => { payload: '0x1', }), { - ...mockState.confirmTransaction, + ...mockState, nonce: '0x1', } ) @@ -278,7 +273,7 @@ describe('Confirm Transaction Duck', () => { payload: true, }), { - ...mockState.confirmTransaction, + ...mockState, toSmartContract: true, } ) @@ -290,7 +285,7 @@ describe('Confirm Transaction Duck', () => { type: FETCH_DATA_START, }), { - ...mockState.confirmTransaction, + ...mockState, fetchingData: true, } ) @@ -298,24 +293,13 @@ describe('Confirm Transaction Duck', () => { it('should set fetchingData to false when receiving a FETCH_DATA_END action', () => { assert.deepEqual( - ConfirmTransactionReducer({ confirmTransaction: { fetchingData: true } }, { - type: FETCH_DATA_END, - }), - { - fetchingData: false, - } + ConfirmTransactionReducer({ fetchingData: true }, { type: FETCH_DATA_END }), + { fetchingData: false }, ) }) it('should clear confirmTransaction when receiving a FETCH_DATA_END action', () => { - assert.deepEqual( - ConfirmTransactionReducer(mockState, { - type: CLEAR_CONFIRM_TRANSACTION, - }), - { - ...initialState, - } - ) + assert.deepEqual(ConfirmTransactionReducer(mockState, { type: CLEAR_CONFIRM_TRANSACTION }), initialState) }) }) diff --git a/ui/app/ducks/gas/gas-duck.test.js b/ui/app/ducks/gas/gas-duck.test.js index 5d62db9c2..966d3d7b3 100644 --- a/ui/app/ducks/gas/gas-duck.test.js +++ b/ui/app/ducks/gas/gas-duck.test.js @@ -93,9 +93,7 @@ describe('Gas Duck', () => { }) const mockState = { - gas: { - mockProp: 123, - }, + mockProp: 123, } const initState = { customData: { @@ -140,10 +138,7 @@ describe('Gas Duck', () => { describe('GasReducer()', () => { it('should initialize state', () => { - assert.deepEqual( - GasReducer({}), - initState - ) + assert.deepEqual(GasReducer(undefined, {}), initState) }) it('should return state unchanged if it does not match a dispatched actions type', () => { @@ -152,58 +147,45 @@ describe('Gas Duck', () => { type: 'someOtherAction', value: 'someValue', }), - Object.assign({}, mockState.gas) + mockState, ) }) it('should set basicEstimateIsLoading to true when receiving a BASIC_GAS_ESTIMATE_LOADING_STARTED action', () => { assert.deepEqual( - GasReducer(mockState, { - type: BASIC_GAS_ESTIMATE_LOADING_STARTED, - }), - Object.assign({ basicEstimateIsLoading: true }, mockState.gas) + GasReducer(mockState, { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }), + { basicEstimateIsLoading: true, ...mockState }, ) }) it('should set basicEstimateIsLoading to false when receiving a BASIC_GAS_ESTIMATE_LOADING_FINISHED action', () => { assert.deepEqual( - GasReducer(mockState, { - type: BASIC_GAS_ESTIMATE_LOADING_FINISHED, - }), - Object.assign({ basicEstimateIsLoading: false }, mockState.gas) + GasReducer(mockState, { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }), + { basicEstimateIsLoading: false, ...mockState }, ) }) it('should set gasEstimatesLoading to true when receiving a GAS_ESTIMATE_LOADING_STARTED action', () => { assert.deepEqual( - GasReducer(mockState, { - type: GAS_ESTIMATE_LOADING_STARTED, - }), - Object.assign({ gasEstimatesLoading: true }, mockState.gas) + GasReducer(mockState, { type: GAS_ESTIMATE_LOADING_STARTED }), + { gasEstimatesLoading: true, ...mockState } ) }) it('should set gasEstimatesLoading to false when receiving a GAS_ESTIMATE_LOADING_FINISHED action', () => { assert.deepEqual( - GasReducer(mockState, { - type: GAS_ESTIMATE_LOADING_FINISHED, - }), - Object.assign({ gasEstimatesLoading: false }, mockState.gas) + GasReducer(mockState, { type: GAS_ESTIMATE_LOADING_FINISHED }), + { gasEstimatesLoading: false, ...mockState }, ) }) - it('should return a new object (and not just modify the existing state object)', () => { - assert.deepEqual(GasReducer(mockState), mockState.gas) - assert.notEqual(GasReducer(mockState), mockState.gas) - }) - it('should set basicEstimates when receiving a SET_BASIC_GAS_ESTIMATE_DATA action', () => { assert.deepEqual( GasReducer(mockState, { type: SET_BASIC_GAS_ESTIMATE_DATA, value: { someProp: 'someData123' }, }), - Object.assign({ basicEstimates: { someProp: 'someData123' } }, mockState.gas) + { basicEstimates: { someProp: 'someData123' }, ...mockState }, ) }) @@ -213,7 +195,7 @@ describe('Gas Duck', () => { type: SET_PRICE_AND_TIME_ESTIMATES, value: { someProp: 'someData123' }, }), - Object.assign({ priceAndTimeEstimates: { someProp: 'someData123' } }, mockState.gas) + { priceAndTimeEstimates: { someProp: 'someData123' }, ...mockState }, ) }) @@ -223,7 +205,7 @@ describe('Gas Duck', () => { type: SET_CUSTOM_GAS_PRICE, value: 4321, }), - Object.assign({ customData: { price: 4321 } }, mockState.gas) + { customData: { price: 4321 }, ...mockState }, ) }) @@ -233,7 +215,7 @@ describe('Gas Duck', () => { type: SET_CUSTOM_GAS_LIMIT, value: 9876, }), - Object.assign({ customData: { limit: 9876 } }, mockState.gas) + { customData: { limit: 9876 }, ...mockState }, ) }) @@ -243,7 +225,7 @@ describe('Gas Duck', () => { type: SET_CUSTOM_GAS_TOTAL, value: 10000, }), - Object.assign({ customData: { total: 10000 } }, mockState.gas) + { customData: { total: 10000 }, ...mockState }, ) }) @@ -253,7 +235,7 @@ describe('Gas Duck', () => { type: SET_API_ESTIMATES_LAST_RETRIEVED, value: 1500000000000, }), - Object.assign({ priceAndTimeEstimatesLastRetrieved: 1500000000000 }, mockState.gas) + { priceAndTimeEstimatesLastRetrieved: 1500000000000, ...mockState }, ) }) @@ -263,7 +245,7 @@ describe('Gas Duck', () => { type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED, value: 1700000000000, }), - Object.assign({ basicPriceAndTimeEstimatesLastRetrieved: 1700000000000 }, mockState.gas) + { basicPriceAndTimeEstimatesLastRetrieved: 1700000000000, ...mockState }, ) }) @@ -273,35 +255,27 @@ describe('Gas Duck', () => { type: SET_CUSTOM_GAS_ERRORS, value: { someError: 'error_error' }, }), - Object.assign({ errors: { someError: 'error_error' } }, mockState.gas) + { errors: { someError: 'error_error' }, ...mockState }, ) }) it('should return the initial state in response to a RESET_CUSTOM_GAS_STATE action', () => { assert.deepEqual( - GasReducer(mockState, { - type: RESET_CUSTOM_GAS_STATE, - }), - Object.assign({}, initState) + GasReducer(mockState, { type: RESET_CUSTOM_GAS_STATE }), + initState, ) }) }) describe('basicGasEstimatesLoadingStarted', () => { it('should create the correct action', () => { - assert.deepEqual( - basicGasEstimatesLoadingStarted(), - { type: BASIC_GAS_ESTIMATE_LOADING_STARTED } - ) + assert.deepEqual(basicGasEstimatesLoadingStarted(), { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }) }) }) describe('basicGasEstimatesLoadingFinished', () => { it('should create the correct action', () => { - assert.deepEqual( - basicGasEstimatesLoadingFinished(), - { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED } - ) + assert.deepEqual(basicGasEstimatesLoadingFinished(), { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }) }) }) @@ -309,11 +283,9 @@ describe('Gas Duck', () => { it('should call fetch with the expected params', async () => { const mockDistpatch = sinon.spy() - await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: Object.assign( - {}, - initState, - { basicPriceAEstimatesLastRetrieved: 1000000 } - ) })) + await fetchBasicGasEstimates()(mockDistpatch, () => ({ + gas: { ...initState, basicPriceAEstimatesLastRetrieved: 1000000 }, + })) assert.deepEqual( mockDistpatch.getCall(0).args, [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ] diff --git a/ui/app/ducks/gas/gas.duck.js b/ui/app/ducks/gas/gas.duck.js index 2f27eafea..13a0fc5a1 100644 --- a/ui/app/ducks/gas/gas.duck.js +++ b/ui/app/ducks/gas/gas.duck.js @@ -28,7 +28,6 @@ const SET_API_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_API_ESTIMATES_LAST_RE const SET_BASIC_API_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_BASIC_API_ESTIMATES_LAST_RETRIEVED' const SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED' -// TODO: determine if this approach to initState is consistent with conventional ducks pattern const initState = { customData: { price: null, @@ -57,96 +56,94 @@ const initState = { } // Reducer -export default function reducer ({ gas: gasState = initState }, action = {}) { - const newState = clone(gasState) - +export default function reducer (state = initState, action) { switch (action.type) { case BASIC_GAS_ESTIMATE_LOADING_STARTED: return { - ...newState, + ...state, basicEstimateIsLoading: true, } case BASIC_GAS_ESTIMATE_LOADING_FINISHED: return { - ...newState, + ...state, basicEstimateIsLoading: false, } case GAS_ESTIMATE_LOADING_STARTED: return { - ...newState, + ...state, gasEstimatesLoading: true, } case GAS_ESTIMATE_LOADING_FINISHED: return { - ...newState, + ...state, gasEstimatesLoading: false, } case SET_BASIC_GAS_ESTIMATE_DATA: return { - ...newState, + ...state, basicEstimates: action.value, } case SET_CUSTOM_GAS_PRICE: return { - ...newState, + ...state, customData: { - ...newState.customData, + ...state.customData, price: action.value, }, } case SET_CUSTOM_GAS_LIMIT: return { - ...newState, + ...state, customData: { - ...newState.customData, + ...state.customData, limit: action.value, }, } case SET_CUSTOM_GAS_TOTAL: return { - ...newState, + ...state, customData: { - ...newState.customData, + ...state.customData, total: action.value, }, } case SET_PRICE_AND_TIME_ESTIMATES: return { - ...newState, + ...state, priceAndTimeEstimates: action.value, } case SET_CUSTOM_GAS_ERRORS: return { - ...newState, + ...state, errors: { - ...newState.errors, + ...state.errors, ...action.value, }, } case SET_API_ESTIMATES_LAST_RETRIEVED: return { - ...newState, + ...state, priceAndTimeEstimatesLastRetrieved: action.value, } case SET_BASIC_API_ESTIMATES_LAST_RETRIEVED: return { - ...newState, + ...state, basicPriceAndTimeEstimatesLastRetrieved: action.value, } case SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED: return { - ...newState, + ...state, basicPriceEstimatesLastRetrieved: action.value, } case RESET_CUSTOM_DATA: return { - ...newState, + ...state, customData: clone(initState.customData), } case RESET_CUSTOM_GAS_STATE: return clone(initState) default: - return newState + return state } } diff --git a/ui/app/ducks/index.js b/ui/app/ducks/index.js index 4786584b8..d0531dcee 100644 --- a/ui/app/ducks/index.js +++ b/ui/app/ducks/index.js @@ -1,90 +1,17 @@ -import { cloneDeep } from 'lodash' -import copyToClipboard from 'copy-to-clipboard' - -// -// Sub-Reducers take in the complete state and return their sub-state -// -import reduceMetamask from './metamask/metamask' - -import reduceLocale from './locale/locale' -import reduceSend from './send/send.duck' -import reduceApp from './app/app' -import reduceConfirmTransaction from './confirm-transaction/confirm-transaction.duck' -import reduceGas from './gas/gas.duck' - -window.METAMASK_CACHED_LOG_STATE = null - -export default rootReducer - -function rootReducer (state, action) { - // clone - state = { ...state } - - if (action.type === 'GLOBAL_FORCE_UPDATE') { - return action.value - } - - // - // MetaMask - // - - state.metamask = reduceMetamask(state, action) - - // - // AppState - // - - state.appState = reduceApp(state, action) - - // - // LocaleMessages - // - - state.localeMessages = reduceLocale(state, action) - - // - // Send - // - - state.send = reduceSend(state, action) - - state.confirmTransaction = reduceConfirmTransaction(state, action) - - state.gas = reduceGas(state, action) - - window.METAMASK_CACHED_LOG_STATE = state - return state -} - -window.getCleanAppState = function () { - const state = cloneDeep(window.METAMASK_CACHED_LOG_STATE) - // append additional information - state.version = global.platform.getVersion() - state.browser = window.navigator.userAgent - return state -} - -window.logStateString = function (cb) { - const state = window.getCleanAppState() - global.platform.getPlatformInfo((err, platform) => { - if (err) { - return cb(err) - } - state.platform = platform - const stateString = JSON.stringify(state, null, 2) - cb(null, stateString) - }) -} - -window.logState = function (toClipboard) { - return window.logStateString((err, result) => { - if (err) { - console.error(err.message) - } else if (toClipboard) { - copyToClipboard(result) - console.log('State log copied') - } else { - console.log(result) - } - }) -} +import { combineReducers } from 'redux' +import metamaskReducer from './metamask/metamask' +import localeMessagesReducer from './locale/locale' +import sendReducer from './send/send.duck' +import appStateReducer from './app/app' +import confirmTransactionReducer from './confirm-transaction/confirm-transaction.duck' +import gasReducer from './gas/gas.duck' + +export default combineReducers({ + activeTab: (s) => (s === undefined ? null : s), + metamask: metamaskReducer, + appState: appStateReducer, + send: sendReducer, + confirmTransaction: confirmTransactionReducer, + gas: gasReducer, + localeMessages: localeMessagesReducer, +}) diff --git a/ui/app/ducks/locale/locale.js b/ui/app/ducks/locale/locale.js index cbb334f1c..d815acfeb 100644 --- a/ui/app/ducks/locale/locale.js +++ b/ui/app/ducks/locale/locale.js @@ -1,17 +1,13 @@ import { actionConstants } from '../../store/actions' -export default reduceMetamask - -function reduceMetamask (state, action) { - const localeMessagesState = { ...state.localeMessages } - - switch (action.type) { +export default function reduceLocaleMessages (state = {}, { type, value }) { + switch (type) { case actionConstants.SET_CURRENT_LOCALE: return { - ...localeMessagesState, - current: action.value.messages, + ...state, + current: value.messages, } default: - return localeMessagesState + return state } } diff --git a/ui/app/ducks/metamask/metamask.js b/ui/app/ducks/metamask/metamask.js index 728d6f2e8..ce2b52a85 100644 --- a/ui/app/ducks/metamask/metamask.js +++ b/ui/app/ducks/metamask/metamask.js @@ -1,15 +1,8 @@ -import { actionConstants } from '../../store/actions' +import { actionConstants as actions } from '../../store/actions' import { getEnvironmentType } from '../../../../app/scripts/lib/util' import { ENVIRONMENT_TYPE_POPUP } from '../../../../app/scripts/lib/enums' -const actions = actionConstants - -export default reduceMetamask - -function reduceMetamask (state, action) { - let newState - - // clone + defaults +export default function reduceMetamask (state = {}, action) { const metamaskState = Object.assign({ isInitialized: false, isUnlocked: false, @@ -59,7 +52,7 @@ function reduceMetamask (state, action) { participateInMetaMetrics: null, metaMetricsSendCount: 0, nextNonce: null, - }, state.metamask) + }, state) switch (action.type) { @@ -97,25 +90,6 @@ function reduceMetamask (state, action) { }, } - case actions.COMPLETED_TX: - const stringId = String(action.id) - newState = { - ...metamaskState, - unapprovedTxs: {}, - unapprovedMsgs: {}, - } - for (const id in metamaskState.unapprovedTxs) { - if (id !== stringId) { - newState.unapprovedTxs[id] = metamaskState.unapprovedTxs[id] - } - } - for (const id in metamaskState.unapprovedMsgs) { - if (id !== stringId) { - newState.unapprovedMsgs[id] = metamaskState.unapprovedMsgs[id] - } - } - return newState - case actions.SHOW_ACCOUNT_DETAIL: return { ...metamaskState, @@ -124,8 +98,8 @@ function reduceMetamask (state, action) { selectedAddress: action.value, } - case actions.SET_SELECTED_TOKEN: - newState = { + case actions.SET_SELECTED_TOKEN: { + const newState = { ...metamaskState, selectedTokenAddress: action.value, } @@ -148,6 +122,7 @@ function reduceMetamask (state, action) { newState.send = newSend return newState + } case actions.SET_ACCOUNT_LABEL: const account = action.value.account @@ -411,6 +386,5 @@ function reduceMetamask (state, action) { default: return metamaskState - } } diff --git a/ui/app/ducks/send/send-duck.test.js b/ui/app/ducks/send/send-duck.test.js index d0e3ab7af..284cd37ac 100644 --- a/ui/app/ducks/send/send-duck.test.js +++ b/ui/app/ducks/send/send-duck.test.js @@ -10,9 +10,7 @@ import SendReducer, { describe('Send Duck', () => { const mockState = { - send: { - mockProp: 123, - }, + mockProp: 123, } const initState = { toDropdownOpen: false, @@ -28,10 +26,7 @@ describe('Send Duck', () => { describe('SendReducer()', () => { it('should initialize state', () => { - assert.deepEqual( - SendReducer({}), - initState - ) + assert.deepEqual(SendReducer(undefined, {}), initState) }) it('should return state unchanged if it does not match a dispatched actions type', () => { @@ -40,22 +35,16 @@ describe('Send Duck', () => { type: 'someOtherAction', value: 'someValue', }), - Object.assign({}, mockState.send) + mockState, ) }) - it('should return a new object (and not just modify the existing state object)', () => { - assert.deepEqual(SendReducer(mockState), mockState.send) - assert.notEqual(SendReducer(mockState), mockState.send) - }) - - it('should set toDropdownOpen to true when receiving a OPEN_TO_DROPDOWN action', () => { assert.deepEqual( SendReducer(mockState, { type: OPEN_TO_DROPDOWN, }), - Object.assign({ toDropdownOpen: true }, mockState.send) + { toDropdownOpen: true, ...mockState }, ) }) @@ -64,47 +53,43 @@ describe('Send Duck', () => { SendReducer(mockState, { type: CLOSE_TO_DROPDOWN, }), - Object.assign({ toDropdownOpen: false }, mockState.send) + { toDropdownOpen: false, ...mockState }, ) }) it('should set gasButtonGroupShown to true when receiving a SHOW_GAS_BUTTON_GROUP action', () => { assert.deepEqual( - SendReducer(Object.assign({}, mockState, { gasButtonGroupShown: false }), { - type: SHOW_GAS_BUTTON_GROUP, - }), - Object.assign({ gasButtonGroupShown: true }, mockState.send) + SendReducer({ ...mockState, gasButtonGroupShown: false }, { type: SHOW_GAS_BUTTON_GROUP }), + { gasButtonGroupShown: true, ...mockState }, ) }) it('should set gasButtonGroupShown to false when receiving a HIDE_GAS_BUTTON_GROUP action', () => { assert.deepEqual( - SendReducer(mockState, { - type: HIDE_GAS_BUTTON_GROUP, - }), - Object.assign({ gasButtonGroupShown: false }, mockState.send) + SendReducer(mockState, { type: HIDE_GAS_BUTTON_GROUP }), + { gasButtonGroupShown: false, ...mockState }, ) }) it('should extend send.errors with the value of a UPDATE_SEND_ERRORS action', () => { - const modifiedMockState = Object.assign({}, mockState, { - send: { - errors: { - someError: false, - }, + const modifiedMockState = { + ...mockState, + errors: { + someError: false, }, - }) + } assert.deepEqual( SendReducer(modifiedMockState, { type: UPDATE_SEND_ERRORS, value: { someOtherError: true }, }), - Object.assign({}, modifiedMockState.send, { + { + ...modifiedMockState, errors: { someError: false, someOtherError: true, }, - }) + }, ) }) @@ -113,44 +98,28 @@ describe('Send Duck', () => { SendReducer(mockState, { type: RESET_SEND_STATE, }), - Object.assign({}, initState) + initState, ) }) }) describe('openToDropdown', () => { - assert.deepEqual( - openToDropdown(), - { type: OPEN_TO_DROPDOWN } - ) + assert.deepEqual(openToDropdown(), { type: OPEN_TO_DROPDOWN }) }) describe('closeToDropdown', () => { - assert.deepEqual( - closeToDropdown(), - { type: CLOSE_TO_DROPDOWN } - ) + assert.deepEqual(closeToDropdown(), { type: CLOSE_TO_DROPDOWN }) }) describe('showGasButtonGroup', () => { - assert.deepEqual( - showGasButtonGroup(), - { type: SHOW_GAS_BUTTON_GROUP } - ) + assert.deepEqual(showGasButtonGroup(), { type: SHOW_GAS_BUTTON_GROUP }) }) describe('hideGasButtonGroup', () => { - assert.deepEqual( - hideGasButtonGroup(), - { type: HIDE_GAS_BUTTON_GROUP } - ) + assert.deepEqual(hideGasButtonGroup(), { type: HIDE_GAS_BUTTON_GROUP }) }) describe('updateSendErrors', () => { - assert.deepEqual( - updateSendErrors('mockErrorObject'), - { type: UPDATE_SEND_ERRORS, value: 'mockErrorObject' } - ) + assert.deepEqual(updateSendErrors('mockErrorObject'), { type: UPDATE_SEND_ERRORS, value: 'mockErrorObject' }) }) - }) diff --git a/ui/app/ducks/send/send.duck.js b/ui/app/ducks/send/send.duck.js index 385b80dab..fce3ee3e9 100644 --- a/ui/app/ducks/send/send.duck.js +++ b/ui/app/ducks/send/send.duck.js @@ -6,7 +6,6 @@ const RESET_SEND_STATE = 'metamask/send/RESET_SEND_STATE' const SHOW_GAS_BUTTON_GROUP = 'metamask/send/SHOW_GAS_BUTTON_GROUP' const HIDE_GAS_BUTTON_GROUP = 'metamask/send/HIDE_GAS_BUTTON_GROUP' -// TODO: determine if this approach to initState is consistent with conventional ducks pattern const initState = { toDropdownOpen: false, gasButtonGroupShown: true, @@ -14,42 +13,40 @@ const initState = { } // Reducer -export default function reducer ({ send: sendState = initState }, action = {}) { - const newState = { ...sendState } - +export default function reducer (state = initState, action) { switch (action.type) { case OPEN_TO_DROPDOWN: return { - ...newState, + ...state, toDropdownOpen: true, } case CLOSE_TO_DROPDOWN: return { - ...newState, + ...state, toDropdownOpen: false, } case UPDATE_SEND_ERRORS: return { - ...newState, + ...state, errors: { - ...newState.errors, + ...state.errors, ...action.value, }, } case SHOW_GAS_BUTTON_GROUP: return { - ...newState, + ...state, gasButtonGroupShown: true, } case HIDE_GAS_BUTTON_GROUP: return { - ...newState, + ...state, gasButtonGroupShown: false, } case RESET_SEND_STATE: return { ...initState } default: - return newState + return state } } diff --git a/ui/app/pages/confirm-transaction/conf-tx.js b/ui/app/pages/confirm-transaction/conf-tx.js index 60ea55e99..426aeeb3e 100644 --- a/ui/app/pages/confirm-transaction/conf-tx.js +++ b/ui/app/pages/confirm-transaction/conf-tx.js @@ -13,12 +13,15 @@ import Loading from '../../components/ui/loading-screen' import { DEFAULT_ROUTE } from '../../helpers/constants/routes' function mapStateToProps (state) { - const { metamask } = state + const { metamask, appState } = state const { unapprovedMsgCount, unapprovedPersonalMsgCount, unapprovedTypedMessagesCount, } = metamask + const { + txId, + } = appState return { identities: state.metamask.identities, @@ -26,7 +29,7 @@ function mapStateToProps (state) { unapprovedMsgs: state.metamask.unapprovedMsgs, unapprovedPersonalMsgs: state.metamask.unapprovedPersonalMsgs, unapprovedTypedMessages: state.metamask.unapprovedTypedMessages, - index: state.appState.currentView.context, + index: txId, warning: state.appState.warning, network: state.metamask.network, provider: state.metamask.provider, diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 01f4ea842..5dad5deb8 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -13,6 +13,7 @@ import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../app/scripts/lib/enums' import { hasUnconfirmedTransactions } from '../helpers/utils/confirm-tx.util' import { setCustomGasLimit } from '../ducks/gas/gas.duck' import WebcamUtils from '../../lib/webcam-utils' +import txHelper from '../../lib/tx-helper' export const actionConstants = { GO_HOME: 'GO_HOME', @@ -678,7 +679,7 @@ export function signTx (txData) { return dispatch(displayWarning(err.message)) } }) - dispatch(showConfTxPage({})) + dispatch(showConfTxPage()) } } @@ -858,7 +859,7 @@ export function signTokenTx (tokenAddress, toAddress, amount, txData) { dispatch(hideLoadingIndication()) dispatch(displayWarning(err.message)) }) - dispatch(showConfTxPage({})) + dispatch(showConfTxPage()) } } @@ -877,9 +878,7 @@ const updateMetamaskStateFromBackground = () => { } export function updateTransaction (txData) { - log.info('actions: updateTx: ' + JSON.stringify(txData)) return dispatch => { - log.debug(`actions calling background.updateTx`) dispatch(showLoadingIndication()) return new Promise((resolve, reject) => { @@ -906,9 +905,7 @@ export function updateTransaction (txData) { } export function updateAndApproveTx (txData) { - log.info('actions: updateAndApproveTx: ' + JSON.stringify(txData)) return (dispatch) => { - log.debug(`actions calling background.updateAndApproveTx`) dispatch(showLoadingIndication()) return new Promise((resolve, reject) => { background.updateAndApproveTransaction(txData, err => { @@ -944,9 +941,24 @@ export function updateAndApproveTx (txData) { } export function completedTx (id) { - return { - type: actionConstants.COMPLETED_TX, - value: id, + return (dispatch, getState) => { + const state = getState() + const { + unapprovedTxs, + unapprovedMsgs, + unapprovedPersonalMsgs, + unapprovedTypedMessages, + network, + } = state.metamask + const unconfirmedActions = txHelper(unapprovedTxs, unapprovedMsgs, unapprovedPersonalMsgs, unapprovedTypedMessages, network) + const otherUnconfirmedActions = unconfirmedActions.filter(tx => tx.id !== id) + dispatch({ + type: actionConstants.COMPLETED_TX, + value: { + id, + unconfirmedActionsCount: otherUnconfirmedActions.length, + }, + }) } } @@ -969,7 +981,6 @@ export function cancelMsg (msgData) { return (dispatch) => { dispatch(showLoadingIndication()) return new Promise((resolve, reject) => { - log.debug(`background.cancelMessage`) background.cancelMessage(msgData.id, (err, newState) => { dispatch(updateMetamaskState(newState)) dispatch(hideLoadingIndication()) @@ -1033,7 +1044,6 @@ export function cancelTypedMsg (msgData) { export function cancelTx (txData) { return (dispatch) => { - log.debug(`background.cancelTransaction`) dispatch(showLoadingIndication()) return new Promise((resolve, reject) => { background.cancelTransaction(txData.id, err => { @@ -1252,7 +1262,7 @@ export function showAccountsPage () { } } -export function showConfTxPage ({ transForward = true, id }) { +export function showConfTxPage ({ transForward = true, id } = {}) { return { type: actionConstants.SHOW_CONF_TX_PAGE, transForward, diff --git a/ui/index.js b/ui/index.js index d922a8244..d3e348f04 100644 --- a/ui/index.js +++ b/ui/index.js @@ -1,3 +1,6 @@ +import copyToClipboard from 'copy-to-clipboard' +import log from 'loglevel' +import { clone } from 'lodash' import React from 'react' import { render } from 'react-dom' import Root from './app/pages' @@ -6,13 +9,10 @@ import configureStore from './app/store/store' import txHelper from './lib/tx-helper' import { fetchLocale } from './app/helpers/utils/i18n-helper' import switchDirection from './app/helpers/utils/switch-direction' -import log from 'loglevel' - -export default launchMetamaskUi log.setLevel(global.METAMASK_DEBUG ? 'debug' : 'warn') -function launchMetamaskUi (opts, cb) { +export default function launchMetamaskUi (opts, cb) { const { backgroundConnection } = opts actions._setBackgroundConnection(backgroundConnection) // check if we are unlocked first @@ -22,6 +22,7 @@ function launchMetamaskUi (opts, cb) { } startApp(metamaskState, backgroundConnection, opts) .then((store) => { + setupDebuggingHelpers(store) cb(null, store) }) }) @@ -55,9 +56,6 @@ async function startApp (metamaskState, backgroundConnection, opts) { current: currentLocaleMessages, en: enLocaleMessages, }, - - // Which blockchain we are using: - networkVersion: opts.networkVersion, }) // if unconfirmed txs, start on txConf page @@ -104,3 +102,37 @@ async function startApp (metamaskState, backgroundConnection, opts) { return store } + +function setupDebuggingHelpers (store) { + window.getCleanAppState = function () { + const state = clone(store.getState()) + state.version = global.platform.getVersion() + state.browser = window.navigator.userAgent + return state + } +} + +window.logStateString = function (cb) { + const state = window.getCleanAppState() + global.platform.getPlatformInfo((err, platform) => { + if (err) { + return cb(err) + } + state.platform = platform + const stateString = JSON.stringify(state, null, 2) + cb(null, stateString) + }) +} + +window.logState = function (toClipboard) { + return window.logStateString((err, result) => { + if (err) { + console.error(err.message) + } else if (toClipboard) { + copyToClipboard(result) + console.log('State log copied') + } else { + console.log(result) + } + }) +} From d368464b7bb5a31cbd18ad249766aadf6c978b82 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 6 Feb 2020 13:15:46 -0330 Subject: [PATCH 246/689] Delete adding-new-networks.md (#7999) --- docs/adding-new-networks.md | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 docs/adding-new-networks.md diff --git a/docs/adding-new-networks.md b/docs/adding-new-networks.md deleted file mode 100644 index 40925f135..000000000 --- a/docs/adding-new-networks.md +++ /dev/null @@ -1,24 +0,0 @@ -## Adding Custom Networks - -To add another network to our dropdown menu, make sure the following files are adjusted properly: - -``` -app/scripts/config.js -app/scripts/lib/buy-eth-url.js -ui/app/index.js -ui/app/components/buy-button-subview.js -ui/app/components/drop-menu-item.js -ui/app/components/network.js -ui/app/components/transaction-list-item.js -ui/app/config.js -ui/app/css/lib.css -ui/lib/account-link.js -ui/lib/explorer-link.js -``` - -You will need: -+ The network ID -+ An RPC Endpoint url -+ An explorer link -+ CSS for the display icon - From fbfaa6eb106dfab75f98b1f5b0f959a05facc536 Mon Sep 17 00:00:00 2001 From: ricky Date: Thu, 6 Feb 2020 14:34:23 -0500 Subject: [PATCH 247/689] Use readOnly (#7995) --- .../amount-max-button/amount-max-button.component.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js index cd90ca4ae..420ba1b75 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js @@ -65,7 +65,7 @@ export default class AmountMaxButton extends Component { return (

    - +
    {this.context.t('max')}
    From f928b1f69f26b5363ea622f0a65b2e49e74e2f99 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 6 Feb 2020 16:52:38 -0330 Subject: [PATCH 248/689] Delete developing-on-deps.md (#8004) --- README.md | 1 - docs/developing-on-deps.md | 9 --------- 2 files changed, 10 deletions(-) delete mode 100644 docs/developing-on-deps.md diff --git a/README.md b/README.md index 07c4fe7c7..71d03d96f 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,6 @@ To write tests that will be run in the browser using QUnit, add your test files - [How to add custom build to Firefox](./docs/add-to-firefox.md) - [How to add a new translation to MetaMask](./docs/translating-guide.md) - [Publishing Guide](./docs/publishing.md) -- [How to live reload on local dependency changes](./docs/developing-on-deps.md) - [How to add new networks to the Provider Menu](./docs/adding-new-networks.md) - [How to port MetaMask to a new platform](./docs/porting_to_new_environment.md) - [How to use the TREZOR emulator](./docs/trezor-emulator.md) diff --git a/docs/developing-on-deps.md b/docs/developing-on-deps.md deleted file mode 100644 index 20c0f7c97..000000000 --- a/docs/developing-on-deps.md +++ /dev/null @@ -1,9 +0,0 @@ -### Developing on Dependencies - -To enjoy the live-reloading that `gulp dev` offers while working on the dependencies: - - 1. Clone the dependency locally. - 2. `npm install` or `yarn install` in its folder. - 3. Run `yarn link` in its folder. - 4. Run `yarn link $DEP_NAME` in this project folder. - 5. Next time you `yarn start` it will watch the dependency for changes as well! From 96802b84c5e2953ac819ef0b6ee1374abd1f8cbe Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 6 Feb 2020 18:26:48 -0330 Subject: [PATCH 249/689] Delete limited_site_access.md (#8007) --- docs/limited_site_access.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 docs/limited_site_access.md diff --git a/docs/limited_site_access.md b/docs/limited_site_access.md deleted file mode 100644 index f703d5c7e..000000000 --- a/docs/limited_site_access.md +++ /dev/null @@ -1,5 +0,0 @@ -# Google Chrome/Brave Limited Site Access for Extensions - -Problem: MetaMask doesn't work with limited site access enabled under Chrome's extensions. - -Solution: In addition to the site you wish to whitelist, you must add 'api.infura.io' as another domain, so the MetaMask extension is authorized to make RPC calls to Infura. From 712f3eb637fad9eda67d28121e2d62a1fbfc58ab Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 6 Feb 2020 18:42:22 -0330 Subject: [PATCH 250/689] Update README.md (#8005) --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 71d03d96f..24d7b0c98 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,6 @@ To write tests that will be run in the browser using QUnit, add your test files - [How to add custom build to Firefox](./docs/add-to-firefox.md) - [How to add a new translation to MetaMask](./docs/translating-guide.md) - [Publishing Guide](./docs/publishing.md) -- [How to add new networks to the Provider Menu](./docs/adding-new-networks.md) - [How to port MetaMask to a new platform](./docs/porting_to_new_environment.md) - [How to use the TREZOR emulator](./docs/trezor-emulator.md) - [How to generate a visualization of this repository's development](./development/gource-viz.sh) From 1eb828f7f0333f754aac5ba70319d6fbd6888b14 Mon Sep 17 00:00:00 2001 From: William Morriss Date: Thu, 6 Feb 2020 14:25:45 -0800 Subject: [PATCH 251/689] Add support for 24 word seed phrases (#7987) --- app/_locales/en/messages.json | 2 +- .../import-with-seed-phrase.component.js | 3 ++- .../confirm-seed-phrase/confirm-seed-phrase.component.js | 4 ---- ui/app/pages/keychains/restore-vault.js | 3 ++- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 64c95545a..d6b0e2bcc 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1187,7 +1187,7 @@ "message": "Separate each word with a single space" }, "seedPhraseReq": { - "message": "Seed phrases are 12 words long" + "message": "Seed phrases contain 12, 15, 18, 21, or 24 words" }, "selectCurrency": { "message": "Select Currency" diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js index 12eb4900f..2ea69f832 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js @@ -73,7 +73,8 @@ export default class ImportWithSeedPhrase extends PureComponent { if (seedPhrase) { const parsedSeedPhrase = this.parseSeedPhrase(seedPhrase) - if (parsedSeedPhrase.split(' ').length !== 12) { + const wordCount = parsedSeedPhrase.split(new RegExp('\\s')).length + if (wordCount % 3 !== 0 || wordCount > 24 || wordCount < 12) { seedPhraseError = this.context.t('seedPhraseReq') } else if (!validateMnemonic(parsedSeedPhrase)) { seedPhraseError = this.context.t('invalidSeedPhrase') diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js index 2f04a9055..cab59f4dc 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js @@ -271,9 +271,5 @@ function insert (list, value, target, removeOld) { }) } - if (nextList.length > 12) { - nextList.pop() - } - return nextList } diff --git a/ui/app/pages/keychains/restore-vault.js b/ui/app/pages/keychains/restore-vault.js index ff0e2aa1d..425aa3fbc 100644 --- a/ui/app/pages/keychains/restore-vault.js +++ b/ui/app/pages/keychains/restore-vault.js @@ -42,7 +42,8 @@ class RestoreVaultPage extends Component { handleSeedPhraseChange (seedPhrase) { let seedPhraseError = null - if (seedPhrase && this.parseSeedPhrase(seedPhrase).split(' ').length !== 12) { + const wordCount = this.parseSeedPhrase(seedPhrase).split(new RegExp('\\s')).length + if (seedPhrase && (wordCount % 3 !== 0 || wordCount < 12 || wordCount > 24)) { seedPhraseError = this.context.t('seedPhraseReq') } From 1d654d6c4ef40ee6d65e7cb4f4753cf7a9754eca Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 6 Feb 2020 18:56:31 -0330 Subject: [PATCH 252/689] Remove version bump scripts (#8006) --- development/rollback.sh | 35 - development/run-version-bump.js | 46 - development/version-bump.js | 50 - docs/bumping_version.md | 33 - package.json | 2 - test/unit/development/sample-changelog.md | 914 ------------------- test/unit/development/sample-manifest.json | 71 -- test/unit/development/version–bump-test.js | 46 - 8 files changed, 1197 deletions(-) delete mode 100755 development/rollback.sh delete mode 100644 development/run-version-bump.js delete mode 100644 development/version-bump.js delete mode 100644 docs/bumping_version.md delete mode 100644 test/unit/development/sample-changelog.md delete mode 100644 test/unit/development/sample-manifest.json delete mode 100644 test/unit/development/version–bump-test.js diff --git a/development/rollback.sh b/development/rollback.sh deleted file mode 100755 index a3040e6f1..000000000 --- a/development/rollback.sh +++ /dev/null @@ -1,35 +0,0 @@ -#! /bin/bash - -[[ -z "$1" ]] && { echo "Rollback version is required!" ; exit 1; } -echo "Rolling back to version $1" - -# Checkout branch to increment version -git checkout -b "version-increment-$1" -yarn version:bump patch - -# Store the new version name -NEW_VERSION=$(jq -r .version < app/manifest.json) - -# Make sure origin tags are loaded -git fetch origin - -# check out the rollback branch -git checkout "origin/v$1" - -# Create the rollback branch. -git checkout -b "Version-$NEW_VERSION-Rollback-to-$1" - -# Set the version files to the next one. -git checkout master CHANGELOG.md -git checkout master app/manifest.json -git commit -m "Version $NEW_VERSION (Rollback to $1)" - -# Push the new branch to PR -git push -u origin HEAD - -# Create tag and push that up too -git tag "v${NEW_VERSION}" -git push origin "v${NEW_VERSION}" - -# Cleanup version branch -git branch -D "version-increment-$1" diff --git a/development/run-version-bump.js b/development/run-version-bump.js deleted file mode 100644 index 2868f7c0d..000000000 --- a/development/run-version-bump.js +++ /dev/null @@ -1,46 +0,0 @@ -const promisify = require('pify') -const fs = require('fs') - -const readFile = promisify(fs.readFile) -const writeFile = promisify(fs.writeFile) -const path = require('path') - -const changelogPath = path.join(__dirname, '..', 'CHANGELOG.md') -const manifestPath = path.join(__dirname, '..', 'app', 'manifest.json') -const manifest = require('../app/manifest.json') -const versionBump = require('./version-bump') - -const bumpType = normalizeType(process.argv[2]) - -start().catch(console.error) - -async function start () { - - const changeBuffer = await readFile(changelogPath) - const changelog = changeBuffer.toString() - - const newData = await versionBump(bumpType, changelog, manifest) - - const manifestString = JSON.stringify(newData.manifest, null, 2) - - await writeFile(changelogPath, newData.changelog) - await writeFile(manifestPath, manifestString) - - console.log(`Bumped ${bumpType} to version ${newData.version}`) -} - - -function normalizeType (userInput) { - const err = new Error('First option must be a type (major, minor, or patch)') - if (!userInput || typeof userInput !== 'string') { - throw err - } - - const lower = userInput.toLowerCase() - - if (lower !== 'major' && lower !== 'minor' && lower !== 'patch') { - throw err - } - - return lower -} diff --git a/development/version-bump.js b/development/version-bump.js deleted file mode 100644 index 74c321b26..000000000 --- a/development/version-bump.js +++ /dev/null @@ -1,50 +0,0 @@ -const { cloneDeep } = require('lodash') - -async function versionBump (bumpType, changelog, oldManifest) { - const manifest = cloneDeep(oldManifest) - const newVersion = newVersionFrom(manifest, bumpType) - - manifest.version = newVersion - const date = (new Date()).toDateString() - - const logHeader = `\n## ${newVersion} ${date}` - const logLines = changelog.split('\n') - for (let i = 0; i < logLines.length; i++) { - if (logLines[i].includes('Current Develop Branch')) { - logLines.splice(i + 1, 0, logHeader) - break - } - } - - return { - version: newVersion, - manifest: manifest, - changelog: logLines.join('\n'), - } -} - -function newVersionFrom (manifest, bumpType) { - const string = manifest.version - const segments = string.split('.').map((str) => parseInt(str)) - - switch (bumpType) { - case 'major': - segments[0] += 1 - segments[1] = 0 - segments[2] = 0 - break - case 'minor': - segments[1] += 1 - segments[2] = 0 - break - case 'patch': - segments[2] += 1 - break - default: - throw new Error(`invalid bumpType ${bumpType}`) - } - - return segments.map(String).join('.') -} - -module.exports = versionBump diff --git a/docs/bumping_version.md b/docs/bumping_version.md deleted file mode 100644 index 5b4ca40a6..000000000 --- a/docs/bumping_version.md +++ /dev/null @@ -1,33 +0,0 @@ -# How to Bump MetaMask's Version Automatically - -``` -yarn version:bump patch -``` - -MetaMask publishes using a loose [semver](https://semver.org/) interpretation. We divide the three segments of our version into three types of version bump: - -## Major - -Means a breaking change, either an API removed, or a major user expectation changed. - -## Minor - -Means a new API or new user feature. - -## Patch - -Means a fix for a bug, or correcting something that should have been assumed to work a different way. - -# Bumping the version - -`yarn version:bump $BUMP_TYPE` where `$BUMP_TYPE` is one of `major`, `minor`, or `patch`. - -This will increment the version in the `app/manifest.json` and `CHANGELOG.md` files according to our current protocol, where the manifest's version is updated, and any line items currently under the changelog's "master" section are now under the new dated version section. - -# Modifying the bump script - -The script that is executed lives [here](../development/run-version-bump.js). -The main functions all live [here](../development/version-bump.js). -The test for this behavior is at `test/unit/development/version-bump-test.js`. - - diff --git a/package.json b/package.json index e7e9e9211..53357a0db 100644 --- a/package.json +++ b/package.json @@ -49,12 +49,10 @@ "devtools:redux": "remotedev --hostname=localhost --port=8000", "start:dev": "concurrently -k -n build,react,redux yarn:start yarn:devtools:react yarn:devtools:redux", "announce": "node development/announcer.js", - "version:bump": "node development/run-version-bump.js", "storybook": "start-storybook -p 6006 -c .storybook", "storybook:build": "build-storybook -c .storybook -o .out", "storybook:deploy": "storybook-to-ghpages", "update-changelog": "./development/auto-changelog.sh", - "rollback": "./development/rollback.sh", "generate:migration": "./development/generate-migration.sh" }, "resolutions": { diff --git a/test/unit/development/sample-changelog.md b/test/unit/development/sample-changelog.md deleted file mode 100644 index 69f6513e6..000000000 --- a/test/unit/development/sample-changelog.md +++ /dev/null @@ -1,914 +0,0 @@ -# Changelog - -## Current Develop Branch - -## 4.1.3 2018-2-28 - -- Ensure MetaMask's inpage provider is named MetamaskInpageProvider to keep some sites from breaking. -- Add retry transaction button back into classic ui. - -## 4.1.2 2018-2-28 - -- Actually includes all the fixes mentioned in 4.1.1 (sorry) - -## 4.1.1 2018-2-28 - -- Fix "Add Token" screen referencing missing token logo urls -- Prevent user from switching network during signature request -- Fix misleading language "Contract Published" -> "Contract Deployment" -- Fix cancel button on "Buy Eth" screen -- Improve new-ui onboarding flow style - -## 4.1.0 2018-2-27 - -- Report failed txs to Sentry with more specific message -- Fix internal feature flags being sometimes undefined -- Standardized license to MIT - -## 4.0.0 2018-2-22 - -- Introduce new MetaMask user interface. - -## 3.14.2 2018-2-15 - -- Fix bug where log subscriptions would break when switching network. -- Fix bug where storage values were cached across blocks. -- Add MetaMask light client [testing container](https://github.com/MetaMask/mesh-testing) - -## 3.14.1 2018-2-1 - -- Further fix scrolling for Firefox. - -## 3.14.0 2018-2-1 - -- Removed unneeded data from storage -- Add a "reset account" feature to Settings -- Add warning for importing some kinds of files. -- Scrollable Setting view for Firefox. - -## 3.13.8 2018-1-29 - -- Fix provider for Kovan network. -- Bump limit for EventEmitter listeners before warning. -- Display Error when empty string is entered as a token address. - -## 3.13.7 2018-1-22 - -- Add ability to bypass gas estimation loading indicator. -- Forward failed transactions to Sentry error reporting service -- Re-add changes from 3.13.5 - -## 3.13.6 2017-1-18 - -- Roll back changes to 3.13.4 to fix some issues with the new Infura REST provider. - -## 3.13.5 2018-1-16 - -- Estimating gas limit for simple ether sends now faster & cheaper, by avoiding VM usage on recipients with no code. -- Add an extra px to address for Firefox clipping. -- Fix Firefox scrollbar. -- Open MetaMask popup for transaction confirmation before gas estimation finishes and add a loading screen over transaction confirmation. -- Fix bug that prevented eth_signTypedData from signing bytes. -- Further improve gas price estimation. - -## 3.13.4 2018-1-9 - -- Remove recipient field if application initializes a tx with an empty string, or 0x, and tx data. Throw an error with the same condition, but without tx data. -- Improve gas price suggestion to be closer to the lowest that will be accepted. -- Throw an error if a application tries to submit a tx whose value is a decimal, and inform that it should be in wei. -- Fix bug that prevented updating custom token details. -- No longer mark long-pending transactions as failed, since we now have button to retry with higher gas. -- Fix rounding error when specifying an ether amount that has too much precision. -- Fix bug where incorrectly inputting seed phrase would prevent any future attempts from succeeding. - -## 3.13.3 2017-12-14 - -- Show tokens that are held that have no balance. -- Reduce load on Infura by using a new block polling endpoint. - -## 3.13.2 2017-12-9 - -- Reduce new block polling interval to 8000 ms, to ease server load. - -## 3.13.1 2017-12-7 - -- Allow Dapps to specify a transaction nonce, allowing dapps to propose resubmit and force-cancel transactions. - -## 3.13.0 2017-12-7 - -- Allow resubmitting transactions that are taking long to complete. - -## 3.12.1 2017-11-29 - -- Fix bug where a user could be shown two different seed phrases. -- Detect when multiple web3 extensions are active, and provide useful error. -- Adds notice about seed phrase backup. - -## 3.12.0 2017-10-25 - -- Add support for alternative ENS TLDs (Ethereum Name Service Top-Level Domains). -- Lower minimum gas price to 0.1 GWEI. -- Remove web3 injection message from production (thanks to @ChainsawBaby) -- Add additional debugging info to our state logs, specifically OS version and browser version. - -## 3.11.2 2017-10-21 - -- Fix bug where reject button would sometimes not work. -- Fixed bug where sometimes MetaMask's connection to a page would be unreliable. - -## 3.11.1 2017-10-20 - -- Fix bug where log filters were not populated correctly -- Fix bug where web3 API was sometimes injected after the page loaded. -- Fix bug where first account was sometimes not selected correctly after creating or restoring a vault. -- Fix bug where imported accounts could not use new eth_signTypedData method. - -## 3.11.0 2017-10-11 - -- Add support for new eth_signTypedData method per EIP 712. -- Fix bug where some transactions would be shown as pending forever, even after successfully mined. -- Fix bug where a transaction might be shown as pending forever if another tx with the same nonce was mined. -- Fix link to support article on token addresses. - -## 3.10.9 2017-10-5 - -- Only rebrodcast transactions for a day not a days worth of blocks -- Remove Slack link from info page, since it is a big phishing target. -- Stop computing balance based on pending transactions, to avoid edge case where users are unable to send transactions. - -## 3.10.8 2017-9-28 - -- Fixed usage of new currency fetching API. - -## 3.10.7 2017-9-28 - -- Fixed bug where sometimes the current account was not correctly set and exposed to web apps. -- Added AUD, HKD, SGD, IDR, PHP to currency conversion list - -## 3.10.6 2017-9-27 - -- Fix bug where newly created accounts were not selected. -- Fix bug where selected account was not persisted between lockings. - -## 3.10.5 2017-9-27 - -- Fix block gas limit estimation. - -## 3.10.4 2017-9-27 - -- Fix bug that could mis-render token balances when very small. (Not actually included in 3.9.9) -- Fix memory leak warning. -- Fix bug where new event filters would not include historical events. - -## 3.10.3 2017-9-21 - -- Fix bug where metamask-dapp connections are lost on rpc error -- Fix bug that would sometimes display transactions as failed that could be successfully mined. - -## 3.10.2 2017-9-18 - -rollback to 3.10.0 due to bug - -## 3.10.1 2017-9-18 - -- Add ability to export private keys as a file. -- Add ability to export seed words as a file. -- Changed state logs to a file download than a clipboard copy. -- Add specific error for failed recipient address checksum. -- Fixed a long standing memory leak associated with filters installed by dapps -- Fix link to support center. -- Fixed tooltip icon locations to avoid overflow. -- Warn users when a dapp proposes a high gas limit (90% of blockGasLimit or higher -- Sort currencies by currency name (thanks to strelok1: https://github.com/strelok1). - -## 3.10.0 2017-9-11 - -- Readded loose keyring label back into the account list. -- Remove cryptonator from chrome permissions. -- Add info on token contract addresses. -- Add validation preventing users from inputting their own addresses as token tracking addresses. -- Added button to reject all transactions (thanks to davidp94! https://github.com/davidp94) - - -## 3.9.13 2017-9-8 - -- Changed the way we initialize the inpage provider to fix a bug affecting some developers. - -## 3.9.12 2017-9-6 - -- Fix bug that prevented Web3 1.0 compatibility -- Make eth_sign deprecation warning less noisy -- Add useful link to eth_sign deprecation warning. -- Fix bug with network version serialization over synchronous RPC -- Add MetaMask version to state logs. -- Add the total amount of tokens when multiple tokens are added under the token list -- Use HTTPS links for Etherscan. -- Update Support center link to new one with HTTPS. -- Make web3 deprecation notice more useful by linking to a descriptive article. - -## 3.9.11 2017-8-24 - -- Fix nonce calculation bug that would sometimes generate very wrong nonces. -- Give up resubmitting a transaction after 3500 blocks. - -## 3.9.10 2017-8-23 - -- Improve nonce calculation, to prevent bug where people are unable to send transactions reliably. -- Remove link to eth-tx-viz from identicons in tx history. - -## 3.9.9 2017-8-18 - -- Fix bug where some transaction submission errors would show an empty screen. -- Fix bug that could mis-render token balances when very small. -- Fix formatting of eth_sign "Sign Message" view. -- Add deprecation warning to eth_sign "Sign Message" view. - -## 3.9.8 2017-8-16 - -- Reenable token list. -- Remove default tokens. - -## 3.9.7 2017-8-15 - -- hotfix - disable token list -- Added a deprecation warning for web3 https://github.com/ethereum/mist/releases/tag/v0.9.0 - -## 3.9.6 2017-8-09 - -- Replace account screen with an account drop-down menu. -- Replace account buttons with a new account-specific drop-down menu. - -## 3.9.5 2017-8-04 - -- Improved phishing detection configuration update rate - -## 3.9.4 2017-8-03 - -- Fixed bug that prevented transactions from being rejected. - -## 3.9.3 2017-8-03 - -- Add support for EGO ujo token -- Continuously update blacklist for known phishing sites in background. -- Automatically detect suspicious URLs too similar to common phishing targets, and blacklist them. - -## 3.9.2 2017-7-26 - -- Fix bugs that could sometimes result in failed transactions after switching networks. -- Include stack traces in txMeta's to better understand the life cycle of transactions -- Enhance blacklister functionality to include levenshtein logic. (credit to @sogoiii and @409H for their help!) - -## 3.9.1 2017-7-19 - -- No longer automatically request 1 ropsten ether for the first account in a new vault. -- Now redirects from known malicious sites faster. -- Added a link to our new support page to the help screen. -- Fixed bug where a new transaction would be shown over the current transaction, creating a possible timing attack against user confirmation. -- Fixed bug in nonce tracker where an incorrect nonce would be calculated. -- Lowered minimum gas price to 1 Gwei. - -## 3.9.0 2017-7-12 - -- Now detects and blocks known phishing sites. - -## 3.8.6 2017-7-11 - -- Make transaction resubmission more resilient. -- No longer validate nonce client-side in retry loop. -- Fix bug where insufficient balance error was sometimes shown on successful transactions. - -## 3.8.5 2017-7-7 - -- Fix transaction resubmit logic to fail slightly less eagerly. - -## 3.8.4 2017-7-7 - -- Improve transaction resubmit logic to fail more eagerly when a user would expect it to. - -## 3.8.3 2017-7-6 - -- Re-enable default token list. -- Add origin header to dapp-bound requests to allow providers to throttle sites. -- Fix bug that could sometimes resubmit a transaction that had been stalled due to low balance after balance was restored. - -## 3.8.2 2017-7-3 - -- No longer show network loading indication on config screen, to allow selecting custom RPCs. -- Visually indicate that network spinner is a menu. -- Indicate what network is being searched for when disconnected. - -## 3.8.1 2017-6-30 - -- Temporarily disabled loading popular tokens by default to improve performance. -- Remove SEND token button until a better token sending form can be built, due to some precision issues. -- Fix precision bug in token balances. -- Cache token symbol and precisions to reduce network load. -- Transpile some newer JavaScript, restores compatibility with some older browsers. - -## 3.8.0 2017-6-28 - -- No longer stop rebroadcasting transactions -- Add list of popular tokens held to the account detail view. -- Add ability to add Tokens to token list. -- Add a warning to JSON file import. -- Add "send" link to token list, which goes to TokenFactory. -- Fix bug where slowly mined txs would sometimes be incorrectly marked as failed. -- Fix bug where badge count did not reflect personal_sign pending messages. -- Seed word confirmation wording is now scarier. -- Fix error for invalid seed words. -- Prevent users from submitting two duplicate transactions by disabling submit. -- Allow Dapps to specify gas price as hex string. -- Add button for copying state logs to clipboard. - -## 3.7.8 2017-6-12 - -- Add an `ethereum:` prefix to the QR code address -- The default network on installation is now MainNet -- Fix currency API URL from cryptonator. -- Update gasLimit params with every new block seen. -- Fix ENS resolver symbol UI. - -## 3.7.7 2017-6-8 - -- Fix bug where MetaMask would show old data after computer being asleep or disconnected from the internet. - -## 3.7.6 2017-6-5 - -- Fix bug that prevented publishing contracts. - -## 3.7.5 2017-6-5 - -- Prevent users from sending to the `0x0` address. -- Provide useful errors when entering bad characters in ENS name. -- Add ability to copy addresses from transaction confirmation view. - -## 3.7.4 2017-6-2 - -- Fix bug with inflight cache that caused some block lookups to return bad values (affected OasisDex). -- Fixed bug with gas limit calculation that would sometimes create unsubmittable gas limits. - -## 3.7.3 2017-6-1 - -- Rebuilt to fix cache clearing bug. - -## 3.7.2 2017-5-31 - -- Now when switching networks sites that use web3 will reload -- Now when switching networks the extension does not restart -- Cleanup decimal bugs in our gas inputs. -- Fix bug where submit button was enabled for invalid gas inputs. -- Now enforce 95% of block's gasLimit to protect users. -- Removing provider-engine from the inpage provider. This fixes some error handling inconsistencies introduced in 3.7.0. -- Added "inflight cache", which prevents identical requests from clogging up the network, dramatically improving ENS performance. -- Fixed bug where filter subscriptions would sometimes fail to unsubscribe. -- Some contracts will now display logos instead of jazzicons. -- Some contracts will now have names displayed in the confirmation view. - -## 3.7.0 2017-5-23 - -- Add Transaction Number (nonce) to transaction list. -- Label the pending tx icon with a tooltip. -- Fix bug where website filters would pile up and not deallocate when leaving a site. -- Continually resubmit pending txs for a period of time to ensure successful broadcast. -- ENS names will no longer resolve to their owner if no resolver is set. Resolvers must be explicitly set and configured. - -## 3.6.5 2017-5-17 - -- Fix bug where edited gas parameters would not take effect. -- Trim currency list. -- Enable decimals in our gas prices. -- Fix reset button. -- Fix event filter bug introduced by newer versions of Geth. -- Fix bug where decimals in gas inputs could result in strange values. - -## 3.6.4 2017-5-8 - -- Fix main-net ENS resolution. - -## 3.6.3 2017-5-8 - -- Fix bug that could stop newer versions of Geth from working with MetaMask. - -## 3.6.2 2017-5-8 - -- Input gas price in Gwei. -- Enforce Safe Gas Minimum recommended by EthGasStation. -- Fix bug where block-tracker could stop polling for new blocks. -- Reduce UI size by removing internal web3. -- Fix bug where gas parameters would not properly update on adjustment. - -## 3.6.1 2017-4-30 - -- Made fox less nosy. -- Fix bug where error was reported in debugger console when Chrome opened a new window. - -## 3.6.0 2017-4-26 - -- Add Rinkeby Test Network to our network list. - -## 3.5.4 2017-4-25 - -- Fix occasional nonce tracking issue. -- Fix bug where some events would not be emitted by web3. -- Fix bug where an error would be thrown when composing signatures for networks with large ID values. - -## 3.5.3 2017-4-24 - -- Popup new transactions in Firefox. -- Fix transition issue from account detail screen. -- Revise buy screen for more modularity. -- Fixed some other small bugs. - -## 3.5.2 2017-3-28 - -- Fix bug where gas estimate totals were sometimes wrong. -- Add link to Kovan Test Faucet instructions on buy view. -- Inject web3 into loaded iFrames. - -## 3.5.1 2017-3-27 - -- Fix edge case where users were unable to enable the notice button if notices were short enough to not require a scrollbar. - -## 3.5.0 2017-3-27 - -- Add better error messages for when a transaction fails on approval -- Allow sending to ENS names in send form on Ropsten. -- Added an address book functionality that remembers the last 15 unique addresses sent to. -- Can now change network to custom RPC URL from lock screen. -- Removed support for old, lightwallet based vault. Users who have not opened app in over a month will need to recover with their seed phrase. This will allow Firefox support sooner. -- Fixed bug where spinner wouldn't disappear on incorrect password submission on seed word reveal. -- Polish the private key UI. -- Enforce minimum values for gas price and gas limit. -- Fix bug where total gas was sometimes not live-updated. -- Fix bug where editing gas value could have some abrupt behaviors (#1233) -- Add Kovan as an option on our network list. -- Fixed bug where transactions on other networks would disappear when submitting a transaction on another network. - -## 3.4.0 2017-3-8 - -- Add two most recently used custom RPCs to network dropdown menu. -- Add personal_sign method support. -- Add personal_ecRecover method support. -- Add ability to customize gas and gasPrice on the transaction approval screen. -- Increase default gas buffer to 1.5x estimated gas value. - -## 3.3.0 2017-2-20 - -- net_version has been made synchronous. -- Test suite for migrations expanded. -- Network now changeable from lock screen. -- Improve test coverage of eth.sign behavior, including a code example of verifying a signature. - -## 3.2.2 2017-2-8 - -- Revert eth.sign behavior to the previous one with a big warning. We will be gradually implementing the new behavior over the coming time. https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign - -- Improve test coverage of eth.sign behavior, including a code example of verifying a signature. - -## 3.2.2 2017-2-8 - -- Revert eth.sign behavior to the previous one with a big warning. We will be gradually implementing the new behavior over the coming time. https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign - -## 3.2.1 2017-2-8 - -- Revert back to old style message signing. -- Fixed some build errors that were causing a variety of bugs. - -## 3.2.0 2017-2-8 - -- Add ability to import accounts in JSON file format (used by Mist, Geth, MyEtherWallet, and more!) -- Fix unapproved messages not being included in extension badge. -- Fix rendering bug where the Confirm transaction view would let you approve transactions when the account has insufficient balance. - -## 3.1.2 2017-1-24 - -- Fix "New Account" default keychain - -## 3.1.1 2017-1-20 - -- Fix HD wallet seed export - -## 3.1.0 2017-1-18 - -- Add ability to import accounts by private key. -- Fixed bug that returned the wrong transaction hashes on private networks that had not implemented EIP 155 replay protection (like TestRPC). - -## 3.0.1 2017-1-17 - -- Fixed bug that prevented eth.sign from working. -- Fix the displaying of transactions that have been submitted to the network in Transaction History - -## 3.0.0 2017-1-16 - -- Fix seed word account generation (https://medium.com/metamask/metamask-3-migration-guide-914b79533cdd#.t4i1qmmsz). -- Fix Bug where you see an empty transaction flash by on the confirm transaction view. -- Create visible difference in transaction history between an approved but not yet included in a block transaction and a transaction who has been confirmed. -- Fix memory leak in RPC Cache -- Override RPC commands eth_syncing and web3_clientVersion -- Remove certain non-essential permissions from certain builds. -- Add a check for when a tx is included in a block. -- Fix bug where browser-solidity would sometimes warn of a contract creation error when there was none. -- Minor modifications to network display. -- Network now displays properly for pending transactions. -- Implement replay attack protections allowed by EIP 155. -- Fix bug where sometimes loading account data would fail by querying a future block. - -## 2.14.1 2016-12-20 - -- Update Coinbase info. and increase the buy amount to $15 -- Fixed ropsten transaction links -- Temporarily disable extension reload detection causing infinite reload bug. -- Implemented basic checking for valid RPC URIs. - -## 2.14.0 2016-12-16 - -- Removed Morden testnet provider from provider menu. -- Add support for notices. -- Fix broken reload detection. -- Fix transaction forever cached-as-pending bug. - -## 2.13.11 2016-11-23 - -- Add support for synchronous RPC method "eth_uninstallFilter". -- Forgotten password prompts now send users directly to seed word restoration. - -## 2.13.10 2016-11-22 - -- Improve gas calculation logic. -- Default to Dapp-specified gas limits for transactions. -- Ropsten networks now properly point to the faucet when attempting to buy ether. -- Ropsten transactions now link to etherscan correctly. - -## 2.13.9 2016-11-21 - -- Add support for the new, default Ropsten Test Network. -- Fix bug that would cause MetaMask to occasionally lose its StreamProvider connection and drop requests. -- Fix bug that would cause the Custom RPC menu item to not appear when Localhost 8545 was selected. -- Point ropsten faucet button to actual faucet. -- Phase out ethereumjs-util from our encryptor module. - -## 2.13.8 2016-11-16 - -- Show a warning when a transaction fails during simulation. -- Fix bug where 20% of gas estimate was not being added properly. -- Render error messages in confirmation screen more gracefully. - -## 2.13.7 2016-11-8 - -- Fix bug where gas estimate would sometimes be very high. -- Increased our gas estimate from 100k gas to 20% of estimate. -- Fix GitHub link on info page to point at current repository. - -## 2.13.6 2016-10-26 - -- Add a check for improper Transaction data. -- Inject up to date version of web3.js -- Now nicknaming new accounts "Account #" instead of "Wallet #" for clarity. -- Fix bug where custom provider selection could show duplicate items. -- Fix bug where connecting to a local morden node would make two providers appear selected. -- Fix bug that was sometimes preventing transactions from being sent. - -## 2.13.5 2016-10-18 - -- Increase default max gas to `100000` over the RPC's `estimateGas` response. -- Fix bug where slow-loading dapps would sometimes trigger infinite reload loops. - -## 2.13.4 2016-10-17 - -- Add custom transaction fee field to send form. -- Fix bug where web3 was being injected into XML files. -- Fix bug where changing network would not reload current Dapps. - -## 2.13.3 2016-10-4 - -- Fix bug where log queries were filtered out. -- Decreased vault confirmation button font size to help some Linux users who could not see it. -- Made popup a little taller because it would sometimes cut off buttons. -- Fix bug where long account lists would get scrunched instead of scrolling. -- Add legal information to relevant pages. -- Rename UI elements to be more consistent with one another. -- Updated Terms of Service and Usage. -- Prompt users to re-agree to the Terms of Service when they are updated. - -## 2.13.2 2016-10-4 - -- Fix bug where chosen FIAT exchange rate does no persist when switching networks -- Fix additional parameters that made MetaMask sometimes receive errors from Parity. -- Fix bug where invalid transactions would still open the MetaMask popup. -- Removed hex prefix from private key export, to increase compatibility with Geth, MyEtherWallet, and Jaxx. - -## 2.13.1 2016-09-23 - -- Fix a bug with estimating gas on Parity -- Show loading indication when selecting ShapeShift as purchasing method. - -## 2.13.0 2016-09-18 - -- Add Parity compatibility, fixing Geth dependency issues. -- Add a link to the transaction in history that goes to https://metamask.github.io/eth-tx-viz -too help visualize transactions and to where they are going. -- Show "Buy Ether" button and warning on tx confirmation when sender balance is insufficient - -## 2.12.1 2016-09-14 - -- Fixed bug where if you send a transaction from within MetaMask extension the -popup notification opens up. -- Fixed bug where some tx errors would block subsequent txs until the plugin was refreshed. - -## 2.12.0 2016-09-14 - -- Add a QR button to the Account detail screen -- Fixed bug where opening MetaMask could close a non-metamask popup. -- Fixed memory leak that caused occasional crashes. - -## 2.11.1 2016-09-12 - -- Fix bug that prevented caches from being cleared in Opera. - -## 2.11.0 2016-09-12 - -- Fix bug where pending transactions from Test net (or other networks) show up In Main net. -- Add fiat conversion values to more views. -- On fresh install, open a new tab with the MetaMask Introduction video. Does not open on update. -- Block negative values from transactions. -- Fixed a memory leak. -- MetaMask logo now renders as super lightweight SVG, improving compatibility and performance. -- Now showing loading indication during vault unlocking, to clarify behavior for users who are experiencing slow unlocks. -- Now only initially creates one wallet when restoring a vault, to reduce some users' confusion. - -## 2.10.2 2016-09-02 - -- Fix bug where notification popup would not display. - -## 2.10.1 2016-09-02 - -- Fix bug where provider menu did not allow switching to custom network from a custom network. -- Sending a transaction from within MetaMask no longer triggers a popup. -- The ability to build without livereload features (such as for production) can be enabled with the gulp --disableLiveReload flag. -- Fix Ethereum JSON RPC Filters bug. - -## 2.10.0 2016-08-29 - -- Changed transaction approval from notifications system to popup system. -- Add a back button to locked screen to allow restoring vault from seed words when password is forgotten. -- Forms now retain their values even when closing the popup and reopening it. -- Fixed a spelling error in provider menu. - -## 2.9.2 2016-08-24 - -- Fixed shortcut bug from preventing installation. - -## 2.9.1 2016-08-24 - -- Added static image as fallback for when WebGL isn't supported. -- Transaction history now has a hard limit. -- Added info link on account screen that visits Etherscan. -- Fixed bug where a message signing request would be lost if the vault was locked. -- Added shortcut to open MetaMask (Ctrl+Alt+M or Cmd+Opt/Alt+M) -- Prevent API calls in tests. -- Fixed bug where sign message confirmation would sometimes render blank. - -## 2.9.0 2016-08-22 - -- Added ShapeShift to the transaction history -- Added affiliate key to Shapeshift requests -- Added feature to reflect current conversion rates of current vault balance. -- Modify balance display logic. - -## 2.8.0 2016-08-15 - -- Integrate ShapeShift -- Add a form for Coinbase to specify amount to buy -- Fix various typos. -- Make dapp-metamask connection more reliable -- Remove Ethereum Classic from provider menu. - -## 2.7.3 2016-07-29 - -- Fix bug where changing an account would not update in a live Dapp. - -## 2.7.2 2016-07-29 - -- Add Ethereum Classic to provider menu -- Fix bug where host store would fail to receive updates. - -## 2.7.1 2016-07-27 - -- Fix bug where web3 would sometimes not be injected in time for the application. -- Fixed bug where sometimes when opening the plugin, it would not fully open until closing and re-opening. -- Got most functionality working within Firefox (still working on review process before it can be available). -- Fixed menu dropdown bug introduced in Chrome 52. - -## 2.7.0 2016-07-21 - -- Added a Warning screen about storing ETH -- Add buy Button! -- MetaMask now throws descriptive errors when apps try to use synchronous web3 methods. -- Removed firefox-specific line in manifest. - -## 2.6.2 2016-07-20 - -- Fixed bug that would prevent the plugin from reopening on the first try after receiving a new transaction while locked. -- Fixed bug that would render 0 ETH as a non-exact amount. - -## 2.6.1 2016-07-13 - -- Fix tool tips on Eth balance to show the 6 decimals -- Fix rendering of recipient SVG in tx approval notification. -- New vaults now generate only one wallet instead of three. -- Bumped version of web3 provider engine. -- Fixed bug where some lowercase or uppercase addresses were not being recognized as valid. -- Fixed bug where gas cost was misestimated on the tx confirmation view. - -## 2.6.0 2016-07-11 - -- Fix formatting of ETH balance -- Fix formatting of account details. -- Use web3 minified dist for faster inject times -- Fix issue where dropdowns were not in front of icons. -- Update transaction approval styles. -- Align failed and successful transaction history text. -- Fix issue where large domain names and large transaction values would misalign the transaction history. -- Abbreviate ether balances on transaction details to maintain formatting. -- General code cleanup. - -## 2.5.0 2016-06-29 - -- Implement new account design. -- Added a network indicator mark in dropdown menu -- Added network name next to network indicator -- Add copy transaction hash button to completed transaction list items. -- Unify wording for transaction approve/reject options on notifications and the extension. -- Fix bug where confirmation view would be shown twice. - -## 2.4.5 2016-06-29 - -- Fixed bug where MetaMask interfered with PDF loading. -- Moved switch account icon into menu bar. -- Changed status shapes to be a yellow warning sign for failure and ellipsis for pending transactions. -- Now enforce 20 character limit on wallet names. -- Wallet titles are now properly truncated in transaction confirmation. -- Fix formatting on terms & conditions page. -- Now enforce 30 character limit on wallet names. -- Fix out-of-place positioning of pending transaction badges on wallet list. -- Change network status icons to reflect current design. - -## 2.4.4 2016-06-23 - -- Update web3-stream-provider for batch payload bug fix - -## 2.4.3 2016-06-23 - -- Remove redundant network option buttons from settings page -- Switch out font family Transat for Montserrat - -## 2.4.2 2016-06-22 - -- Change out export icon for key. -- Unify copy to clipboard icon -- Fixed eth.sign behavior. -- Fix behavior of batched outbound transactions. - -## 2.4.0 2016-06-20 - -- Clean up UI. -- Remove nonfunctional QR code button. -- Make network loading indicator clickable to select accessible network. -- Show more characters of addresses when space permits. -- Fixed bug when signing messages under 64 hex characters long. -- Add disclaimer view with placeholder text for first time users. - -## 2.3.1 2016-06-09 - -- Style up the info page -- Cache identicon images to optimize for long lists of transactions. -- Fix out of gas errors - -## 2.3.0 2016-06-06 - -- Show network status in title bar -- Added seed word recovery to config screen. -- Clicking network status indicator now reveals a provider menu. - -## 2.2.0 2016-06-02 - -- Redesigned init, vault create, vault restore and seed confirmation screens. -- Added pending transactions to transaction list on account screen. -- Clicking a pending transaction takes you back to the transaction approval screen. -- Update provider-engine to fix intermittent out of gas errors. - -## 2.1.0 2016-05-26 - -- Added copy address button to account list. -- Fixed back button on confirm transaction screen. -- Add indication of pending transactions to account list screen. -- Fixed bug where error warning was sometimes not cleared on view transition. -- Updated eth-lightwallet to fix a critical security issue. - -## 2.0.0 2016-05-23 - -- UI Overhaul per Vlad Todirut's designs. -- Replaced identicons with jazzicons. -- Fixed glitchy transitions. -- Added support for capitalization-based address checksums. -- Send value is no longer limited by javascript number precision, and is always in ETH. -- Added ability to generate new accounts. -- Added ability to locally nickname accounts. - -## 1.8.4 2016-05-13 - -- Point rpc servers to https endpoints. - -## 1.8.3 2016-05-12 - -- Bumped web3 to 0.6.0 -- Really fixed `eth_syncing` method response. - -## 1.8.2 2016-05-11 - -- Fixed bug where send view would not load correctly the first time it was visited per account. -- Migrated all users to new scalable backend. -- Fixed `eth_syncing` method response. - -## 1.8.1 2016-05-10 - -- Initial usage of scalable blockchain backend. -- Made official providers more easily configurable for us internally. - -## 1.8.0 2016-05-10 - -- Add support for calls to `eth.sign`. -- Moved account exporting within subview of the account detail view. -- Added buttons to the account export process. -- Improved visual appearance of account detail transition where button heights would change. -- Restored back button to account detail view. -- Show transaction list always, never collapsed. -- Changing provider now reloads current Dapps -- Improved appearance of transaction list in account detail view. - -## 1.7.0 2016-04-29 - -- Account detail view is now the primary view. -- The account detail view now has a "Change acct" button which shows the account list. -- Clicking accounts in the account list now both selects that account and displays that account's detail view. -- Selected account is now persisted between sessions, so the current account stays selected. -- Account icons are now "identicons" (deterministically generated from the address). -- Fixed link to Slack channel. -- Added a context guard for "define" to avoid UMD's exporting themselves to the wrong module system, fixing interference with some websites. -- Transaction list now only shows transactions for the current account. -- Transaction list now only shows transactions for the current network (mainnet, testnet, testrpc). -- Fixed transaction links to etherscan blockchain explorer. -- Fixed some UI transitions that had weird behavior. - -## 1.6.0 2016-04-22 - -- Pending transactions are now persisted to localStorage and resume even after browser is closed. -- Completed transactions are now persisted and can be displayed via UI. -- Added transaction list to account detail view. -- Fix bug on config screen where current RPC address was always displayed wrong. -- Fixed bug where entering a decimal value when sending a transaction would result in sending the wrong amount. -- Add save button to custom RPC input field. -- Add quick-select button for RPC on `localhost:8545`. -- Improve config view styling. -- Users have been migrated from old test-net RPC to a newer test-net RPC. - -## 1.5.1 2016-04-15 - -- Corrected text above account list. Selected account is visible to all sites, not just the current domain. -- Merged the UI codebase into the main plugin codebase for simpler maintenance. -- Fix Ether display rounding error. Now rendering to four decimal points. -- Fix some inpage synchronous methods -- Change account rendering to show four decimals and a leading zero. - -## 1.5.0 2016-04-13 - -- Added ability to send ether. -- Fixed bugs related to using Javascript numbers, which lacked appropriate precision. -- Replaced Etherscan main-net provider with our own production RPC. - -## 1.4.0 2016-04-08 - -- Removed extra entropy text field for simplified vault creation. -- Now supports exporting an account's private key. -- Unified button and input styles across the app. -- Removed some non-working placeholder UI until it works. -- Fix popup's web3 stream provider -- Temporarily deactivated fauceting indication because it would activate when restoring an empty account. - -## 1.3.2 2016-04-04 - - - When unlocking, first account is auto-selected. - - When creating a first vault on the test-net, the first account is auto-funded. - - Fixed some styling issues. - -## 1.0.1-1.3.1 - -Many changes not logged. Hopefully beginning to log consistently now! - -## 1.0.0 - -Made seed word restoring BIP44 compatible. - -## 0.14.0 - -Added the ability to restore accounts from seed words. diff --git a/test/unit/development/sample-manifest.json b/test/unit/development/sample-manifest.json deleted file mode 100644 index 2b3acf1b5..000000000 --- a/test/unit/development/sample-manifest.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "name": "MetaMask", - "short_name": "Metamask", - "version": "4.1.3", - "manifest_version": 2, - "author": "https://metamask.io", - "description": "Ethereum Browser Extension", - "commands": { - "_execute_browser_action": { - "suggested_key": { - "windows": "Alt+Shift+M", - "mac": "Alt+Shift+M", - "chromeos": "Alt+Shift+M", - "linux": "Alt+Shift+M" - } - } - }, - "icons": { - "16": "images/icon-16.png", - "128": "images/icon-128.png" - }, - "applications": { - "gecko": { - "id": "webextension@metamask.io" - } - }, - "default_locale": "en", - "background": { - "scripts": [ - "scripts/chromereload.js", - "scripts/background.js" - ], - "persistent": true - }, - "browser_action": { - "default_icon": { - "19": "images/icon-19.png", - "38": "images/icon-38.png" - }, - "default_title": "MetaMask", - "default_popup": "popup.html" - }, - "content_scripts": [ - { - "matches": [ - "file://*/*", - "http://*/*", - "https://*/*" - ], - "js": [ - "scripts/contentscript.js" - ], - "run_at": "document_start", - "all_frames": true - } - ], - "permissions": [ - "storage", - "clipboardWrite", - "http://localhost:8545/", - "https://*.infura.io/" - ], - "web_accessible_resources": [ - "scripts/inpage.js" - ], - "externally_connectable": { - "matches": [ - "https://metamask.io/*" - ] - } -} diff --git a/test/unit/development/version–bump-test.js b/test/unit/development/version–bump-test.js deleted file mode 100644 index fc800c256..000000000 --- a/test/unit/development/version–bump-test.js +++ /dev/null @@ -1,46 +0,0 @@ -import assert from 'assert' -import versionBump from '../../../development/version-bump' -import promisify from 'pify' -import fs from 'fs' - -const readFile = promisify(fs.readFile) -import path from 'path' - -const changelogPath = path.join(__dirname, 'sample-changelog.md') -import manifest from './sample-manifest.json' - -let changelog - - -describe('version bumper', function () { - - beforeEach(async () => { - // load changelog. Mock version is 4.1.3 - const changeBuffer = await readFile(changelogPath) - changelog = changeBuffer.toString() - }) - - it('returns a properly bumped major version', async function () { - const result = await versionBump('major', changelog, manifest) - const expected = '5.0.0' - assert.equal(result.version, expected, 'major bumps correctly') - assert.equal(result.manifest.version, expected, 'major bumps correctly') - assert.ok(result.changelog.includes(expected)) - }) - - it('returns a properly bumped minor version', async function () { - const result = await versionBump('minor', changelog, manifest) - const expected = '4.2.0' - assert.equal(result.version, expected, 'minor bumps correctly') - assert.equal(result.manifest.version, expected, 'minor bumps correctly') - assert.ok(result.changelog.includes(expected)) - }) - - it('returns a properly bumped patch version', async function () { - const result = await versionBump('patch', changelog, manifest) - const expected = '4.1.4' - assert.equal(result.version, expected, 'patch bumps correctly') - assert.equal(result.manifest.version, expected, 'patch bumps correctly') - assert.ok(result.changelog.includes(expected)) - }) -}) From c0d6121cd9c037cf46bbd3af85477172507614da Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Fri, 7 Feb 2020 13:19:32 -0330 Subject: [PATCH 253/689] Browser tests (#8010) --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 24d7b0c98..ef903aedd 100644 --- a/README.md +++ b/README.md @@ -58,10 +58,6 @@ yarn start yarn dist ``` -#### Writing Browser Tests - -To write tests that will be run in the browser using QUnit, add your test files to `test/integration/lib`. - ## Other Docs - [How to add custom build to Chrome](./docs/add-to-chrome.md) From 5b28fb3a1c2c1da9b15cc45eba937beb8a25ffd3 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Sat, 8 Feb 2020 16:26:33 -0330 Subject: [PATCH 254/689] Enable Storybook deploy on CI (#8009) --- .circleci/config.yml | 56 +++++++++++++++++++++++++----------- .gitignore | 1 + .storybook/webpack.config.js | 2 +- package.json | 2 +- 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index bc1cbd820..eb816f456 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,6 +16,9 @@ workflows: - prep-build-test: requires: - prep-deps + - prep-build-storybook: + requires: + - prep-deps - prep-scss: requires: - prep-deps @@ -79,12 +82,12 @@ workflows: - prep-deps - prep-build - all-tests-pass - # - job-publish-storybook: - # filters: - # branches: - # only: develop - # requires: - # - prep-deps + - job-publish-storybook: + filters: + branches: + only: develop + requires: + - prep-build-storybook - coveralls-upload: requires: - test-unit @@ -158,6 +161,21 @@ jobs: paths: - dist-test + prep-build-storybook: + docker: + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 + steps: + - checkout + - attach_workspace: + at: . + - run: + name: Build Storybook + command: yarn storybook:build + - persist_to_workspace: + root: . + paths: + - .out + prep-scss: docker: - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 @@ -330,16 +348,22 @@ jobs: - run: name: Create GitHub Pull Request to sync master with develop command: .circleci/scripts/release-create-master-pr - # job-publish-storybook: - # docker: - # - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 - # steps: - # - checkout - # - attach_workspace: - # at: . - # - run: - # name: storybook:deploy - # command: yarn storybook:deploy + + job-publish-storybook: + docker: + - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 + steps: + - add_ssh_keys: + fingerprints: + - "5e:a3:2d:35:b6:25:b5:87:b1:41:11:0d:77:50:96:73" + - checkout + - attach_workspace: + at: . + - run: + name: storybook:deploy + command: | + git remote add storybook git@github.com:MetaMask/metamask-storybook.git + yarn storybook:deploy test-unit: docker: diff --git a/.gitignore b/.gitignore index b99c21fd3..b9302b399 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ temp .DS_Store app/.DS_Store +.out/ coverage/ dist builds/ diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js index bd66954f3..efb85d232 100644 --- a/.storybook/webpack.config.js +++ b/.storybook/webpack.config.js @@ -31,7 +31,7 @@ module.exports = { }, resolve: { alias: { - './fonts/Font_Awesome': path.resolve(__dirname, '../fonts/Font_Awesome'), + './fonts/Font_Awesome': path.resolve(__dirname, '../app/fonts/Font_Awesome'), }, }, } diff --git a/package.json b/package.json index 53357a0db..7c4ae1788 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "announce": "node development/announcer.js", "storybook": "start-storybook -p 6006 -c .storybook", "storybook:build": "build-storybook -c .storybook -o .out", - "storybook:deploy": "storybook-to-ghpages", + "storybook:deploy": "storybook-to-ghpages --existing-output-dir .out --remote storybook --branch master", "update-changelog": "./development/auto-changelog.sh", "generate:migration": "./development/generate-migration.sh" }, From 1a1e0b43d0048892cd6b31161a0ea5ef6ef789c6 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Sun, 9 Feb 2020 16:12:57 -0330 Subject: [PATCH 255/689] Remove unused test:single script (#8025) --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 7c4ae1788..7e48f4147 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,6 @@ "sendwithprivatedapp": "node development/static-server.js test/e2e/send-eth-with-private-key-test --port 8080", "test:unit": "mocha --exit --require test/env.js --require test/setup.js --recursive \"test/unit/**/*.js\" \"ui/app/**/*.test.js\"", "test:unit:global": "mocha --exit --require test/env.js --require test/setup.js --recursive mocha test/unit-global/*", - "test:single": "mocha --require test/env.js --require test/helper.js", "test:integration": "yarn test:integration:build && yarn test:flat", "test:integration:build": "gulp build:scss", "test:e2e:chrome": "SELENIUM_BROWSER=chrome test/e2e/run-all.sh", From 8c81f9d5307ad8052cdb3520e38f6a29ba8ff14d Mon Sep 17 00:00:00 2001 From: ricky Date: Mon, 10 Feb 2020 12:42:59 -0500 Subject: [PATCH 256/689] Ensure we pass history to UnlockPage component (#8017) * Add .isRequired to history propType definition * Ensure we pass history down to the component --- ui/app/pages/unlock-page/unlock-page.component.js | 2 +- ui/app/pages/unlock-page/unlock-page.container.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/app/pages/unlock-page/unlock-page.component.js b/ui/app/pages/unlock-page/unlock-page.component.js index 2b6916bd7..1fc33c360 100644 --- a/ui/app/pages/unlock-page/unlock-page.component.js +++ b/ui/app/pages/unlock-page/unlock-page.component.js @@ -14,7 +14,7 @@ export default class UnlockPage extends Component { } static propTypes = { - history: PropTypes.object, + history: PropTypes.object.isRequired, isUnlocked: PropTypes.bool, onImport: PropTypes.func, onRestore: PropTypes.func, diff --git a/ui/app/pages/unlock-page/unlock-page.container.js b/ui/app/pages/unlock-page/unlock-page.container.js index 2f4687f82..88420c5a5 100644 --- a/ui/app/pages/unlock-page/unlock-page.container.js +++ b/ui/app/pages/unlock-page/unlock-page.container.js @@ -55,6 +55,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { onImport, onRestore: onImport, onSubmit: ownPropsSubmit || onSubmit, + history, } } From 1ae09338975a8d89f1d5e2e675480cf0d8d764f3 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 10 Feb 2020 14:17:31 -0330 Subject: [PATCH 257/689] Use image hash for ShellCheck Docker image (#8022) --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index eb816f456..530f5bd62 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -211,7 +211,7 @@ jobs: test-lint-shellcheck: docker: - - image: koalaman/shellcheck-alpine:stable + - image: koalaman/shellcheck-alpine@sha256:169a51b086af0ab181e32801c15deb78944bb433d4f2c0a21cc30d4e60547065 steps: - checkout - run: apk add --no-cache bash jq yarn From 3bbbe133111053467843bab2f78319fa7bb181d4 Mon Sep 17 00:00:00 2001 From: ryanml Date: Tue, 11 Feb 2020 07:40:15 -0800 Subject: [PATCH 258/689] Use contact name instead of address during send flow (#7971) --- .../transaction-list-item-details.component.test.js | 8 ++++++++ .../transaction-list-item-details.component.js | 6 ++++++ .../transaction-list-item-details.container.js | 13 ++++++++++++- .../sender-to-recipient.component.js | 2 +- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js b/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js index 2111c890d..abba1b08c 100644 --- a/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js +++ b/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js @@ -35,6 +35,8 @@ describe('TransactionListItemDetails Component', () => { senderAddress="0x2" tryReverseResolveAddress={() => {}} transactionGroup={transactionGroup} + senderNickname="sender-nickname" + recipientNickname="recipient-nickname" />, { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } ) @@ -77,6 +79,8 @@ describe('TransactionListItemDetails Component', () => { tryReverseResolveAddress={() => {}} transactionGroup={transactionGroup} showSpeedUp + senderNickname="sender-nickname" + recipientNickname="recipient-nickname" />, { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } ) @@ -112,6 +116,8 @@ describe('TransactionListItemDetails Component', () => { senderAddress="0x2" tryReverseResolveAddress={() => {}} transactionGroup={transactionGroup} + senderNickname="sender-nickname" + recipientNickname="recipient-nickname" />, { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } ) @@ -150,6 +156,8 @@ describe('TransactionListItemDetails Component', () => { senderAddress="0x2" tryReverseResolveAddress={() => {}} transactionGroup={transactionGroup} + senderNickname="sender-nickname" + recipientNickname="recipient-nickname" />, { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } } ) diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js index 29634e023..d193f9fb9 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js +++ b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js @@ -35,6 +35,8 @@ export default class TransactionListItemDetails extends PureComponent { rpcPrefs: PropTypes.object, senderAddress: PropTypes.string.isRequired, tryReverseResolveAddress: PropTypes.func.isRequired, + senderNickname: PropTypes.string.isRequired, + recipientNickname: PropTypes.string.isRequired, } state = { @@ -146,6 +148,8 @@ export default class TransactionListItemDetails extends PureComponent { rpcPrefs: { blockExplorerUrl } = {}, senderAddress, isEarliestNonce, + senderNickname, + recipientNickname, } = this.props const { primaryTransaction: transaction } = transactionGroup const { hash } = transaction @@ -212,6 +216,8 @@ export default class TransactionListItemDetails extends PureComponent { addressOnly recipientEns={recipientEns} recipientAddress={recipientAddress} + recipientNickname={recipientNickname} + senderName={senderNickname} senderAddress={senderAddress} onRecipientClick={() => { this.context.metricsEvent({ diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js index 50f93f497..2a7cea51f 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js +++ b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js @@ -2,18 +2,29 @@ import { connect } from 'react-redux' import TransactionListItemDetails from './transaction-list-item-details.component' import { checksumAddress } from '../../../helpers/utils/util' import { tryReverseResolveAddress } from '../../../store/actions' +import { getAddressBook } from '../../../selectors/selectors' const mapStateToProps = (state, ownProps) => { const { metamask } = state const { ensResolutionsByAddress, } = metamask - const { recipientAddress } = ownProps + const { recipientAddress, senderAddress } = ownProps const address = checksumAddress(recipientAddress) const recipientEns = ensResolutionsByAddress[address] || '' + const addressBook = getAddressBook(state) + + const getNickName = (address) => { + const entry = addressBook.find((contact) => { + return address.toLowerCase() === contact.address.toLowerCase() + }) + return entry && entry.name || '' + } return { recipientEns, + senderNickname: getNickName(senderAddress), + recipientNickname: getNickName(recipientAddress), } } diff --git a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js index a7597e36b..2780456d6 100644 --- a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js +++ b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js @@ -78,7 +78,7 @@ export default class SenderToRecipient extends PureComponent {
    { addressOnly - ? {`${t('from')}: ${checksummedSenderAddress}`} + ? {`${t('from')}: ${senderName || checksummedSenderAddress}`} : senderName }
    From 4f3fc95d5062abce22d3c9cac5587269f4c98c91 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 11 Feb 2020 13:21:13 -0330 Subject: [PATCH 259/689] Update ESLint rules for test suite (#8023) * Use @metamask/eslint-config@1.1.0 * Use eslint-plugin-mocha@6.2.2 * Mark root ESLint config as root * Update Mocha ESLint rules with shared ESLint config --- .eslintrc.js | 6 +- package.json | 4 +- test/e2e/.eslintrc.js | 5 + test/e2e/address-book.spec.js | 28 +- test/e2e/ethereum-on.spec.js | 28 +- test/e2e/from-import-ui.spec.js | 66 +- test/e2e/incremental-security.spec.js | 40 +- test/e2e/metamask-responsive-ui.spec.js | 32 +- test/e2e/metamask-ui.spec.js | 150 ++--- test/e2e/permissions.spec.js | 26 +- test/e2e/send-edit.spec.js | 14 +- test/e2e/signature-request.spec.js | 12 +- test/e2e/tests/simple-send.spec.js | 2 +- test/e2e/threebox.spec.js | 56 +- test/e2e/web3.spec.js | 30 +- test/unit-global/frozenPromise.js | 12 +- test/unit/actions/tx_test.js | 5 +- test/unit/app/ComposableObservableStore.js | 10 +- .../app/account-import-strategies.spec.js | 16 +- test/unit/app/cleanErrorStack.spec.js | 12 +- .../controllers/balance-controller.spec.js | 4 +- .../app/controllers/cached-balances-test.js | 16 +- .../app/controllers/detect-tokens-test.js | 22 +- .../app/controllers/ens-controller-test.js | 14 +- .../controllers/incoming-transactions-test.js | 76 +-- .../app/controllers/infura-controller-test.js | 21 +- .../controllers/metamask-controller-test.js | 90 +-- .../network/network-controller-test.js | 100 ++- .../network/pending-middleware-test.js | 136 ++-- .../preferences-controller-test.js | 12 +- .../app/controllers/token-rates-controller.js | 6 +- .../transactions/pending-tx-test.js | 31 +- .../recipient-blacklist-checker-test.js | 27 +- .../transactions/tx-controller-test.js | 62 +- .../transactions/tx-state-manager-test.js | 10 +- .../controllers/transactions/tx-utils-test.js | 8 +- test/unit/app/fetch-with-timeout.test.js | 8 +- test/unit/app/nodeify-test.js | 4 +- test/unit/app/pending-balance-test.js | 11 +- test/unit/app/typed-message-manager.spec.js | 6 +- test/unit/app/util-test.js | 128 ++-- test/unit/migrations/021-test.js | 4 +- test/unit/migrations/022-test.js | 4 +- test/unit/migrations/023-test.js | 8 +- test/unit/migrations/024-test.js | 6 +- test/unit/migrations/025-test.js | 6 +- test/unit/migrations/026-test.js | 6 +- test/unit/migrations/027-test.js | 6 +- test/unit/migrations/028-test.js | 6 +- test/unit/migrations/029-test.js | 4 +- test/unit/migrations/030-test.js | 4 +- test/unit/migrations/031-test.js | 6 +- test/unit/migrations/033-test.js | 4 +- test/unit/migrations/034-test.js | 14 +- test/unit/migrations/035-test.js | 10 +- test/unit/migrations/036-test.js | 14 +- test/unit/migrations/037-test.js | 8 +- test/unit/migrations/038-test.js | 8 +- test/unit/migrations/039-test.js | 30 +- test/unit/migrations/migrations-test.js | 4 +- test/unit/migrations/migrator-test.js | 73 ++- test/unit/migrations/template-test.js | 4 +- test/unit/ui/app/actions.spec.js | 393 +++++------ .../unit/ui/app/components/token-cell.spec.js | 12 +- test/unit/ui/app/reducers/app.spec.js | 79 ++- test/unit/ui/app/reducers/metamask.spec.js | 64 +- test/unit/ui/app/selectors.spec.js | 20 +- .../ui/etherscan-prefix-for-network.spec.js | 14 +- test/web3/web3.js | 4 +- .../account-menu/tests/account-menu.test.js | 54 +- .../app/app-header/tests/app-header.test.js | 24 +- .../confirm-detail-row.component.test.js | 52 +- .../app/dropdowns/tests/dropdown.test.js | 10 +- .../app/dropdowns/tests/menu.test.js | 56 +- .../tests/network-dropdown-icon.test.js | 11 +- .../dropdowns/tests/network-dropdown.test.js | 32 +- .../advanced-gas-input-component.test.js | 20 +- .../advanced-tab-content-component.test.js | 24 +- .../tests/basic-tab-content-component.test.js | 27 +- ...gas-modal-page-container-component.test.js | 40 +- ...gas-modal-page-container-container.test.js | 53 +- .../gas-price-button-group-component.test.js | 40 +- .../tests/gas-price-chart.component.test.js | 34 +- .../app/info-box/tests/info-box.test.js | 10 +- .../app/menu-bar/tests/menu-bar.test.js | 12 +- .../tests/modal-content.component.test.js | 8 +- .../app/modal/tests/modal.component.test.js | 14 +- ...ncel-transaction-gas-fee.component.test.js | 4 +- .../cancel-transaction.component.test.js | 6 +- .../tests/confirm-delete-network.test.js | 12 +- .../tests/confirm-remove-account.test.js | 12 +- .../tests/confirm-reset-account.test.js | 10 +- .../tests/metametrics-opt-in-modal.test.js | 10 +- .../tests/reject-transactions.test.js | 10 +- .../tests/account-details-modal.test.js | 12 +- .../tests/transaction-confirmed.test.js | 20 +- .../tests/selected-account-component.test.js | 4 +- .../sidebars/tests/sidebars-component.test.js | 30 +- .../tests/signature-request.test.js | 34 +- .../app/tests/signature-request.test.js | 10 +- .../components/app/tests/token-cell.spec.js | 12 +- .../transaction-action.component.test.js | 12 +- ...transaction-activity-log.component.test.js | 8 +- ...transaction-activity-log.container.test.js | 6 +- .../transaction-activity-log.util.test.js | 618 +++++++++--------- .../transaction-breakdown.component.test.js | 4 +- ...ransaction-breakdown-row.component.test.js | 6 +- ...action-list-item-details.component.test.js | 10 +- .../transaction-status.component.test.js | 6 +- .../token-view-balance.component.test.js | 8 +- ...erenced-currency-display.component.test.js | 8 +- ...erenced-currency-display.container.test.js | 12 +- ...eferenced-currency-input.component.test.js | 8 +- ...eferenced-currency-input.container.test.js | 6 +- ...-preferenced-token-input.component.test.js | 8 +- ...-preferenced-token-input.container.test.js | 6 +- .../components/ui/alert/tests/alert.test.js | 10 +- .../tests/breadcrumbs.component.test.js | 4 +- .../tests/button-group-component.test.js | 32 +- .../ui/card/tests/card.component.test.js | 4 +- .../tests/currency-display.component.test.js | 6 +- .../tests/currency-display.container.test.js | 10 +- .../tests/currency-input.component.test.js | 26 +- .../tests/currency-input.container.test.js | 12 +- .../tests/error-message.component.test.js | 6 +- .../tests/hex-to-decimal.component.test.js | 6 +- .../tests/identicon.component.test.js | 8 +- .../tests/metafox-logo.component.test.js | 6 +- .../page-container-footer.component.test.js | 28 +- .../page-container-header.component.test.js | 26 +- .../tests/token-input.component.test.js | 26 +- .../tests/token-input.container.test.js | 20 +- .../tests/unit-input.component.test.js | 24 +- .../confirm-transaction.duck.test.js | 80 +-- ui/app/ducks/gas/gas-duck.test.js | 108 +-- ui/app/ducks/send/send-duck.test.js | 30 +- .../tests/with-modal-props.test.js | 4 +- .../with-token-tracker.component.test.js | 8 +- ui/app/helpers/utils/common.util.test.js | 6 +- ui/app/helpers/utils/confirm-tx.util.test.js | 52 +- ui/app/helpers/utils/conversion-util.test.js | 10 +- ui/app/helpers/utils/fetch-with-cache.test.js | 22 +- .../helpers/utils/transactions.util.test.js | 12 +- ui/app/helpers/utils/util.test.js | 6 +- .../pages/add-token/tests/add-token.test.js | 44 +- ...confirm-transaction-base.component.test.js | 6 +- .../tests/create-account.test.js | 12 +- .../import-with-seed-phrase.component.test.js | 16 +- .../end-of-flow/tests/end-of-flow.test.js | 11 +- .../tests/first-time-flow-switch.test.js | 12 +- .../tests/metametrics-opt-in.test.js | 44 +- .../tests/reveal-seed-phrase.test.js | 8 +- .../confirm-seed-phrase-component.test.js | 12 +- .../select-action/tests/select-action.test.js | 10 +- .../welcome/tests/welcome.test.js | 8 +- .../pages/keychains/tests/reveal-seed.test.js | 23 +- ui/app/pages/lock/tests/lock.test.js | 6 +- .../tests/account-list-item-component.test.js | 67 +- .../tests/account-list-item-container.test.js | 12 +- .../tests/add-recipient-component.test.js | 32 +- .../tests/add-recipient-container.test.js | 25 +- .../tests/add-recipient-selectors.test.js | 16 +- .../tests/add-recipient-utils.test.js | 32 +- .../tests/amount-max-button-component.test.js | 16 +- .../tests/amount-max-button-container.test.js | 18 +- .../tests/amount-max-button-selectors.test.js | 6 +- .../tests/amount-max-button-utils.test.js | 8 +- .../tests/send-amount-row-component.test.js | 26 +- .../tests/send-amount-row-container.test.js | 22 +- .../tests/send-amount-row-selectors.test.js | 8 +- .../send-dropdown-list-component.test.js | 24 +- .../tests/send-from-row-component.test.js | 8 +- .../tests/send-from-row-container.test.js | 6 +- .../tests/gas-fee-display.component.test.js | 41 +- .../tests/send-gas-row-component.test.js | 56 +- .../tests/send-gas-row-container.test.js | 45 +- .../tests/send-gas-row-selectors.test.js | 16 +- .../send-row-error-message-component.test.js | 22 +- .../send-row-error-message-container.test.js | 6 +- .../tests/send-row-wrapper-component.test.js | 36 +- .../tests/send-content-component.test.js | 18 +- .../tests/send-footer-component.test.js | 38 +- .../tests/send-footer-container.test.js | 24 +- .../tests/send-footer-selectors.test.js | 8 +- .../tests/send-footer-utils.test.js | 28 +- .../tests/send-header-component.test.js | 16 +- .../tests/send-header-container.test.js | 26 +- .../tests/send-header-selectors.test.js | 12 +- .../pages/send/tests/send-component.test.js | 76 +-- .../pages/send/tests/send-container.test.js | 24 +- .../pages/send/tests/send-selectors.test.js | 156 ++--- ui/app/pages/send/tests/send-utils.test.js | 96 +-- .../tests/advanced-tab-component.test.js | 6 +- .../security-tab/tests/security-tab.test.js | 10 +- .../settings-tab/tests/settings-tab.test.js | 12 +- .../unlock-page/tests/unlock-page.test.js | 14 +- ui/app/selectors/custom-gas.test.js | 38 +- .../tests/confirm-transaction.test.js | 22 +- ui/app/selectors/tests/selectors.test.js | 6 +- ui/app/selectors/tests/tokens.test.js | 4 +- ui/app/selectors/tests/transactions.test.js | 28 +- yarn.lock | 26 +- 202 files changed, 2702 insertions(+), 2932 deletions(-) create mode 100644 test/e2e/.eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js index 558e66bc2..d40917334 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,5 @@ module.exports = { + root: true, parser: 'babel-eslint', parserOptions: { 'sourceType': 'module', @@ -20,17 +21,16 @@ module.exports = { extends: [ '@metamask/eslint-config', '@metamask/eslint-config/config/nodejs', + '@metamask/eslint-config/config/mocha', 'plugin:react/recommended', ], env: { 'browser': true, - 'mocha': true, }, plugins: [ 'babel', - 'mocha', 'chai', 'react', 'json', @@ -90,6 +90,6 @@ module.exports = { 'prop': 'parens-new-line', }], 'babel/semi': ['error', 'never'], - 'mocha/no-exclusive-tests': 'error', + 'mocha/no-setup-in-describe': 'off', }, } diff --git a/package.json b/package.json index 7e48f4147..27e9ed66e 100644 --- a/package.json +++ b/package.json @@ -176,7 +176,7 @@ "@babel/preset-env": "^7.5.5", "@babel/preset-react": "^7.0.0", "@babel/register": "^7.5.5", - "@metamask/eslint-config": "^1.0.0", + "@metamask/eslint-config": "^1.1.0", "@metamask/forwarder": "^1.1.0", "@metamask/onboarding": "^0.2.0", "@sentry/cli": "^1.49.0", @@ -208,7 +208,7 @@ "eslint-plugin-chai": "0.0.1", "eslint-plugin-import": "^2.19.1", "eslint-plugin-json": "^1.2.0", - "eslint-plugin-mocha": "^5.0.0", + "eslint-plugin-mocha": "^6.2.2", "eslint-plugin-react": "^7.4.0", "fancy-log": "^1.3.3", "fetch-mock": "^6.5.2", diff --git a/test/e2e/.eslintrc.js b/test/e2e/.eslintrc.js new file mode 100644 index 000000000..d84a4b2fb --- /dev/null +++ b/test/e2e/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + rules: { + 'mocha/no-hooks-for-single-case': 'off', + }, +} diff --git a/test/e2e/address-book.spec.js b/test/e2e/address-book.spec.js index 02d391cb4..95c78b27d 100644 --- a/test/e2e/address-book.spec.js +++ b/test/e2e/address-book.spec.js @@ -52,24 +52,24 @@ describe('MetaMask', function () { await driver.quit() }) - describe('Going through the first time flow', () => { - it('clicks the continue button on the welcome screen', async () => { + describe('Going through the first time flow', function () { + it('clicks the continue button on the welcome screen', async function () { await driver.findElement(By.css('.welcome-page__header')) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "Create New Wallet" option', async () => { + it('clicks the "Create New Wallet" option', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { + it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) - it('accepts a secure password', async () => { + it('accepts a secure password', async function () { const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) @@ -83,7 +83,7 @@ describe('MetaMask', function () { let seedPhrase - it('reveals the seed phrase', async () => { + it('reveals the seed phrase', async function () { const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button') await driver.clickElement(byRevealButton) await driver.delay(regularDelayMs) @@ -102,7 +102,7 @@ describe('MetaMask', function () { await driver.delay(tinyDelayMs) } - it('can retype the seed phrase', async () => { + it('can retype the seed phrase', async function () { const words = seedPhrase.split(' ') for (const word of words) { @@ -113,15 +113,15 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('clicks through the success screen', async () => { + it('clicks through the success screen', async function () { await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver.delay(regularDelayMs) }) }) - describe('Import seed phrase', () => { - it('logs out of the vault', async () => { + describe('Import seed phrase', function () { + it('logs out of the vault', async function () { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) @@ -131,7 +131,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('imports seed phrase', async () => { + it('imports seed phrase', async function () { const restoreSeedLink = await driver.findClickableElement(By.css('.unlock-page__link--import')) assert.equal(await restoreSeedLink.getText(), 'Import using account seed phrase') await restoreSeedLink.click() @@ -150,14 +150,14 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('balance renders', async () => { + it('balance renders', async function () { const balance = await driver.findElement(By.css('.balance-display .token-amount')) await driver.wait(until.elementTextMatches(balance, /25\s*ETH/)) await driver.delay(regularDelayMs) }) }) - describe('Adds an entry to the address book and sends eth to that address', () => { + describe('Adds an entry to the address book and sends eth to that address', function () { it('starts a send transaction', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) @@ -205,7 +205,7 @@ describe('MetaMask', function () { }) }) - describe('Sends to an address book entry', () => { + describe('Sends to an address book entry', function () { it('starts a send transaction by clicking address book entry', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) diff --git a/test/e2e/ethereum-on.spec.js b/test/e2e/ethereum-on.spec.js index 30bacf16a..8fce9c45b 100644 --- a/test/e2e/ethereum-on.spec.js +++ b/test/e2e/ethereum-on.spec.js @@ -51,24 +51,24 @@ describe('MetaMask', function () { await driver.quit() }) - describe('Going through the first time flow, but skipping the seed phrase challenge', () => { - it('clicks the continue button on the welcome screen', async () => { + describe('Going through the first time flow, but skipping the seed phrase challenge', function () { + it('clicks the continue button on the welcome screen', async function () { await driver.findElement(By.css('.welcome-page__header')) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "Create New Wallet" option', async () => { + it('clicks the "Create New Wallet" option', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { + it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) - it('accepts a secure password', async () => { + it('accepts a secure password', async function () { const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) @@ -80,7 +80,7 @@ describe('MetaMask', function () { await driver.delay(largeDelayMs) }) - it('skips the seed phrase challenge', async () => { + it('skips the seed phrase challenge', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) await driver.delay(regularDelayMs) @@ -88,7 +88,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('gets the current accounts address', async () => { + it('gets the current accounts address', async function () { const addressInput = await driver.findElement(By.css('.qr-ellip-address')) publicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) @@ -101,12 +101,12 @@ describe('MetaMask', function () { }) - describe('provider listening for events', () => { + describe('provider listening for events', function () { let extension let popup let dapp - it('connects to the dapp', async () => { + it('connects to the dapp', async function () { await driver.openNewPage('http://127.0.0.1:8080/') await driver.delay(regularDelayMs) @@ -134,13 +134,13 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('has the ganache network id within the dapp', async () => { + it('has the ganache network id within the dapp', async function () { const networkDiv = await driver.findElement(By.css('#network')) await driver.delay(regularDelayMs) assert.equal(await networkDiv.getText(), '5777') }) - it('changes the network', async () => { + it('changes the network', async function () { await driver.switchToWindow(extension) await driver.clickElement(By.css('.network-name')) @@ -150,19 +150,19 @@ describe('MetaMask', function () { await driver.delay(largeDelayMs) }) - it('sets the network div within the dapp', async () => { + it('sets the network div within the dapp', async function () { await driver.switchToWindow(dapp) const networkDiv = await driver.findElement(By.css('#network')) assert.equal(await networkDiv.getText(), '3') }) - it('sets the chainId div within the dapp', async () => { + it('sets the chainId div within the dapp', async function () { await driver.switchToWindow(dapp) const chainIdDiv = await driver.findElement(By.css('#chainId')) assert.equal(await chainIdDiv.getText(), '0x3') }) - it('sets the account div within the dapp', async () => { + it('sets the account div within the dapp', async function () { await driver.switchToWindow(dapp) const accountsDiv = await driver.findElement(By.css('#accounts')) assert.equal(await accountsDiv.getText(), publicAddress.toLowerCase()) diff --git a/test/e2e/from-import-ui.spec.js b/test/e2e/from-import-ui.spec.js index 9911ec8d1..666981bc3 100644 --- a/test/e2e/from-import-ui.spec.js +++ b/test/e2e/from-import-ui.spec.js @@ -56,24 +56,24 @@ describe('Using MetaMask with an existing account', function () { await driver.quit() }) - describe('First time flow starting from an existing seed phrase', () => { - it('clicks the continue button on the welcome screen', async () => { + describe('First time flow starting from an existing seed phrase', function () { + it('clicks the continue button on the welcome screen', async function () { await driver.findElement(By.css('.welcome-page__header')) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "Import Wallet" option', async () => { + it('clicks the "Import Wallet" option', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { + it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) - it('imports a seed phrase', async () => { + it('imports a seed phrase', async function () { const [seedTextArea] = await driver.findElements(By.css('textarea.first-time-flow__textarea')) await seedTextArea.sendKeys(testSeedPhrase) await driver.delay(regularDelayMs) @@ -89,15 +89,15 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(regularDelayMs) }) - it('clicks through the success screen', async () => { + it('clicks through the success screen', async function () { await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver.delay(regularDelayMs) }) }) - describe('Show account information', () => { - it('shows the correct account address', async () => { + describe('Show account information', function () { + it('shows the correct account address', async function () { await driver.clickElement(By.css('.account-details__details-button')) await driver.findVisibleElement(By.css('.qr-wrapper')) await driver.delay(regularDelayMs) @@ -109,7 +109,7 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(largeDelayMs) }) - it('shows a QR code for the account', async () => { + it('shows a QR code for the account', async function () { await driver.clickElement(By.css('.account-details__details-button')) await driver.findVisibleElement(By.css('.qr-wrapper')) const detailModal = await driver.findElement(By.css('span .modal')) @@ -121,8 +121,8 @@ describe('Using MetaMask with an existing account', function () { }) }) - describe('Lock and unlock', () => { - it('logs out of the account', async () => { + describe('Lock and unlock', function () { + it('logs out of the account', async function () { await driver.clickElement(By.css('.account-menu__icon .identicon')) await driver.delay(regularDelayMs) @@ -132,7 +132,7 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(regularDelayMs) }) - it('accepts the account password after lock', async () => { + it('accepts the account password after lock', async function () { const passwordField = await driver.findElement(By.id('password')) await passwordField.sendKeys('correct horse battery staple') await passwordField.sendKeys(Key.ENTER) @@ -140,8 +140,8 @@ describe('Using MetaMask with an existing account', function () { }) }) - describe('Add an account', () => { - it('switches to localhost', async () => { + describe('Add an account', function () { + it('switches to localhost', async function () { await driver.clickElement(By.css('.network-name')) await driver.delay(regularDelayMs) @@ -149,7 +149,7 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(largeDelayMs) }) - it('choose Create Account from the account menu', async () => { + it('choose Create Account from the account menu', async function () { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) @@ -157,7 +157,7 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(regularDelayMs) }) - it('set account name', async () => { + it('set account name', async function () { const [accountName] = await driver.findElements(By.css('.new-account-create-form input')) await accountName.sendKeys('2nd account') await driver.delay(regularDelayMs) @@ -166,15 +166,15 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(regularDelayMs) }) - it('should show the correct account name', async () => { + it('should show the correct account name', async function () { const [accountName] = await driver.findElements(By.css('.account-details__account-name')) assert.equal(await accountName.getText(), '2nd account') await driver.delay(regularDelayMs) }) }) - describe('Switch back to original account', () => { - it('chooses the original account from the account menu', async () => { + describe('Switch back to original account', function () { + it('chooses the original account from the account menu', async function () { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) @@ -183,7 +183,7 @@ describe('Using MetaMask with an existing account', function () { }) }) - describe('Send ETH from inside MetaMask', () => { + describe('Send ETH from inside MetaMask', function () { it('starts a send transaction', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) @@ -225,8 +225,8 @@ describe('Using MetaMask with an existing account', function () { }) }) - describe('Imports an account with private key', () => { - it('choose Create Account from the account menu', async () => { + describe('Imports an account with private key', function () { + it('choose Create Account from the account menu', async function () { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) @@ -234,7 +234,7 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(regularDelayMs) }) - it('enter private key', async () => { + it('enter private key', async function () { const privateKeyInput = await driver.findElement(By.css('#private-key-box')) await privateKeyInput.sendKeys(testPrivateKey2) await driver.delay(regularDelayMs) @@ -242,21 +242,21 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(regularDelayMs) }) - it('should show the correct account name', async () => { + it('should show the correct account name', async function () { const [accountName] = await driver.findElements(By.css('.account-details__account-name')) assert.equal(await accountName.getText(), 'Account 4') await driver.delay(regularDelayMs) }) - it('should show the imported label', async () => { + it('should show the imported label', async function () { const [importedLabel] = await driver.findElements(By.css('.account-details__keyring-label')) assert.equal(await importedLabel.getText(), 'IMPORTED') await driver.delay(regularDelayMs) }) }) - describe('Imports and removes an account', () => { - it('choose Create Account from the account menu', async () => { + describe('Imports and removes an account', function () { + it('choose Create Account from the account menu', async function () { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) @@ -264,7 +264,7 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(regularDelayMs) }) - it('enter private key', async () => { + it('enter private key', async function () { const privateKeyInput = await driver.findElement(By.css('#private-key-box')) await privateKeyInput.sendKeys(testPrivateKey3) await driver.delay(regularDelayMs) @@ -272,7 +272,7 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(regularDelayMs) }) - it('should open the remove account modal', async () => { + it('should open the remove account modal', async function () { const [accountName] = await driver.findElements(By.css('.account-details__account-name')) assert.equal(await accountName.getText(), 'Account 5') await driver.delay(regularDelayMs) @@ -289,7 +289,7 @@ describe('Using MetaMask with an existing account', function () { await driver.findElement(By.css('.confirm-remove-account__account')) }) - it('should remove the account', async () => { + it('should remove the account', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Remove')]`)) await driver.delay(regularDelayMs) @@ -303,13 +303,13 @@ describe('Using MetaMask with an existing account', function () { }) }) - describe('Connects to a Hardware wallet', () => { - it('choose Connect Hardware Wallet from the account menu', async () => { + describe('Connects to a Hardware wallet', function () { + it('choose Connect Hardware Wallet from the account menu', async function () { await driver.clickElement(By.xpath(`//div[contains(text(), 'Connect Hardware Wallet')]`)) await driver.delay(regularDelayMs) }) - it('should open the TREZOR Connect popup', async () => { + it('should open the TREZOR Connect popup', async function () { await driver.clickElement(By.css('.hw-connect__btn:nth-of-type(2)')) await driver.delay(regularDelayMs) await driver.clickElement(By.xpath(`//button[contains(text(), 'Connect')]`)) diff --git a/test/e2e/incremental-security.spec.js b/test/e2e/incremental-security.spec.js index 734655b81..57b38cb65 100644 --- a/test/e2e/incremental-security.spec.js +++ b/test/e2e/incremental-security.spec.js @@ -56,24 +56,24 @@ describe('MetaMask', function () { await driver.quit() }) - describe('Going through the first time flow, but skipping the seed phrase challenge', () => { - it('clicks the continue button on the welcome screen', async () => { + describe('Going through the first time flow, but skipping the seed phrase challenge', function () { + it('clicks the continue button on the welcome screen', async function () { await driver.findElement(By.css('.welcome-page__header')) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "Create New Wallet" option', async () => { + it('clicks the "Create New Wallet" option', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { + it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) - it('accepts a secure password', async () => { + it('accepts a secure password', async function () { const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) @@ -86,7 +86,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('skips the seed phrase challenge', async () => { + it('skips the seed phrase challenge', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) await driver.delay(regularDelayMs) @@ -94,7 +94,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('gets the current accounts address', async () => { + it('gets the current accounts address', async function () { const addressInput = await driver.findElement(By.css('.qr-ellip-address')) publicAddress = await addressInput.getAttribute('value') @@ -108,10 +108,10 @@ describe('MetaMask', function () { }) - describe('send to current account from dapp with different provider', () => { + describe('send to current account from dapp with different provider', function () { let extension - it('switches to dapp screen', async () => { + it('switches to dapp screen', async function () { const windowHandles = await driver.getAllWindowHandles() extension = windowHandles[0] @@ -119,7 +119,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('sends eth to the current account', async () => { + it('sends eth to the current account', async function () { const addressInput = await driver.findElement(By.css('#address')) await addressInput.sendKeys(publicAddress) await driver.delay(regularDelayMs) @@ -130,11 +130,11 @@ describe('MetaMask', function () { await driver.wait(until.elementTextMatches(txStatus, /Success/), 15000) }) - it('switches back to MetaMask', async () => { + it('switches back to MetaMask', async function () { await driver.switchToWindow(extension) }) - it('should have the correct amount of eth', async () => { + it('should have the correct amount of eth', async function () { const balances = await driver.findElements(By.css('.currency-display-component__text')) await driver.wait(until.elementTextMatches(balances[0], /1/), 15000) const balance = await balances[0].getText() @@ -143,20 +143,20 @@ describe('MetaMask', function () { }) }) - describe('backs up the seed phrase', () => { - it('should show a backup reminder', async () => { + describe('backs up the seed phrase', function () { + it('should show a backup reminder', async function () { const backupReminder = await driver.findElements(By.xpath("//div[contains(@class, 'home-notification__text') and contains(text(), 'Backup your Secret Recovery code to keep your wallet and funds secure')]")) assert.equal(backupReminder.length, 1) }) - it('should take the user to the seedphrase backup screen', async () => { + it('should take the user to the seedphrase backup screen', async function () { await driver.clickElement(By.css('.home-notification__accept-button')) await driver.delay(regularDelayMs) }) let seedPhrase - it('reveals the seed phrase', async () => { + it('reveals the seed phrase', async function () { const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button') await driver.clickElement(byRevealButton) await driver.delay(regularDelayMs) @@ -175,7 +175,7 @@ describe('MetaMask', function () { await driver.delay(tinyDelayMs) } - it('can retype the seed phrase', async () => { + it('can retype the seed phrase', async function () { const words = seedPhrase.split(' ') for (const word of words) { @@ -186,12 +186,12 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('can click through the success screen', async () => { + it('can click through the success screen', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'All Done')]`)) await driver.delay(regularDelayMs) }) - it('should have the correct amount of eth', async () => { + it('should have the correct amount of eth', async function () { const balances = await driver.findElements(By.css('.currency-display-component__text')) await driver.wait(until.elementTextMatches(balances[0], /1/), 15000) const balance = await balances[0].getText() @@ -199,7 +199,7 @@ describe('MetaMask', function () { assert.equal(balance, '1') }) - it('should not show a backup reminder', async () => { + it('should not show a backup reminder', async function () { await driver.assertElementNotPresent(By.css('.backup-notification')) }) }) diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index 6dda0192c..41eee8efd 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -46,24 +46,24 @@ describe('MetaMask', function () { await driver.quit() }) - describe('Going through the first time flow', () => { - it('clicks the continue button on the welcome screen', async () => { + describe('Going through the first time flow', function () { + it('clicks the continue button on the welcome screen', async function () { await driver.findElement(By.css('.welcome-page__header')) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "Create New Wallet" option', async () => { + it('clicks the "Create New Wallet" option', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "I agree" option on the metametrics opt-in screen', async () => { + it('clicks the "I agree" option on the metametrics opt-in screen', async function () { await driver.clickElement(By.css('.btn-primary')) await driver.delay(largeDelayMs) }) - it('accepts a secure password', async () => { + it('accepts a secure password', async function () { const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) @@ -78,7 +78,7 @@ describe('MetaMask', function () { let seedPhrase - it('reveals the seed phrase', async () => { + it('reveals the seed phrase', async function () { const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button') await driver.clickElement(byRevealButton) await driver.delay(regularDelayMs) @@ -97,7 +97,7 @@ describe('MetaMask', function () { await driver.delay(tinyDelayMs) } - it('can retype the seed phrase', async () => { + it('can retype the seed phrase', async function () { const words = seedPhrase.split(' ') for (const word of words) { @@ -108,15 +108,15 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('clicks through the success screen', async () => { + it('clicks through the success screen', async function () { await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver.delay(regularDelayMs) }) }) - describe('Show account information', () => { - it('show account details dropdown menu', async () => { + describe('Show account information', function () { + it('show account details dropdown menu', async function () { await driver.clickElement(By.css('div.menu-bar__open-in-browser')) const options = await driver.findElements(By.css('div.menu.account-details-dropdown div.menu__item')) assert.equal(options.length, 4) // HD Wallet type does not have to show the Remove Account option @@ -124,8 +124,8 @@ describe('MetaMask', function () { }) }) - describe('Import seed phrase', () => { - it('logs out of the vault', async () => { + describe('Import seed phrase', function () { + it('logs out of the vault', async function () { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) @@ -135,7 +135,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('imports seed phrase', async () => { + it('imports seed phrase', async function () { const restoreSeedLink = await driver.findClickableElement(By.css('.unlock-page__link--import')) assert.equal(await restoreSeedLink.getText(), 'Import using account seed phrase') await restoreSeedLink.click() @@ -154,7 +154,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('switches to localhost', async () => { + it('switches to localhost', async function () { await driver.clickElement(By.css('.network-name')) await driver.delay(regularDelayMs) @@ -162,14 +162,14 @@ describe('MetaMask', function () { await driver.delay(largeDelayMs * 2) }) - it('balance renders', async () => { + it('balance renders', async function () { const balance = await driver.findElement(By.css('.transaction-view-balance__primary-balance')) await driver.wait(until.elementTextMatches(balance, /100\s*ETH/)) await driver.delay(regularDelayMs) }) }) - describe('Send ETH from inside MetaMask', () => { + describe('Send ETH from inside MetaMask', function () { it('starts to send a transaction', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index d3f5f6e5e..ad86c1ec1 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -47,24 +47,24 @@ describe('MetaMask', function () { await driver.quit() }) - describe('Going through the first time flow', () => { - it('clicks the continue button on the welcome screen', async () => { + describe('Going through the first time flow', function () { + it('clicks the continue button on the welcome screen', async function () { await driver.findElement(By.css('.welcome-page__header')) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "Create New Wallet" option', async () => { + it('clicks the "Create New Wallet" option', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { + it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) - it('accepts a secure password', async () => { + it('accepts a secure password', async function () { const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) @@ -79,7 +79,7 @@ describe('MetaMask', function () { let seedPhrase - it('reveals the seed phrase', async () => { + it('reveals the seed phrase', async function () { const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button') await driver.findElement(byRevealButton) await driver.clickElement(byRevealButton) @@ -99,7 +99,7 @@ describe('MetaMask', function () { await driver.delay(tinyDelayMs) } - it('can retype the seed phrase', async () => { + it('can retype the seed phrase', async function () { const words = seedPhrase.split(' ') for (const word of words) { @@ -110,15 +110,15 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('clicks through the success screen', async () => { + it('clicks through the success screen', async function () { await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver.delay(regularDelayMs) }) }) - describe('Show account information', () => { - it('shows the QR code for the account', async () => { + describe('Show account information', function () { + it('shows the QR code for the account', async function () { await driver.clickElement(By.css('.account-details__details-button')) await driver.findVisibleElement(By.css('.qr-wrapper')) await driver.delay(regularDelayMs) @@ -131,8 +131,8 @@ describe('MetaMask', function () { }) }) - describe('Lock an unlock', () => { - it('logs out of the account', async () => { + describe('Lock an unlock', function () { + it('logs out of the account', async function () { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) @@ -142,7 +142,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('accepts the account password after lock', async () => { + it('accepts the account password after lock', async function () { const passwordField = await driver.findElement(By.id('password')) await passwordField.sendKeys('correct horse battery staple') await passwordField.sendKeys(Key.ENTER) @@ -150,8 +150,8 @@ describe('MetaMask', function () { }) }) - describe('Add account', () => { - it('choose Create Account from the account menu', async () => { + describe('Add account', function () { + it('choose Create Account from the account menu', async function () { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) @@ -159,7 +159,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('set account name', async () => { + it('set account name', async function () { const accountName = await driver.findElement(By.css('.new-account-create-form input')) await accountName.sendKeys('2nd account') await driver.delay(regularDelayMs) @@ -168,15 +168,15 @@ describe('MetaMask', function () { await driver.delay(largeDelayMs) }) - it('should display correct account name', async () => { + it('should display correct account name', async function () { const accountName = await driver.findElement(By.css('.account-details__account-name')) assert.equal(await accountName.getText(), '2nd account') await driver.delay(regularDelayMs) }) }) - describe('Import seed phrase', () => { - it('logs out of the vault', async () => { + describe('Import seed phrase', function () { + it('logs out of the vault', async function () { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) @@ -186,7 +186,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('imports seed phrase', async () => { + it('imports seed phrase', async function () { const restoreSeedLink = await driver.findClickableElement(By.css('.unlock-page__link--import')) assert.equal(await restoreSeedLink.getText(), 'Import using account seed phrase') await restoreSeedLink.click() @@ -205,14 +205,14 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('balance renders', async () => { + it('balance renders', async function () { const balance = await driver.findElement(By.css('.balance-display .token-amount')) await driver.wait(until.elementTextMatches(balance, /100\s*ETH/)) await driver.delay(regularDelayMs) }) }) - describe('Send ETH from inside MetaMask using default gas', () => { + describe('Send ETH from inside MetaMask using default gas', function () { it('starts a send transaction', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) @@ -275,7 +275,7 @@ describe('MetaMask', function () { }) }) - describe('Send ETH from inside MetaMask using fast gas option', () => { + describe('Send ETH from inside MetaMask using fast gas option', function () { it('starts a send transaction', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) @@ -314,7 +314,7 @@ describe('MetaMask', function () { }) }) - describe('Send ETH from inside MetaMask using advanced gas modal', () => { + describe('Send ETH from inside MetaMask using advanced gas modal', function () { it('starts a send transaction', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) @@ -362,13 +362,13 @@ describe('MetaMask', function () { }) }) - describe('Send ETH from dapp using advanced gas controls', () => { + describe('Send ETH from dapp using advanced gas controls', function () { let windowHandles let extension let popup let dapp - it('goes to the settings screen', async () => { + it('goes to the settings screen', async function () { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) @@ -394,7 +394,7 @@ describe('MetaMask', function () { await driver.delay(largeDelayMs) }) - it('connects the dapp', async () => { + it('connects the dapp', async function () { await driver.openNewPage('http://127.0.0.1:8080/') await driver.delay(regularDelayMs) @@ -422,7 +422,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('initiates a send from the dapp', async () => { + it('initiates a send from the dapp', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`), 10000) await driver.delay(2000) @@ -478,8 +478,8 @@ describe('MetaMask', function () { }) }) - describe('Navigate transactions', () => { - it('adds multiple transactions', async () => { + describe('Navigate transactions', function () { + it('adds multiple transactions', async function () { await driver.delay(regularDelayMs) await driver.waitUntilXWindowHandles(2) @@ -510,7 +510,7 @@ describe('MetaMask', function () { await driver.delay(largeDelayMs) }) - it('navigates the transactions', async () => { + it('navigates the transactions', async function () { await driver.clickElement(By.css('[data-testid="next-page"]')) let navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) let navigationText = await navigationElement.getText() @@ -547,7 +547,7 @@ describe('MetaMask', function () { assert.equal(navigationText.includes('2'), true, 'changed transaction left') }) - it('adds a transaction while confirm screen is in focus', async () => { + it('adds a transaction while confirm screen is in focus', async function () { let navigationElement = await driver.findElement(By.css('.confirm-page-container-navigation')) let navigationText = await navigationElement.getText() assert.equal(navigationText.includes('2'), true, 'second transaction in focus') @@ -570,7 +570,7 @@ describe('MetaMask', function () { assert.equal(navigationText.includes('2'), true, 'correct (same) transaction in focus') }) - it('rejects a transaction', async () => { + it('rejects a transaction', async function () { await driver.delay(tinyDelayMs) await driver.clickElement(By.xpath(`//button[contains(text(), 'Reject')]`)) await driver.delay(largeDelayMs * 2) @@ -581,7 +581,7 @@ describe('MetaMask', function () { assert.equal(navigationText.includes('4'), true, 'transaction rejected') }) - it('confirms a transaction', async () => { + it('confirms a transaction', async function () { await driver.delay(tinyDelayMs / 2) await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(regularDelayMs) @@ -593,7 +593,7 @@ describe('MetaMask', function () { assert.equal(navigationText.includes('3'), true, 'transaction confirmed') }) - it('rejects the rest of the transactions', async () => { + it('rejects the rest of the transactions', async function () { await driver.clickElement(By.xpath(`//a[contains(text(), 'Reject 3')]`)) await driver.delay(regularDelayMs) @@ -605,10 +605,10 @@ describe('MetaMask', function () { }) }) - describe('Deploy contract and call contract methods', () => { + describe('Deploy contract and call contract methods', function () { let extension let dapp - it('creates a deploy contract transaction', async () => { + it('creates a deploy contract transaction', async function () { const windowHandles = await driver.getAllWindowHandles() extension = windowHandles[0] dapp = windowHandles[1] @@ -627,7 +627,7 @@ describe('MetaMask', function () { await driver.delay(largeDelayMs) }) - it('displays the contract creation data', async () => { + it('displays the contract creation data', async function () { await driver.clickElement(By.xpath(`//li[contains(text(), 'Data')]`)) await driver.delay(regularDelayMs) @@ -641,7 +641,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('confirms a deploy contract transaction', async () => { + it('confirms a deploy contract transaction', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`)) await driver.delay(largeDelayMs) @@ -655,7 +655,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('calls and confirms a contract method where ETH is sent', async () => { + it('calls and confirms a contract method where ETH is sent', async function () { await driver.switchToWindow(dapp) await driver.delay(regularDelayMs) @@ -721,7 +721,7 @@ describe('MetaMask', function () { await driver.wait(until.elementTextMatches(txValues[0], /-4\s*ETH/), 10000) }) - it('calls and confirms a contract method where ETH is received', async () => { + it('calls and confirms a contract method where ETH is received', async function () { await driver.switchToWindow(dapp) await driver.delay(regularDelayMs) @@ -749,7 +749,7 @@ describe('MetaMask', function () { await driver.switchToWindow(extension) }) - it('renders the correct ETH balance', async () => { + it('renders the correct ETH balance', async function () { const balance = await driver.findElement(By.css('.transaction-view-balance__primary-balance')) await driver.delay(regularDelayMs) await driver.wait(until.elementTextMatches(balance, /^87.*\s*ETH.*$/), 10000) @@ -759,8 +759,8 @@ describe('MetaMask', function () { }) }) - describe('Add a custom token from a dapp', () => { - it('creates a new token', async () => { + describe('Add a custom token from a dapp', function () { + it('creates a new token', async function () { let windowHandles = await driver.getAllWindowHandles() const extension = windowHandles[0] const dapp = windowHandles[1] @@ -807,12 +807,12 @@ describe('MetaMask', function () { await driver.delay(largeDelayMs) }) - it('clicks on the Add Token button', async () => { + it('clicks on the Add Token button', async function () { await driver.clickElement(By.xpath(`//div[contains(text(), 'Add Token')]`)) await driver.delay(regularDelayMs) }) - it('picks the newly created Test token', async () => { + it('picks the newly created Test token', async function () { await driver.clickElement(By.xpath("//li[contains(text(), 'Custom Token')]")) await driver.delay(regularDelayMs) @@ -827,7 +827,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('renders the balance for the new token', async () => { + it('renders the balance for the new token', async function () { const balance = await driver.findElement(By.css('.transaction-view-balance .transaction-view-balance__primary-balance')) await driver.wait(until.elementTextMatches(balance, /^10.000\s*TST\s*$/)) const tokenAmount = await balance.getText() @@ -836,7 +836,7 @@ describe('MetaMask', function () { }) }) - describe('Send token from inside MetaMask', () => { + describe('Send token from inside MetaMask', function () { let gasModal it('starts to send a transaction', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) @@ -856,13 +856,13 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('opens customize gas modal', async () => { + it('opens customize gas modal', async function () { await driver.findElement(By.css('.page-container__title')) await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) await driver.delay(regularDelayMs) }) - it('transitions to the confirm screen', async () => { + it('transitions to the confirm screen', async function () { await driver.wait(until.stalenessOf(gasModal)) // Continue to next screen @@ -870,7 +870,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('displays the token transfer data', async () => { + it('displays the token transfer data', async function () { await driver.clickElement(By.xpath(`//li[contains(text(), 'Data')]`)) await driver.delay(regularDelayMs) @@ -912,9 +912,9 @@ describe('MetaMask', function () { }) }) - describe('Send a custom token from dapp', () => { + describe('Send a custom token from dapp', function () { let gasModal - it('sends an already created token', async () => { + it('sends an already created token', async function () { const windowHandles = await driver.getAllWindowHandles() const extension = windowHandles[0] const dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) @@ -945,7 +945,7 @@ describe('MetaMask', function () { gasModal = await driver.findElement(By.css('span .modal')) }) - it('customizes gas', async () => { + it('customizes gas', async function () { await driver.clickElement(By.css('.page-container__tab:nth-of-type(2)')) await driver.delay(regularDelayMs) @@ -1003,9 +1003,9 @@ describe('MetaMask', function () { }) }) - describe('Approves a custom token from dapp', () => { + describe('Approves a custom token from dapp', function () { let gasModal - it('approves an already created token', async () => { + it('approves an already created token', async function () { const windowHandles = await driver.getAllWindowHandles() const extension = windowHandles[0] const dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) @@ -1031,7 +1031,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('displays the token approval data', async () => { + it('displays the token approval data', async function () { await driver.clickElement(By.css('.confirm-approve-content__view-full-tx-button')) await driver.delay(regularDelayMs) @@ -1044,14 +1044,14 @@ describe('MetaMask', function () { assert(confirmDataText.match(/0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef4/)) }) - it('opens the gas edit modal', async () => { + it('opens the gas edit modal', async function () { await driver.clickElement(By.css('.confirm-approve-content__small-blue-text.cursor-pointer')) await driver.delay(regularDelayMs) gasModal = await driver.findElement(By.css('span .modal')) }) - it('customizes gas', async () => { + it('customizes gas', async function () { await driver.clickElement(By.css('.page-container__tab:nth-of-type(2)')) await driver.delay(regularDelayMs) @@ -1078,7 +1078,7 @@ describe('MetaMask', function () { assert.equal(await gasFeeInEth.getText(), '0.0006 ETH') }) - it('edits the permission', async () => { + it('edits the permission', async function () { const editButtons = await driver.findClickableElements(By.css('.confirm-approve-content__small-blue-text.cursor-pointer')) await editButtons[1].click() await driver.delay(regularDelayMs) @@ -1121,8 +1121,8 @@ describe('MetaMask', function () { }) }) - describe('Tranfers a custom token from dapp when no gas value is specified', () => { - it('transfers an already created token, without specifying gas', async () => { + describe('Tranfers a custom token from dapp when no gas value is specified', function () { + it('transfers an already created token, without specifying gas', async function () { const windowHandles = await driver.getAllWindowHandles() const extension = windowHandles[0] const dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) @@ -1166,8 +1166,8 @@ describe('MetaMask', function () { }) }) - describe('Approves a custom token from dapp when no gas value is specified', () => { - it('approves an already created token', async () => { + describe('Approves a custom token from dapp when no gas value is specified', function () { + it('approves an already created token', async function () { const windowHandles = await driver.getAllWindowHandles() const extension = windowHandles[0] const dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) @@ -1221,8 +1221,8 @@ describe('MetaMask', function () { }) }) - describe('Hide token', () => { - it('hides the token when clicked', async () => { + describe('Hide token', function () { + it('hides the token when clicked', async function () { await driver.clickElement(By.css('.token-list-item__ellipsis')) const byTokenMenuDropdownOption = By.css('.menu__item--clickable') @@ -1237,13 +1237,13 @@ describe('MetaMask', function () { }) }) - describe('Add existing token using search', () => { - it('clicks on the Add Token button', async () => { + describe('Add existing token using search', function () { + it('clicks on the Add Token button', async function () { await driver.clickElement(By.xpath(`//div[contains(text(), 'Add Token')]`)) await driver.delay(regularDelayMs) }) - it('can pick a token from the existing options', async () => { + it('can pick a token from the existing options', async function () { const tokenSearch = await driver.findElement(By.css('#search-tokens')) await tokenSearch.sendKeys('BAT') await driver.delay(regularDelayMs) @@ -1258,14 +1258,14 @@ describe('MetaMask', function () { await driver.delay(largeDelayMs) }) - it('renders the balance for the chosen token', async () => { + it('renders the balance for the chosen token', async function () { const balance = await driver.findElement(By.css('.transaction-view-balance__primary-balance')) await driver.wait(until.elementTextMatches(balance, /0\s*BAT/)) await driver.delay(regularDelayMs) }) }) - describe('Stores custom RPC history', () => { + describe('Stores custom RPC history', function () { const customRpcUrls = [ 'http://127.0.0.1:8545/1', 'http://127.0.0.1:8545/2', @@ -1274,7 +1274,7 @@ describe('MetaMask', function () { ] customRpcUrls.forEach(customRpcUrl => { - it(`creates custom RPC: ${customRpcUrl}`, async () => { + it(`creates custom RPC: ${customRpcUrl}`, async function () { await driver.clickElement(By.css('.network-name')) await driver.delay(regularDelayMs) @@ -1293,7 +1293,7 @@ describe('MetaMask', function () { }) }) - it('selects another provider', async () => { + it('selects another provider', async function () { await driver.clickElement(By.css('.network-name')) await driver.delay(regularDelayMs) @@ -1301,7 +1301,7 @@ describe('MetaMask', function () { await driver.delay(largeDelayMs * 2) }) - it('finds all recent RPCs in history', async () => { + it('finds all recent RPCs in history', async function () { await driver.clickElement(By.css('.network-name')) await driver.delay(regularDelayMs) @@ -1311,7 +1311,7 @@ describe('MetaMask', function () { assert.equal(customRpcs.length, customRpcUrls.length) }) - it('deletes a custom RPC', async () => { + it('deletes a custom RPC', async function () { const networkListItems = await driver.findClickableElements(By.css('.networks-tab__networks-list-name')) const lastNetworkListItem = networkListItems[networkListItems.length - 1] await lastNetworkListItem.click() diff --git a/test/e2e/permissions.spec.js b/test/e2e/permissions.spec.js index 3f3d323b1..a34b11a8d 100644 --- a/test/e2e/permissions.spec.js +++ b/test/e2e/permissions.spec.js @@ -51,24 +51,24 @@ describe('MetaMask', function () { await driver.quit() }) - describe('Going through the first time flow, but skipping the seed phrase challenge', () => { - it('clicks the continue button on the welcome screen', async () => { + describe('Going through the first time flow, but skipping the seed phrase challenge', function () { + it('clicks the continue button on the welcome screen', async function () { await driver.findElement(By.css('.welcome-page__header')) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "Create New Wallet" option', async () => { + it('clicks the "Create New Wallet" option', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { + it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) - it('accepts a secure password', async () => { + it('accepts a secure password', async function () { const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password')) const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password')) @@ -81,7 +81,7 @@ describe('MetaMask', function () { await driver.delay(largeDelayMs) }) - it('skips the seed phrase challenge', async () => { + it('skips the seed phrase challenge', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`)) await driver.delay(regularDelayMs) @@ -89,7 +89,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('gets the current accounts address', async () => { + it('gets the current accounts address', async function () { const addressInput = await driver.findElement(By.css('.qr-ellip-address')) publicAddress = await addressInput.getAttribute('value') const accountModal = await driver.findElement(By.css('span .modal')) @@ -101,12 +101,12 @@ describe('MetaMask', function () { }) }) - describe('sets permissions', () => { + describe('sets permissions', function () { let extension let popup let dapp - it('connects to the dapp', async () => { + it('connects to the dapp', async function () { await driver.openNewPage('http://127.0.0.1:8080/') await driver.delay(regularDelayMs) @@ -132,7 +132,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('shows connected sites', async () => { + it('shows connected sites', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Connected Sites')]`)) await driver.findElement(By.css('.connected-sites__title')) @@ -149,7 +149,7 @@ describe('MetaMask', function () { assert.equal(await permissionDescription.getText(), 'View the address of the selected account') }) - it('can get accounts within the dapp', async () => { + it('can get accounts within the dapp', async function () { await driver.switchToWindow(dapp) await driver.delay(regularDelayMs) @@ -159,7 +159,7 @@ describe('MetaMask', function () { assert.equal((await getAccountsResult.getText()).toLowerCase(), publicAddress.toLowerCase()) }) - it('can disconnect all accounts', async () => { + it('can disconnect all accounts', async function () { await driver.switchToWindow(extension) await driver.clickElement(By.xpath(`//button[contains(text(), 'Disconnect All')]`)) @@ -172,7 +172,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('can no longer get accounts within the dapp', async () => { + it('can no longer get accounts within the dapp', async function () { await driver.switchToWindow(dapp) await driver.delay(regularDelayMs) diff --git a/test/e2e/send-edit.spec.js b/test/e2e/send-edit.spec.js index eb4473f60..8af966a20 100644 --- a/test/e2e/send-edit.spec.js +++ b/test/e2e/send-edit.spec.js @@ -53,24 +53,24 @@ describe('Using MetaMask with an existing account', function () { await driver.quit() }) - describe('First time flow starting from an existing seed phrase', () => { - it('clicks the continue button on the welcome screen', async () => { + describe('First time flow starting from an existing seed phrase', function () { + it('clicks the continue button on the welcome screen', async function () { await driver.findElement(By.css('.welcome-page__header')) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "Import Wallet" option', async () => { + it('clicks the "Import Wallet" option', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { + it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) - it('imports a seed phrase', async () => { + it('imports a seed phrase', async function () { const [seedTextArea] = await driver.findElements(By.css('textarea.first-time-flow__textarea')) await seedTextArea.sendKeys(testSeedPhrase) await driver.delay(regularDelayMs) @@ -86,14 +86,14 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(regularDelayMs) }) - it('clicks through the success screen', async () => { + it('clicks through the success screen', async function () { await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver.delay(regularDelayMs) }) }) - describe('Send ETH from inside MetaMask', () => { + describe('Send ETH from inside MetaMask', function () { it('starts a send transaction', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) await driver.delay(regularDelayMs) diff --git a/test/e2e/signature-request.spec.js b/test/e2e/signature-request.spec.js index 35526b973..738ea262c 100644 --- a/test/e2e/signature-request.spec.js +++ b/test/e2e/signature-request.spec.js @@ -51,13 +51,13 @@ describe('MetaMask', function () { await driver.quit() }) - describe('successfuly signs typed data', () => { + describe('successfuly signs typed data', function () { let extension let popup let dapp let windowHandles - it('accepts the account password after lock', async () => { + it('accepts the account password after lock', async function () { await driver.delay(1000) const passwordField = await driver.findElement(By.id('password')) await passwordField.sendKeys('correct horse battery staple') @@ -65,7 +65,7 @@ describe('MetaMask', function () { await driver.delay(largeDelayMs * 4) }) - it('connects to the dapp', async () => { + it('connects to the dapp', async function () { await driver.openNewPage('http://127.0.0.1:8080/') await driver.delay(regularDelayMs) @@ -92,7 +92,7 @@ describe('MetaMask', function () { await driver.switchToWindow(dapp) }) - it('creates a sign typed data signature request', async () => { + it('creates a sign typed data signature request', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Sign')]`), 10000) await driver.delay(largeDelayMs) @@ -112,7 +112,7 @@ describe('MetaMask', function () { assert.equal(await address.getText(), publicAddress.slice(0, 8) + '...' + publicAddress.slice(publicAddress.length - 8)) }) - it('signs the transaction', async () => { + it('signs the transaction', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Sign')]`), 10000) await driver.delay(regularDelayMs) @@ -120,7 +120,7 @@ describe('MetaMask', function () { await driver.switchToWindow(extension) }) - it('gets the current accounts address', async () => { + it('gets the current accounts address', async function () { await driver.clickElement(By.css('.account-details__details-button')) await driver.delay(regularDelayMs) diff --git a/test/e2e/tests/simple-send.spec.js b/test/e2e/tests/simple-send.spec.js index bf4eed442..e108f46ba 100644 --- a/test/e2e/tests/simple-send.spec.js +++ b/test/e2e/tests/simple-send.spec.js @@ -2,7 +2,7 @@ const { By, Key } = require('selenium-webdriver') const { withFixtures } = require('../helpers') describe('MetaMask Browser Extension', function () { - it('can send a simple transaction from one account to another', async () => { + it('can send a simple transaction from one account to another', async function () { const ganacheOptions = { accounts: [ { diff --git a/test/e2e/threebox.spec.js b/test/e2e/threebox.spec.js index 664ad2084..d55e9419a 100644 --- a/test/e2e/threebox.spec.js +++ b/test/e2e/threebox.spec.js @@ -54,26 +54,26 @@ describe('MetaMask', function () { await driver.quit() }) - describe('set up data to be restored by 3box', () => { + describe('set up data to be restored by 3box', function () { - describe('First time flow starting from an existing seed phrase', () => { - it('clicks the continue button on the welcome screen', async () => { + describe('First time flow starting from an existing seed phrase', function () { + it('clicks the continue button on the welcome screen', async function () { await driver.findElement(By.css('.welcome-page__header')) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "Import Wallet" option', async () => { + it('clicks the "Import Wallet" option', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { + it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) - it('imports a seed phrase', async () => { + it('imports a seed phrase', async function () { const [seedTextArea] = await driver.findElements(By.css('textarea.first-time-flow__textarea')) await seedTextArea.sendKeys(testSeedPhrase) await driver.delay(regularDelayMs) @@ -89,44 +89,44 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) }) - it('clicks through the success screen', async () => { + it('clicks through the success screen', async function () { await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver.delay(regularDelayMs) }) - it('balance renders', async () => { + it('balance renders', async function () { const balance = await driver.findElement(By.css('.balance-display .token-amount')) await driver.wait(until.elementTextMatches(balance, /25\s*ETH/)) await driver.delay(regularDelayMs) }) }) - describe('turns on threebox syncing', () => { - it('goes to the settings screen', async () => { + describe('turns on threebox syncing', function () { + it('goes to the settings screen', async function () { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) await driver.clickElement(By.xpath(`//div[contains(text(), 'Settings')]`)) }) - it('turns on threebox syncing', async () => { + it('turns on threebox syncing', async function () { await driver.clickElement(By.xpath(`//div[contains(text(), 'Advanced')]`)) await driver.clickElement(By.css('[data-testid="advanced-setting-3box"] .toggle-button div')) }) }) - describe('updates settings and address book', () => { - it('adds an address to the contact list', async () => { + describe('updates settings and address book', function () { + it('navigates to General settings', async function () { await driver.clickElement(By.xpath(`//div[contains(text(), 'General')]`)) }) - it('turns on use of blockies', async () => { + it('turns on use of blockies', async function () { await driver.clickElement(By.css('.toggle-button > div')) }) - it('adds an address to the contact list', async () => { + it('adds an address to the contact list', async function () { await driver.clickElement(By.xpath(`//div[contains(text(), 'Contacts')]`)) await driver.clickElement(By.css('.address-book-add-button__button')) @@ -150,7 +150,7 @@ describe('MetaMask', function () { }) - describe('restoration from 3box', () => { + describe('restoration from 3box', function () { let driver2 before(async function () { @@ -162,24 +162,24 @@ describe('MetaMask', function () { await driver2.quit() }) - describe('First time flow starting from an existing seed phrase', () => { - it('clicks the continue button on the welcome screen', async () => { + describe('First time flow starting from an existing seed phrase', function () { + it('clicks the continue button on the welcome screen', async function () { await driver2.findElement(By.css('.welcome-page__header')) await driver2.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver2.delay(largeDelayMs) }) - it('clicks the "Import Wallet" option', async () => { + it('clicks the "Import Wallet" option', async function () { await driver2.clickElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) await driver2.delay(largeDelayMs) }) - it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { + it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { await driver2.clickElement(By.css('.btn-default')) await driver2.delay(largeDelayMs) }) - it('imports a seed phrase', async () => { + it('imports a seed phrase', async function () { const [seedTextArea] = await driver2.findElements(By.css('textarea.first-time-flow__textarea')) await seedTextArea.sendKeys(testSeedPhrase) await driver2.delay(regularDelayMs) @@ -195,40 +195,40 @@ describe('MetaMask', function () { await driver2.delay(regularDelayMs) }) - it('clicks through the success screen', async () => { + it('clicks through the success screen', async function () { await driver2.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) await driver2.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver2.delay(regularDelayMs) }) - it('balance renders', async () => { + it('balance renders', async function () { const balance = await driver2.findElement(By.css('.balance-display .token-amount')) await driver2.wait(until.elementTextMatches(balance, /25\s*ETH/)) await driver2.delay(regularDelayMs) }) }) - describe('restores 3box data', () => { - it('confirms the 3box restore notification', async () => { + describe('restores 3box data', function () { + it('confirms the 3box restore notification', async function () { await driver2.clickElement(By.css('.home-notification__accept-button')) }) // TODO: Fix tests from here forward; they're using the wrong driver - it('goes to the settings screen', async () => { + it('goes to the settings screen', async function () { await driver.clickElement(By.css('.account-menu__icon')) await driver.delay(regularDelayMs) await driver.clickElement(By.xpath(`//div[contains(text(), 'Settings')]`)) }) - it('finds the blockies toggle turned on', async () => { + it('finds the blockies toggle turned on', async function () { await driver.delay(regularDelayMs) const toggleLabel = await driver.findElement(By.css('.toggle-button__status-label')) const toggleLabelText = await toggleLabel.getText() assert.equal(toggleLabelText, 'ON') }) - it('finds the restored address in the contact list', async () => { + it('finds the restored address in the contact list', async function () { await driver.clickElement(By.xpath(`//div[contains(text(), 'Contacts')]`)) await driver.delay(regularDelayMs) diff --git a/test/e2e/web3.spec.js b/test/e2e/web3.spec.js index 8312101b5..9769459f8 100644 --- a/test/e2e/web3.spec.js +++ b/test/e2e/web3.spec.js @@ -52,24 +52,24 @@ describe('Using MetaMask with an existing account', function () { await driver.quit() }) - describe('First time flow starting from an existing seed phrase', () => { - it('clicks the continue button on the welcome screen', async () => { + describe('First time flow starting from an existing seed phrase', function () { + it('clicks the continue button on the welcome screen', async function () { await driver.findElement(By.css('.welcome-page__header')) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "Import Wallet" option', async () => { + it('clicks the "Import Wallet" option', async function () { await driver.clickElement(By.xpath(`//button[contains(text(), 'Import Wallet')]`)) await driver.delay(largeDelayMs) }) - it('clicks the "No thanks" option on the metametrics opt-in screen', async () => { + it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { await driver.clickElement(By.css('.btn-default')) await driver.delay(largeDelayMs) }) - it('imports a seed phrase', async () => { + it('imports a seed phrase', async function () { const [seedTextArea] = await driver.findElements(By.css('textarea.first-time-flow__textarea')) await seedTextArea.sendKeys(testSeedPhrase) await driver.delay(regularDelayMs) @@ -85,7 +85,7 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(regularDelayMs) }) - it('clicks through the success screen', async () => { + it('clicks through the success screen', async function () { await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`)) await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`)) await driver.delay(regularDelayMs) @@ -93,9 +93,9 @@ describe('Using MetaMask with an existing account', function () { }) - describe('opens dapp', () => { + describe('opens dapp', function () { - it('switches to mainnet', async () => { + it('switches to mainnet', async function () { await driver.clickElement(By.css('.network-name')) await driver.delay(regularDelayMs) @@ -103,7 +103,7 @@ describe('Using MetaMask with an existing account', function () { await driver.delay(largeDelayMs * 2) }) - it('connects to dapp', async () => { + it('connects to dapp', async function () { await driver.openNewPage('http://127.0.0.1:8080/') await driver.delay(regularDelayMs) @@ -126,10 +126,10 @@ describe('Using MetaMask with an existing account', function () { }) }) - describe('testing web3 methods', async () => { + describe('testing web3 methods', function () { - it('testing hexa methods', async () => { + it('testing hexa methods', async function () { const List = await driver.findClickableElements(By.className('hexaNumberMethods')) @@ -151,7 +151,7 @@ describe('Using MetaMask with an existing account', function () { } }) - it('testing booleanMethods', async () => { + it('testing booleanMethods', async function () { const List = await driver.findClickableElement(By.className('booleanMethods')) @@ -174,7 +174,7 @@ describe('Using MetaMask with an existing account', function () { }) - it('testing transactionMethods', async () => { + it('testing transactionMethods', async function () { const List = await driver.findClickableElement(By.className('transactionMethods')) @@ -216,7 +216,7 @@ describe('Using MetaMask with an existing account', function () { }) - it('testing blockMethods', async () => { + it('testing blockMethods', async function () { const List = await driver.findClickableElement(By.className('blockMethods')) @@ -242,7 +242,7 @@ describe('Using MetaMask with an existing account', function () { } }) - it('testing methods', async () => { + it('testing methods', async function () { const List = await driver.findClickableElement(By.className('methods')) let parsedData diff --git a/test/unit-global/frozenPromise.js b/test/unit-global/frozenPromise.js index 485417cc0..05f1defe7 100644 --- a/test/unit-global/frozenPromise.js +++ b/test/unit-global/frozenPromise.js @@ -6,9 +6,9 @@ import '../../app/scripts/lib/freezeGlobals' import assert from 'assert' -describe('Promise global is immutable', () => { +describe('Promise global is immutable', function () { - it('throws when reassinging promise (syntax 1)', () => { + it('throws when reassinging promise (syntax 1)', function () { try { Promise = {} assert.fail('did not throw error') @@ -17,7 +17,7 @@ describe('Promise global is immutable', () => { } }) - it('throws when reassinging promise (syntax 2)', () => { + it('throws when reassinging promise (syntax 2)', function () { try { global.Promise = {} assert.fail('did not throw error') @@ -26,7 +26,7 @@ describe('Promise global is immutable', () => { } }) - it('throws when mutating existing Promise property', () => { + it('throws when mutating existing Promise property', function () { try { Promise.all = () => {} assert.fail('did not throw error') @@ -35,7 +35,7 @@ describe('Promise global is immutable', () => { } }) - it('throws when adding new Promise property', () => { + it('throws when adding new Promise property', function () { try { Promise.foo = 'bar' assert.fail('did not throw error') @@ -44,7 +44,7 @@ describe('Promise global is immutable', () => { } }) - it('throws when deleting Promise from global', () => { + it('throws when deleting Promise from global', function () { try { delete global.Promise assert.fail('did not throw error') diff --git a/test/unit/actions/tx_test.js b/test/unit/actions/tx_test.js index d0581294b..dc3accf56 100644 --- a/test/unit/actions/tx_test.js +++ b/test/unit/actions/tx_test.js @@ -25,7 +25,7 @@ describe('tx confirmation screen', function () { const store = mockStore(initialState) describe('cancelTx', function () { - before(function (done) { + it('creates COMPLETED_TX with the cancelled transaction ID', async function () { actions._setBackgroundConnection({ approveTransaction (_, cb) { cb('An error!') @@ -37,10 +37,7 @@ describe('tx confirmation screen', function () { cb() }, }) - done() - }) - it('creates COMPLETED_TX with the cancelled transaction ID', async function () { await store.dispatch(actions.cancelTx({ id: txId })) const storeActions = store.getActions() const completedTxAction = storeActions.find(({ type }) => type === actions.actionConstants.COMPLETED_TX) diff --git a/test/unit/app/ComposableObservableStore.js b/test/unit/app/ComposableObservableStore.js index 1b59d520f..4eb5f0299 100644 --- a/test/unit/app/ComposableObservableStore.js +++ b/test/unit/app/ComposableObservableStore.js @@ -2,20 +2,20 @@ import assert from 'assert' import ComposableObservableStore from '../../../app/scripts/lib/ComposableObservableStore' import ObservableStore from 'obs-store' -describe('ComposableObservableStore', () => { - it('should register initial state', () => { +describe('ComposableObservableStore', function () { + it('should register initial state', function () { const store = new ComposableObservableStore('state') assert.strictEqual(store.getState(), 'state') }) - it('should register initial structure', () => { + it('should register initial structure', function () { const testStore = new ObservableStore() const store = new ComposableObservableStore(null, { TestStore: testStore }) testStore.putState('state') assert.deepEqual(store.getState(), { TestStore: 'state' }) }) - it('should update structure', () => { + it('should update structure', function () { const testStore = new ObservableStore() const store = new ComposableObservableStore() store.updateStructure({ TestStore: testStore }) @@ -23,7 +23,7 @@ describe('ComposableObservableStore', () => { assert.deepEqual(store.getState(), { TestStore: 'state' }) }) - it('should return flattened state', () => { + it('should return flattened state', function () { const fooStore = new ObservableStore({ foo: 'foo' }) const barStore = new ObservableStore({ bar: 'bar' }) const store = new ComposableObservableStore(null, { diff --git a/test/unit/app/account-import-strategies.spec.js b/test/unit/app/account-import-strategies.spec.js index 1a8953bc1..fa43826d6 100644 --- a/test/unit/app/account-import-strategies.spec.js +++ b/test/unit/app/account-import-strategies.spec.js @@ -12,26 +12,24 @@ describe('Account Import Strategies', function () { assert.equal(importPrivKey, ethUtil.stripHexPrefix(privkey)) }) - it('throws an error for empty string private key', async () => { - return assert.rejects(async function () { + it('throws an error for empty string private key', async function () { + await assert.rejects(async () => { await accountImporter.importAccount('Private Key', [ '' ]) }, Error, 'no empty strings') }) - it('throws an error for undefined string private key', async () => { - return assert.rejects(async function () { + it('throws an error for undefined string private key', async function () { + await assert.rejects(async () => { await accountImporter.importAccount('Private Key', [ undefined ]) }) - }) - it('throws an error for undefined string private key', async () => { - return assert.rejects(async function () { + await assert.rejects(async () => { await accountImporter.importAccount('Private Key', []) }) }) - it('throws an error for invalid private key', async () => { - return assert.rejects(async function () { + it('throws an error for invalid private key', async function () { + await assert.rejects(async () => { await accountImporter.importAccount('Private Key', [ 'popcorn' ]) }) }) diff --git a/test/unit/app/cleanErrorStack.spec.js b/test/unit/app/cleanErrorStack.spec.js index 8c27ca249..fa793b605 100644 --- a/test/unit/app/cleanErrorStack.spec.js +++ b/test/unit/app/cleanErrorStack.spec.js @@ -1,7 +1,7 @@ import assert from 'assert' import cleanErrorStack from '../../../app/scripts/lib/cleanErrorStack' -describe('Clean Error Stack', () => { +describe('Clean Error Stack', function () { const testMessage = 'Test Message' const testError = new Error(testMessage) @@ -9,24 +9,24 @@ describe('Clean Error Stack', () => { const blankErrorName = new Error(testMessage) const blankMsgError = new Error() - beforeEach(() => { + beforeEach(function () { undefinedErrorName.name = undefined blankErrorName.name = '' }) - it('tests error with message', () => { + it('tests error with message', function () { assert.equal(cleanErrorStack(testError), 'Error: Test Message') }) - it('tests error with undefined name', () => { + it('tests error with undefined name', function () { assert.equal(cleanErrorStack(undefinedErrorName).toString(), 'Error: Test Message') }) - it('tests error with blank name', () => { + it('tests error with blank name', function () { assert.equal(cleanErrorStack(blankErrorName).toString(), 'Test Message') }) - it('tests error with blank message', () => { + it('tests error with blank message', function () { assert.equal(cleanErrorStack(blankMsgError), 'Error') }) diff --git a/test/unit/app/controllers/balance-controller.spec.js b/test/unit/app/controllers/balance-controller.spec.js index b591e585d..b912b23de 100644 --- a/test/unit/app/controllers/balance-controller.spec.js +++ b/test/unit/app/controllers/balance-controller.spec.js @@ -17,7 +17,7 @@ const accounts = { }, } -describe('Balance Controller', () => { +describe('Balance Controller', function () { let balanceController @@ -29,7 +29,7 @@ describe('Balance Controller', () => { } }) - beforeEach(() => { + beforeEach(function () { balanceController = new BalanceController({ address: TEST_ADDRESS, accountTracker: new AccountTracker({ diff --git a/test/unit/app/controllers/cached-balances-test.js b/test/unit/app/controllers/cached-balances-test.js index 7353cb448..272334dc5 100644 --- a/test/unit/app/controllers/cached-balances-test.js +++ b/test/unit/app/controllers/cached-balances-test.js @@ -2,9 +2,9 @@ import assert from 'assert' import sinon from 'sinon' import CachedBalancesController from '../../../../app/scripts/controllers/cached-balances' -describe('CachedBalancesController', () => { - describe('updateCachedBalances', () => { - it('should update the cached balances', async () => { +describe('CachedBalancesController', function () { + describe('updateCachedBalances', function () { + it('should update the cached balances', async function () { const controller = new CachedBalancesController({ getNetwork: () => Promise.resolve(17), accountTracker: { @@ -27,8 +27,8 @@ describe('CachedBalancesController', () => { }) }) - describe('_generateBalancesToCache', () => { - it('should generate updated account balances where the current network was updated', () => { + describe('_generateBalancesToCache', function () { + it('should generate updated account balances where the current network was updated', function () { const controller = new CachedBalancesController({ accountTracker: { store: { @@ -71,7 +71,7 @@ describe('CachedBalancesController', () => { }) }) - it('should generate updated account balances where the a new network was selected', () => { + it('should generate updated account balances where the a new network was selected', function () { const controller = new CachedBalancesController({ accountTracker: { store: { @@ -109,8 +109,8 @@ describe('CachedBalancesController', () => { }) }) - describe('_registerUpdates', () => { - it('should subscribe to the account tracker with the updateCachedBalances method', async () => { + describe('_registerUpdates', function () { + it('should subscribe to the account tracker with the updateCachedBalances method', async function () { const subscribeSpy = sinon.spy() const controller = new CachedBalancesController({ getNetwork: () => Promise.resolve(17), diff --git a/test/unit/app/controllers/detect-tokens-test.js b/test/unit/app/controllers/detect-tokens-test.js index 7975c90a7..43bc132ff 100644 --- a/test/unit/app/controllers/detect-tokens-test.js +++ b/test/unit/app/controllers/detect-tokens-test.js @@ -6,7 +6,7 @@ import DetectTokensController from '../../../../app/scripts/controllers/detect-t import NetworkController from '../../../../app/scripts/controllers/network/network' import PreferencesController from '../../../../app/scripts/controllers/preferences' -describe('DetectTokensController', () => { +describe('DetectTokensController', function () { const sandbox = sinon.createSandbox() let clock, keyringMemStore, network, preferences, controller @@ -16,7 +16,7 @@ describe('DetectTokensController', () => { getAccounts: noop, } - beforeEach(async () => { + beforeEach(async function () { nock('https://api.infura.io') @@ -32,19 +32,19 @@ describe('DetectTokensController', () => { }) - after(() => { + after(function () { sandbox.restore() nock.cleanAll() }) - it('should poll on correct interval', async () => { + it('should poll on correct interval', async function () { const stub = sinon.stub(global, 'setInterval') new DetectTokensController({ interval: 1337 }) // eslint-disable-line no-new assert.strictEqual(stub.getCall(0).args[1], 1337) stub.restore() }) - it('should be called on every polling period', async () => { + it('should be called on every polling period', async function () { clock = sandbox.useFakeTimers() const network = new NetworkController() network.initializeProvider(networkControllerProviderConfig) @@ -66,7 +66,7 @@ describe('DetectTokensController', () => { sandbox.assert.calledThrice(stub) }) - it('should not check tokens while in test network', async () => { + it('should not check tokens while in test network', async function () { controller.isOpen = true controller.isUnlocked = true @@ -78,7 +78,7 @@ describe('DetectTokensController', () => { sandbox.assert.notCalled(stub) }) - it('should only check and add tokens while in main network', async () => { + it('should only check and add tokens while in main network', async function () { const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore }) controller.isOpen = true controller.isUnlocked = true @@ -94,7 +94,7 @@ describe('DetectTokensController', () => { { address: '0xbc86727e770de68b1060c91f6bb6945c73e10388', decimals: 18, symbol: 'XNK' }]) }) - it('should not detect same token while in main network', async () => { + it('should not detect same token while in main network', async function () { preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8) const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore }) controller.isOpen = true @@ -111,7 +111,7 @@ describe('DetectTokensController', () => { { address: '0xbc86727e770de68b1060c91f6bb6945c73e10388', decimals: 18, symbol: 'XNK' }]) }) - it('should trigger detect new tokens when change address', async () => { + it('should trigger detect new tokens when change address', async function () { controller.isOpen = true controller.isUnlocked = true const stub = sandbox.stub(controller, 'detectNewTokens') @@ -119,7 +119,7 @@ describe('DetectTokensController', () => { sandbox.assert.called(stub) }) - it('should trigger detect new tokens when submit password', async () => { + it('should trigger detect new tokens when submit password', async function () { controller.isOpen = true controller.selectedAddress = '0x0' const stub = sandbox.stub(controller, 'detectNewTokens') @@ -127,7 +127,7 @@ describe('DetectTokensController', () => { sandbox.assert.called(stub) }) - it('should not trigger detect new tokens when not open or not unlocked', async () => { + it('should not trigger detect new tokens when not open or not unlocked', async function () { controller.isOpen = true controller.isUnlocked = false const stub = sandbox.stub(controller, 'detectTokenBalance') diff --git a/test/unit/app/controllers/ens-controller-test.js b/test/unit/app/controllers/ens-controller-test.js index 020fe6fda..1176b8b42 100644 --- a/test/unit/app/controllers/ens-controller-test.js +++ b/test/unit/app/controllers/ens-controller-test.js @@ -9,7 +9,7 @@ const ZERO_X_ERROR_ADDRESS = '0x' describe('EnsController', function () { describe('#constructor', function () { - it('should construct the controller given a provider and a network', async () => { + it('should construct the controller given a provider and a network', async function () { const provider = new HttpProvider('https://ropsten.infura.io') const currentNetworkId = '3' const networkStore = new ObservableStore(currentNetworkId) @@ -21,7 +21,7 @@ describe('EnsController', function () { assert.ok(ens._ens) }) - it('should construct the controller given an existing ENS instance', async () => { + it('should construct the controller given an existing ENS instance', async function () { const networkStore = { subscribe: sinon.spy(), } @@ -35,7 +35,7 @@ describe('EnsController', function () { }) describe('#reverseResolveName', function () { - it('should resolve to an ENS name', async () => { + it('should resolve to an ENS name', async function () { const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5' const networkStore = { subscribe: sinon.spy(), @@ -52,7 +52,7 @@ describe('EnsController', function () { assert.equal(name, 'peaksignal.eth') }) - it('should only resolve an ENS name once', async () => { + it('should only resolve an ENS name once', async function () { const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5' const reverse = sinon.stub().withArgs(address).returns('peaksignal.eth') const lookup = sinon.stub().withArgs('peaksignal.eth').returns(address) @@ -73,7 +73,7 @@ describe('EnsController', function () { assert.ok(reverse.calledOnce) }) - it('should fail if the name is registered to a different address than the reverse-resolved', async () => { + it('should fail if the name is registered to a different address than the reverse-resolved', async function () { const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5' const networkStore = { subscribe: sinon.spy(), @@ -90,7 +90,7 @@ describe('EnsController', function () { assert.strictEqual(name, undefined) }) - it('should throw an error when the lookup resolves to the zero address', async () => { + it('should throw an error when the lookup resolves to the zero address', async function () { const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5' const networkStore = { subscribe: sinon.spy(), @@ -111,7 +111,7 @@ describe('EnsController', function () { } }) - it('should throw an error the lookup resolves to the zero x address', async () => { + it('should throw an error the lookup resolves to the zero x address', async function () { const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5' const networkStore = { subscribe: sinon.spy(), diff --git a/test/unit/app/controllers/incoming-transactions-test.js b/test/unit/app/controllers/incoming-transactions-test.js index d2e12f64b..6b3aeaa29 100644 --- a/test/unit/app/controllers/incoming-transactions-test.js +++ b/test/unit/app/controllers/incoming-transactions-test.js @@ -8,7 +8,7 @@ const IncomingTransactionsController = proxyquire('../../../../app/scripts/contr import { ROPSTEN, RINKEBY, KOVAN, GOERLI, MAINNET } from '../../../../app/scripts/controllers/network/enums' -describe('IncomingTransactionsController', () => { +describe('IncomingTransactionsController', function () { const EMPTY_INIT_STATE = { incomingTransactions: {}, incomingTxLastFetchedBlocksByNetwork: { @@ -71,8 +71,8 @@ describe('IncomingTransactionsController', () => { }, } - describe('constructor', () => { - it('should set up correct store, listeners and properties in the constructor', () => { + describe('constructor', function () { + it('should set up correct store, listeners and properties in the constructor', function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -102,7 +102,7 @@ describe('IncomingTransactionsController', () => { incomingTransactionsController._update.resetHistory() }) - it('should set the store to a provided initial state', () => { + it('should set the store to a provided initial state', function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -114,8 +114,8 @@ describe('IncomingTransactionsController', () => { }) }) - describe('#start', () => { - it('should set up a listener for the latest block', () => { + describe('#start', function () { + it('should set up a listener for the latest block', function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -139,8 +139,8 @@ describe('IncomingTransactionsController', () => { }) }) - describe('_getDataForUpdate', () => { - it('should call fetchAll with the correct params when passed a new block number and the current network has no stored block', async () => { + describe('_getDataForUpdate', function () { + it('should call fetchAll with the correct params when passed a new block number and the current network has no stored block', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -158,7 +158,7 @@ describe('IncomingTransactionsController', () => { ]) }) - it('should call fetchAll with the correct params when passed a new block number but the current network has a stored block', async () => { + it('should call fetchAll with the correct params when passed a new block number but the current network has a stored block', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -176,7 +176,7 @@ describe('IncomingTransactionsController', () => { ]) }) - it('should call fetchAll with the correct params when passed a new network type but no block info exists', async () => { + it('should call fetchAll with the correct params when passed a new network type but no block info exists', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -197,25 +197,7 @@ describe('IncomingTransactionsController', () => { ]) }) - it('should call fetchAll with the correct params when passed a new block number but the current network has a stored block', async () => { - const incomingTransactionsController = new IncomingTransactionsController({ - blockTracker: MOCK_BLOCKTRACKER, - networkController: MOCK_NETWORK_CONTROLLER, - preferencesController: MOCK_PREFERENCES_CONTROLLER, - initState: NON_EMPTY_INIT_STATE_WITH_FAKE_NETWORK_STATE, - }) - incomingTransactionsController._fetchAll = sinon.stub().returns({}) - - await incomingTransactionsController._getDataForUpdate({ address: 'fakeAddress', newBlockNumberDec: 999 }) - - assert(incomingTransactionsController._fetchAll.calledOnce) - - assert.deepEqual(incomingTransactionsController._fetchAll.getCall(0).args, [ - 'fakeAddress', 1111, 'FAKE_NETWORK', - ]) - }) - - it('should return the expected data', async () => { + it('should return the expected data', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -252,7 +234,7 @@ describe('IncomingTransactionsController', () => { }) }) - describe('_updateStateWithNewTxData', () => { + describe('_updateStateWithNewTxData', function () { const MOCK_INPUT_WITHOUT_LASTEST = { newTxs: [{ id: 555, hash: '0xfff' }], currentIncomingTxs: { @@ -275,7 +257,7 @@ describe('IncomingTransactionsController', () => { latestIncomingTxBlockNumber: 444, } - it('should update state with correct blockhash and transactions when passed a truthy latestIncomingTxBlockNumber', async () => { + it('should update state with correct blockhash and transactions when passed a truthy latestIncomingTxBlockNumber', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -300,7 +282,7 @@ describe('IncomingTransactionsController', () => { }) }) - it('should update state with correct blockhash and transactions when passed a falsy latestIncomingTxBlockNumber', async () => { + it('should update state with correct blockhash and transactions when passed a falsy latestIncomingTxBlockNumber', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -326,22 +308,22 @@ describe('IncomingTransactionsController', () => { }) }) - describe('_fetchTxs', () => { + describe('_fetchTxs', function () { const mockFetch = sinon.stub().returns(Promise.resolve({ json: () => Promise.resolve({ someKey: 'someValue' }), })) let tempFetch - beforeEach(() => { + beforeEach(function () { tempFetch = global.fetch global.fetch = mockFetch }) - afterEach(() => { + afterEach(function () { global.fetch = tempFetch mockFetch.resetHistory() }) - it('should call fetch with the expected url when passed an address, block number and supported network', async () => { + it('should call fetch with the expected url when passed an address, block number and supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -355,7 +337,7 @@ describe('IncomingTransactionsController', () => { assert.equal(mockFetch.getCall(0).args[0], `https://api-${ROPSTEN}.etherscan.io/api?module=account&action=txlist&address=0xfakeaddress&tag=latest&page=1&startBlock=789`) }) - it('should call fetch with the expected url when passed an address, block number and MAINNET', async () => { + it('should call fetch with the expected url when passed an address, block number and MAINNET', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -369,7 +351,7 @@ describe('IncomingTransactionsController', () => { assert.equal(mockFetch.getCall(0).args[0], `https://api.etherscan.io/api?module=account&action=txlist&address=0xfakeaddress&tag=latest&page=1&startBlock=789`) }) - it('should call fetch with the expected url when passed an address and supported network, but a falsy block number', async () => { + it('should call fetch with the expected url when passed an address and supported network, but a falsy block number', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -383,7 +365,7 @@ describe('IncomingTransactionsController', () => { assert.equal(mockFetch.getCall(0).args[0], `https://api-${ROPSTEN}.etherscan.io/api?module=account&action=txlist&address=0xfakeaddress&tag=latest&page=1`) }) - it('should not fetch and return an empty object when passed an unsported network', async () => { + it('should not fetch and return an empty object when passed an unsported network', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -397,7 +379,7 @@ describe('IncomingTransactionsController', () => { assert.deepEqual(result, {}) }) - it('should return the results from the fetch call, plus the address and currentNetworkID, when passed an address, block number and supported network', async () => { + it('should return the results from the fetch call, plus the address and currentNetworkID, when passed an address, block number and supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -416,8 +398,8 @@ describe('IncomingTransactionsController', () => { }) }) - describe('_processTxFetchResponse', () => { - it('should return a null block number and empty tx array if status is 0', () => { + describe('_processTxFetchResponse', function () { + it('should return a null block number and empty tx array if status is 0', function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -437,7 +419,7 @@ describe('IncomingTransactionsController', () => { }) }) - it('should return a null block number and empty tx array if the passed result array is empty', () => { + it('should return a null block number and empty tx array if the passed result array is empty', function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -457,7 +439,7 @@ describe('IncomingTransactionsController', () => { }) }) - it('should return the expected block number and tx list when passed data from a successful fetch', () => { + it('should return the expected block number and tx list when passed data from a successful fetch', function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -575,8 +557,8 @@ describe('IncomingTransactionsController', () => { }) }) - describe('_normalizeTxFromEtherscan', () => { - it('should return the expected data when the tx is in error', () => { + describe('_normalizeTxFromEtherscan', function () { + it('should return the expected data when the tx is in error', function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, @@ -616,7 +598,7 @@ describe('IncomingTransactionsController', () => { }) }) - it('should return the expected data when the tx is not in error', () => { + it('should return the expected data when the tx is not in error', function () { const incomingTransactionsController = new IncomingTransactionsController({ blockTracker: MOCK_BLOCKTRACKER, networkController: MOCK_NETWORK_CONTROLLER, diff --git a/test/unit/app/controllers/infura-controller-test.js b/test/unit/app/controllers/infura-controller-test.js index ab3c71e72..1b3af4c06 100644 --- a/test/unit/app/controllers/infura-controller-test.js +++ b/test/unit/app/controllers/infura-controller-test.js @@ -6,18 +6,17 @@ describe('infura-controller', function () { let infuraController, sandbox, networkStatus const response = { 'mainnet': 'degraded', 'ropsten': 'ok', 'kovan': 'ok', 'rinkeby': 'down', 'goerli': 'ok' } - before(async function () { - infuraController = new InfuraController() - sandbox = sinon.createSandbox() - sinon.stub(infuraController, 'checkInfuraNetworkStatus').resolves(response) - networkStatus = await infuraController.checkInfuraNetworkStatus() - }) - - after(function () { - sandbox.restore() - }) - describe('Network status queries', function () { + before(async function () { + infuraController = new InfuraController() + sandbox = sinon.createSandbox() + sinon.stub(infuraController, 'checkInfuraNetworkStatus').resolves(response) + networkStatus = await infuraController.checkInfuraNetworkStatus() + }) + + after(function () { + sandbox.restore() + }) describe('Mainnet', function () { it('should have Mainnet', function () { diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index 5da4750ee..e0d805961 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -110,14 +110,10 @@ describe('MetaMaskController', function () { }) describe('#getAccounts', function () { - - beforeEach(async function () { + it('returns first address when dapp calls web3.eth.getAccounts', async function () { const password = 'a-fake-password' - await metamaskController.createNewVaultAndRestore(password, TEST_SEED) - }) - it('returns first address when dapp calls web3.eth.getAccounts', function () { metamaskController.networkController._baseProviderParams.getAccounts((err, res) => { assert.ifError(err) assert.equal(res.length, 1) @@ -127,12 +123,10 @@ describe('MetaMaskController', function () { }) describe('#importAccountWithStrategy', function () { - const importPrivkey = '4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553' beforeEach(async function () { const password = 'a-fake-password' - await metamaskController.createNewVaultAndRestore(password, TEST_SEED) await metamaskController.importAccountWithStrategy('Private Key', [ importPrivkey ]) }) @@ -148,7 +142,7 @@ describe('MetaMaskController', function () { assert.equal(pubKey, '0xe18035bf8712672935fdb4e5e431b1a0183d2dfc') }) - it('adds private key to keyrings in KeyringController', async function () { + it('adds 1 account', async function () { const keyringAccounts = await metamaskController.keyringController.getAccounts() assert.equal(keyringAccounts[keyringAccounts.length - 1], '0xe18035bf8712672935fdb4e5e431b1a0183d2dfc') }) @@ -180,7 +174,7 @@ describe('MetaMaskController', function () { }) }) - it('gets the address from threebox and creates a new 3box instance', async () => { + it('gets the address from threebox and creates a new 3box instance', async function () { await metamaskController.submitPassword(password) assert(threeBoxSpies.init.calledOnce) assert(threeBoxSpies.turnThreeBoxSyncingOn.calledOnce) @@ -242,7 +236,7 @@ describe('MetaMaskController', function () { assert(metamaskController.keyringController.createNewVaultAndRestore.calledTwice) }) - it('should clear previous identities after vault restoration', async () => { + it('should clear previous identities after vault restoration', async function () { sandbox.stub(metamaskController, 'getBalance') metamaskController.getBalance.callsFake(() => { return Promise.resolve('0x0') @@ -264,7 +258,7 @@ describe('MetaMaskController', function () { }) }) - it('should restore any consecutive accounts with balances', async () => { + it('should restore any consecutive accounts with balances', async function () { sandbox.stub(metamaskController, 'getBalance') metamaskController.getBalance.withArgs(TEST_ADDRESS).callsFake(() => { return Promise.resolve('0x14ced5122ce0a000') @@ -284,8 +278,8 @@ describe('MetaMaskController', function () { }) }) - describe('#getBalance', () => { - it('should return the balance known by accountTracker', async () => { + describe('#getBalance', function () { + it('should return the balance known by accountTracker', async function () { const accounts = {} const balance = '0x14ced5122ce0a000' accounts[TEST_ADDRESS] = { balance: balance } @@ -297,7 +291,7 @@ describe('MetaMaskController', function () { assert.equal(balance, gotten) }) - it('should ask the network for a balance when not known by accountTracker', async () => { + it('should ask the network for a balance when not known by accountTracker', async function () { const accounts = {} const balance = '0x14ced5122ce0a000' const ethQuery = new EthQuery() @@ -314,13 +308,9 @@ describe('MetaMaskController', function () { }) describe('#getApi', function () { - let getApi, state - - beforeEach(function () { - getApi = metamaskController.getApi() - }) - it('getState', function (done) { + let state + const getApi = metamaskController.getApi() getApi.getState((err, res) => { if (err) { done(err) @@ -331,7 +321,6 @@ describe('MetaMaskController', function () { assert.deepEqual(state, metamaskController.getState()) done() }) - }) describe('preferencesController', function () { @@ -549,16 +538,12 @@ describe('MetaMaskController', function () { }) describe('#addNewAccount', function () { - let addNewAccount - - beforeEach(function () { - addNewAccount = metamaskController.addNewAccount() - }) - it('errors when an primary keyring is does not exist', async function () { + const addNewAccount = metamaskController.addNewAccount() + try { await addNewAccount - assert.equal(1 === 0) + assert.fail('should throw') } catch (e) { assert.equal(e.message, 'MetamaskController - No HD Key Tree found') } @@ -586,8 +571,7 @@ describe('MetaMaskController', function () { }) describe('#resetAccount', function () { - - beforeEach(function () { + it('wipes transactions from only the correct network id and with the selected address', async function () { const selectedAddressStub = sinon.stub(metamaskController.preferencesController, 'getSelectedAddress') const getNetworkstub = sinon.stub(metamaskController.txController.txStateManager, 'getNetwork') @@ -600,9 +584,7 @@ describe('MetaMaskController', function () { createTxMeta({ id: 2, status: 'rejected', metamaskNetworkId: 32 }), createTxMeta({ 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) }) @@ -656,14 +638,14 @@ describe('MetaMaskController', function () { }) - describe('#newUnsignedMessage', () => { + describe('#newUnsignedMessage', function () { let msgParams, metamaskMsgs, messages, msgId const address = '0xc42edfcc21ed14dda456aa0756c153f7985d8813' const data = '0x43727970746f6b697474696573' - beforeEach(async () => { + beforeEach(async function () { sandbox.stub(metamaskController, 'getBalance') metamaskController.getBalance.callsFake(() => { return Promise.resolve('0x0') @@ -746,7 +728,7 @@ describe('MetaMaskController', function () { personalMessages[0].msgParams.metamaskId = parseInt(msgId) }) - it('errors with no from in msgParams', async () => { + it('errors with no from in msgParams', async function () { const msgParams = { 'data': data, } @@ -788,23 +770,15 @@ describe('MetaMaskController', function () { }) describe('#setupUntrustedCommunication', function () { - let streamTest - - const phishingMessageSender = { - url: 'http://myethereumwalletntw.com', - tab: {}, - } - - afterEach(function () { - streamTest.end() - }) - - it('sets up phishing stream for untrusted communication ', async () => { + it('sets up phishing stream for untrusted communication ', async function () { + const phishingMessageSender = { + url: 'http://myethereumwalletntw.com', + tab: {}, + } await metamaskController.phishingController.updatePhishingLists() const { promise, resolve } = deferredPromise() - - streamTest = createThoughStream((chunk, _, cb) => { + const streamTest = createThoughStream((chunk, _, cb) => { if (chunk.name !== 'phishing') { return cb() } @@ -812,31 +786,29 @@ describe('MetaMaskController', function () { resolve() cb() }) - metamaskController.setupUntrustedCommunication(streamTest, phishingMessageSender) + metamaskController.setupUntrustedCommunication(streamTest, phishingMessageSender) await promise + streamTest.end() }) }) describe('#setupTrustedCommunication', function () { - let streamTest - - afterEach(function () { - streamTest.end() - }) - - it('sets up controller dnode api for trusted communication', function (done) { + it('sets up controller dnode api for trusted communication', async function () { const messageSender = { url: 'http://mycrypto.com', tab: {}, } - streamTest = createThoughStream((chunk, _, cb) => { + const { promise, resolve } = deferredPromise() + const streamTest = createThoughStream((chunk, _, cb) => { assert.equal(chunk.name, 'controller') + resolve() cb() - done() }) metamaskController.setupTrustedCommunication(streamTest, messageSender) + await promise + streamTest.end() }) }) diff --git a/test/unit/app/controllers/network/network-controller-test.js b/test/unit/app/controllers/network/network-controller-test.js index c360c1bed..239204fed 100644 --- a/test/unit/app/controllers/network/network-controller-test.js +++ b/test/unit/app/controllers/network/network-controller-test.js @@ -3,30 +3,28 @@ import nock from 'nock' import NetworkController from '../../../../../app/scripts/controllers/network' import { getNetworkDisplayName } from '../../../../../app/scripts/controllers/network/util' -describe('# Network Controller', function () { - let networkController - const noop = () => {} - const networkControllerProviderConfig = { - getAccounts: noop, - } +describe('NetworkController', function () { + describe('controller', function () { + let networkController + const noop = () => {} + const networkControllerProviderConfig = { + getAccounts: noop, + } - beforeEach(function () { + beforeEach(function () { + nock('https://rinkeby.infura.io') + .persist() + .post('/metamask') + .reply(200) - nock('https://rinkeby.infura.io') - .persist() - .post('/metamask') - .reply(200) - - networkController = new NetworkController() - - networkController.initializeProvider(networkControllerProviderConfig) - }) + networkController = new NetworkController() + networkController.initializeProvider(networkControllerProviderConfig) + }) - afterEach(function () { - nock.cleanAll() - }) + afterEach(function () { + nock.cleanAll() + }) - describe('network', function () { describe('#provider', function () { it('provider should be updatable without reassignment', function () { networkController.initializeProvider(networkControllerProviderConfig) @@ -64,38 +62,38 @@ describe('# Network Controller', function () { }) }) }) -}) -describe('Network utils', () => { - it('getNetworkDisplayName should return the correct network name', () => { - const tests = [ - { - input: 3, - expected: 'Ropsten', - }, { - input: 4, - expected: 'Rinkeby', - }, { - input: 42, - expected: 'Kovan', - }, { - input: 'ropsten', - expected: 'Ropsten', - }, { - input: 'rinkeby', - expected: 'Rinkeby', - }, { - input: 'kovan', - expected: 'Kovan', - }, { - input: 'mainnet', - expected: 'Main Ethereum Network', - }, { - input: 'goerli', - expected: 'Goerli', - }, - ] + describe('utils', function () { + it('getNetworkDisplayName should return the correct network name', function () { + const tests = [ + { + input: 3, + expected: 'Ropsten', + }, { + input: 4, + expected: 'Rinkeby', + }, { + input: 42, + expected: 'Kovan', + }, { + input: 'ropsten', + expected: 'Ropsten', + }, { + input: 'rinkeby', + expected: 'Rinkeby', + }, { + input: 'kovan', + expected: 'Kovan', + }, { + input: 'mainnet', + expected: 'Main Ethereum Network', + }, { + input: 'goerli', + expected: 'Goerli', + }, + ] - tests.forEach(({ input, expected }) => assert.equal(getNetworkDisplayName(input), expected)) + tests.forEach(({ input, expected }) => assert.equal(getNetworkDisplayName(input), expected)) + }) }) }) diff --git a/test/unit/app/controllers/network/pending-middleware-test.js b/test/unit/app/controllers/network/pending-middleware-test.js index 9fd056266..a339d9b68 100644 --- a/test/unit/app/controllers/network/pending-middleware-test.js +++ b/test/unit/app/controllers/network/pending-middleware-test.js @@ -2,85 +2,77 @@ import assert from 'assert' import { createPendingNonceMiddleware, createPendingTxMiddleware } from '../../../../../app/scripts/controllers/network/middleware/pending' import { txMetaStub } from './stubs' -describe('#createPendingNonceMiddleware', function () { - const getPendingNonce = async () => '0x2' - const address = '0xF231D46dD78806E1DD93442cf33C7671f8538748' - const pendingNonceMiddleware = createPendingNonceMiddleware({ getPendingNonce }) +describe('PendingNonceMiddleware', function () { + describe('#createPendingNonceMiddleware', function () { + const getPendingNonce = async () => '0x2' + const address = '0xF231D46dD78806E1DD93442cf33C7671f8538748' + const pendingNonceMiddleware = createPendingNonceMiddleware({ getPendingNonce }) - it('should call next if not a eth_getTransactionCount request', (done) => { - const req = { method: 'eth_getBlockByNumber' } - const res = {} - pendingNonceMiddleware(req, res, () => done()) - }) - it('should call next if not a "pending" block request', (done) => { - const req = { method: 'eth_getTransactionCount', params: [address] } - const res = {} - pendingNonceMiddleware(req, res, () => done()) - }) - it('should fill the result with a the "pending" nonce', (done) => { - const req = { method: 'eth_getTransactionCount', params: [address, 'pending'] } - const res = {} - pendingNonceMiddleware(req, res, () => { - done(new Error('should not have called next')) - }, () => { - assert(res.result === '0x2') - done() + it('should call next if not a eth_getTransactionCount request', function (done) { + const req = { method: 'eth_getBlockByNumber' } + const res = {} + pendingNonceMiddleware(req, res, () => done()) + }) + it('should call next if not a "pending" block request', function (done) { + const req = { method: 'eth_getTransactionCount', params: [address] } + const res = {} + pendingNonceMiddleware(req, res, () => done()) + }) + it('should fill the result with a the "pending" nonce', function (done) { + const req = { method: 'eth_getTransactionCount', params: [address, 'pending'] } + const res = {} + pendingNonceMiddleware(req, res, () => { + done(new Error('should not have called next')) + }, () => { + assert(res.result === '0x2') + done() + }) }) }) -}) -describe('#createPendingTxMiddleware', function () { - let returnUndefined = true - const getPendingTransactionByHash = () => (returnUndefined ? undefined : txMetaStub) - const address = '0xF231D46dD78806E1DD93442cf33C7671f8538748' - const pendingTxMiddleware = createPendingTxMiddleware({ getPendingTransactionByHash }) - const spec = { - 'blockHash': null, - 'blockNumber': null, - 'from': '0xf231d46dd78806e1dd93442cf33c7671f8538748', - 'gas': '0x5208', - 'gasPrice': '0x1e8480', - 'hash': '0x2cc5a25744486f7383edebbf32003e5a66e18135799593d6b5cdd2bb43674f09', - 'input': '0x', - 'nonce': '0x4', - 'to': '0xf231d46dd78806e1dd93442cf33c7671f8538748', - 'transactionIndex': null, - 'value': '0x0', - 'v': '0x2c', - 'r': '0x5f973e540f2d3c2f06d3725a626b75247593cb36477187ae07ecfe0a4db3cf57', - 's': '0x0259b52ee8c58baaa385fb05c3f96116e58de89bcc165cb3bfdfc708672fed8a', - } - it('should call next if not a eth_getTransactionByHash request', (done) => { - const req = { method: 'eth_getBlockByNumber' } - const res = {} - pendingTxMiddleware(req, res, () => done()) - }) + describe('#createPendingTxMiddleware', function () { + let returnUndefined = true + const getPendingTransactionByHash = () => (returnUndefined ? undefined : txMetaStub) + const address = '0xF231D46dD78806E1DD93442cf33C7671f8538748' + const pendingTxMiddleware = createPendingTxMiddleware({ getPendingTransactionByHash }) + const spec = { + 'blockHash': null, + 'blockNumber': null, + 'from': '0xf231d46dd78806e1dd93442cf33c7671f8538748', + 'gas': '0x5208', + 'gasPrice': '0x1e8480', + 'hash': '0x2cc5a25744486f7383edebbf32003e5a66e18135799593d6b5cdd2bb43674f09', + 'input': '0x', + 'nonce': '0x4', + 'to': '0xf231d46dd78806e1dd93442cf33c7671f8538748', + 'transactionIndex': null, + 'value': '0x0', + 'v': '0x2c', + 'r': '0x5f973e540f2d3c2f06d3725a626b75247593cb36477187ae07ecfe0a4db3cf57', + 's': '0x0259b52ee8c58baaa385fb05c3f96116e58de89bcc165cb3bfdfc708672fed8a', + } + it('should call next if not a eth_getTransactionByHash request', function (done) { + const req = { method: 'eth_getBlockByNumber' } + const res = {} + pendingTxMiddleware(req, res, () => done()) + }) - it('should call next if no pending txMeta is in history', (done) => { - const req = { method: 'eth_getTransactionByHash', params: [address] } - const res = {} - pendingTxMiddleware(req, res, () => done()) - }) + it('should call next if no pending txMeta is in history', function (done) { + const req = { method: 'eth_getTransactionByHash', params: [address] } + const res = {} + pendingTxMiddleware(req, res, () => done()) + }) - it('should fill the result with a the "pending" tx the result should match the rpc spec', (done) => { - returnUndefined = false - const req = { method: 'eth_getTransactionByHash', params: [address, 'pending'] } - const res = {} - pendingTxMiddleware(req, res, () => { - done(new Error('should not have called next')) - }, () => { - /* - // uncomment this section for debugging help with non matching keys - const coppy = {...res.result} - Object.keys(spec).forEach((key) => { - console.log(coppy[key], '===', spec[key], coppy[key] === spec[key], key) - delete coppy[key] + it('should fill the result with a the "pending" tx the result should match the rpc spec', function (done) { + returnUndefined = false + const req = { method: 'eth_getTransactionByHash', params: [address, 'pending'] } + const res = {} + pendingTxMiddleware(req, res, () => { + done(new Error('should not have called next')) + }, () => { + assert.deepStrictEqual(res.result, spec, new Error('result does not match the spec object')) + done() }) - console.log(coppy) - */ - assert.deepStrictEqual(res.result, spec, new Error('result does not match the spec object')) - done() }) }) - }) diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js index b1a886ddb..d81453e37 100644 --- a/test/unit/app/controllers/preferences-controller-test.js +++ b/test/unit/app/controllers/preferences-controller-test.js @@ -8,7 +8,7 @@ describe('preferences controller', function () { let preferencesController let network - beforeEach(() => { + beforeEach(function () { network = { providerStore: new ObservableStore({ type: 'mainnet' }) } preferencesController = new PreferencesController({ network }) }) @@ -346,7 +346,7 @@ describe('preferences controller', function () { let stubNext, stubEnd, stubHandleWatchAssetERC20, asy, req, res const sandbox = sinon.createSandbox() - beforeEach(() => { + beforeEach(function () { req = { params: {} } res = {} asy = { next: () => {}, end: () => {} } @@ -354,7 +354,7 @@ describe('preferences controller', function () { stubEnd = sandbox.stub(asy, 'end').returns(0) stubHandleWatchAssetERC20 = sandbox.stub(preferencesController, '_handleWatchAssetERC20') }) - after(() => { + after(function () { sandbox.restore() }) @@ -404,10 +404,10 @@ describe('preferences controller', function () { let req const sandbox = sinon.createSandbox() - beforeEach(() => { + beforeEach(function () { req = { params: { type: 'ERC20' } } }) - after(() => { + after(function () { sandbox.restore() }) @@ -514,7 +514,7 @@ describe('preferences controller', function () { }) describe('#updateRpc', function () { - it('should update the rpcDetails properly', () => { + it('should update the rpcDetails properly', function () { preferencesController.store.updateState({ frequentRpcListDetail: [{}, { rpcUrl: 'test' }, {}] }) preferencesController.updateRpc({ rpcUrl: 'test', chainId: 1 }) preferencesController.updateRpc({ rpcUrl: 'test/1', chainId: 1 }) diff --git a/test/unit/app/controllers/token-rates-controller.js b/test/unit/app/controllers/token-rates-controller.js index 1174bc364..edcc74120 100644 --- a/test/unit/app/controllers/token-rates-controller.js +++ b/test/unit/app/controllers/token-rates-controller.js @@ -3,15 +3,15 @@ import sinon from 'sinon' import TokenRatesController from '../../../../app/scripts/controllers/token-rates' import ObservableStore from 'obs-store' -describe('TokenRatesController', () => { - it('should listen for preferences store updates', () => { +describe('TokenRatesController', function () { + it('should listen for preferences store updates', function () { const preferences = new ObservableStore({ tokens: [] }) const controller = new TokenRatesController({ preferences }) preferences.putState({ tokens: ['foo'] }) assert.deepEqual(controller._tokens, ['foo']) }) - it('should poll on correct interval', async () => { + it('should poll on correct interval', async function () { const stub = sinon.stub(global, 'setInterval') new TokenRatesController({ interval: 1337 }) // eslint-disable-line no-new assert.strictEqual(stub.getCall(0).args[1], 1337) diff --git a/test/unit/app/controllers/transactions/pending-tx-test.js b/test/unit/app/controllers/transactions/pending-tx-test.js index 10fe9ae43..3dfd852c2 100644 --- a/test/unit/app/controllers/transactions/pending-tx-test.js +++ b/test/unit/app/controllers/transactions/pending-tx-test.js @@ -56,17 +56,7 @@ describe('PendingTransactionTracker', function () { }) describe('_checkPendingTx state management', function () { - let stub - - afterEach(function () { - if (stub) { - stub.restore() - } - }) - it('should emit dropped if another tx with the same nonce succeeds', async function () { - - // SETUP const txGen = new MockTxGen() txGen.generate({ @@ -83,21 +73,19 @@ describe('PendingTransactionTracker', function () { status: 'submitted', }, { count: 1, fromNonce: '0x01' })[0] - stub = sinon.stub(pendingTxTracker, 'getCompletedTransactions') + const stub = sinon.stub(pendingTxTracker, 'getCompletedTransactions') .returns(txGen.txs) - // THE EXPECTATION const spy = sinon.spy() pendingTxTracker.on('tx:dropped', (txId) => { assert.equal(txId, pending.id, 'should fail the pending tx') spy(txId) }) - // THE METHOD await pendingTxTracker._checkPendingTx(pending) - // THE ASSERTION assert.ok(spy.calledWith(pending.id), 'tx dropped should be emitted') + stub.restore() }) }) @@ -161,7 +149,7 @@ describe('PendingTransactionTracker', function () { }) describe('#_checkPendingTxs', function () { - beforeEach(function () { + it('should warp all txMeta\'s in #updatePendingTxs', function (done) { const txMeta2 = txMeta3 = txMeta txMeta2.id = 2 txMeta3.id = 3 @@ -171,9 +159,6 @@ describe('PendingTransactionTracker', function () { }) return tx }) - }) - - it('should warp all txMeta\'s in #updatePendingTxs', function (done) { pendingTxTracker.getPendingTransactions = () => txList pendingTxTracker._checkPendingTx = (tx) => { tx.resolve(tx) @@ -263,7 +248,7 @@ describe('PendingTransactionTracker', function () { const mockFirstRetryBlockNumber = '0x1' let txMetaToTestExponentialBackoff, enoughBalance - beforeEach(() => { + beforeEach(function () { pendingTxTracker.getBalance = (address) => { assert.equal(address, txMeta.txParams.from, 'Should pass the address') return enoughBalance @@ -280,7 +265,7 @@ describe('PendingTransactionTracker', function () { }) }) - afterEach(() => { + afterEach(function () { pendingTxTracker.publishTransaction.restore() }) @@ -327,7 +312,7 @@ describe('PendingTransactionTracker', function () { assert.equal(pendingTxTracker.publishTransaction.callCount, 1, 'Should call publish transaction') }) - it('should call opts.approveTransaction with the id if the tx is not signed', async () => { + it('should call opts.approveTransaction with the id if the tx is not signed', async function () { const stubTx = { id: 40, } @@ -340,7 +325,7 @@ describe('PendingTransactionTracker', function () { }) }) - describe('#_checkIftxWasDropped', () => { + describe('#_checkIftxWasDropped', function () { const txMeta = { id: 1, hash: '0x0593ee121b92e10d63150ad08b4b8f9c7857d1bd160195ee648fb9a0f8d00eeb', @@ -352,7 +337,7 @@ describe('PendingTransactionTracker', function () { }, rawTx: '0xf86c808504a817c800827b0d940c62bb85faa3311a998d3aba8098c1235c564966880de0b6b3a7640000802aa08ff665feb887a25d4099e40e11f0fef93ee9608f404bd3f853dd9e84ed3317a6a02ec9d3d1d6e176d4d2593dd760e74ccac753e6a0ea0d00cc9789d0d7ff1f471d', } - it('should return false when the nonce is the suggested network nonce', (done) => { + it('should return false when the nonce is the suggested network nonce', function (done) { providerResultStub['eth_getTransactionCount'] = '0x01' providerResultStub['eth_getTransactionReceipt'] = {} pendingTxTracker._checkIftxWasDropped(txMeta, {}).then((dropped) => { diff --git a/test/unit/app/controllers/transactions/recipient-blacklist-checker-test.js b/test/unit/app/controllers/transactions/recipient-blacklist-checker-test.js index b3fe8e8ae..c89dd3179 100644 --- a/test/unit/app/controllers/transactions/recipient-blacklist-checker-test.js +++ b/test/unit/app/controllers/transactions/recipient-blacklist-checker-test.js @@ -4,22 +4,21 @@ import { ROPSTEN_CODE, RINKEBY_CODE, KOVAN_CODE, GOERLI_CODE } from '../../../.. import KeyringController from 'eth-keyring-controller' describe('Recipient Blacklist Checker', function () { + describe('#checkAccount', function () { + let publicAccounts - let publicAccounts - - before(async function () { - const damnedMnemonic = 'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat' - const keyringController = new KeyringController({}) - const Keyring = keyringController.getKeyringClassForType('HD Key Tree') - const opts = { - mnemonic: damnedMnemonic, - numberOfAccounts: 10, - } - const keyring = new Keyring(opts) - publicAccounts = await keyring.getAccounts() - }) + before(async function () { + const damnedMnemonic = 'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat' + const keyringController = new KeyringController({}) + const Keyring = keyringController.getKeyringClassForType('HD Key Tree') + const opts = { + mnemonic: damnedMnemonic, + numberOfAccounts: 10, + } + const keyring = new Keyring(opts) + publicAccounts = await keyring.getAccounts() + }) - describe('#checkAccount', function () { it('does not fail on test networks', function () { let callCount = 0 const networks = [ROPSTEN_CODE, RINKEBY_CODE, KOVAN_CODE, GOERLI_CODE] diff --git a/test/unit/app/controllers/transactions/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js index 8aab61122..a17ba8fca 100644 --- a/test/unit/app/controllers/transactions/tx-controller-test.js +++ b/test/unit/app/controllers/transactions/tx-controller-test.js @@ -87,9 +87,8 @@ describe('Transaction Controller', function () { }) describe('#getConfirmedTransactions', function () { - let address - beforeEach(function () { - address = '0xc684832530fcbddae4b4230a47e991ddcec2831d' + it('should return the number of confirmed txs', function () { + const address = '0xc684832530fcbddae4b4230a47e991ddcec2831d' const txParams = { 'from': address, 'to': '0xc684832530fcbddae4b4230a47e991ddcec2831d', @@ -105,9 +104,6 @@ describe('Transaction Controller', function () { { id: 7, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, { id: 8, status: 'failed', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, ]) - }) - - it('should return the number of confirmed txs', function () { assert.equal(txController.nonceTracker.getConfirmedTransactions(address).length, 3) }) }) @@ -132,11 +128,11 @@ describe('Transaction Controller', function () { txController.emit('newUnapprovedTx', txMeta) return Promise.resolve(txController.txStateManager.addTx(txMeta)) }) + }) - afterEach(function () { - txController.txStateManager._saveTxList([]) - stub.restore() - }) + afterEach(function () { + txController.txStateManager._saveTxList([]) + stub.restore() }) it('should resolve when finished and status is submitted and resolve with the hash', function (done) { @@ -226,11 +222,11 @@ describe('Transaction Controller', function () { it('should fail if the from address isn\'t the selected address', function (done) { txController.addUnapprovedTransaction({ from: '0x0d1d4e623D10F9FBA5Db95830F7d3839406C6AF2' }) - .then(function () { + .then(() => { assert.fail('transaction should not have been added') done() }) - .catch(function () { + .catch(() => { assert.ok('pass') done() }) @@ -259,7 +255,7 @@ describe('Transaction Controller', function () { }) describe('#addTxGasDefaults', function () { - it('should add the tx defaults if their are none', async () => { + it('should add the tx defaults if their are none', async function () { const txMeta = { txParams: { from: '0xc684832530fcbddae4b4230a47e991ddcec2831d', @@ -307,11 +303,9 @@ describe('Transaction Controller', function () { }) describe('#approveTransaction', function () { - let txMeta, originalValue - - beforeEach(function () { - originalValue = '0x01' - txMeta = { + it('does not overwrite set values', function (done) { + const originalValue = '0x01' + const txMeta = { id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, @@ -321,10 +315,6 @@ describe('Transaction Controller', function () { gasPrice: originalValue, }, } - }) - - - it('does not overwrite set values', function (done) { this.timeout(15000) const wrongValue = '0x05' @@ -366,9 +356,8 @@ describe('Transaction Controller', function () { }) describe('#updateAndApproveTransaction', function () { - let txMeta - beforeEach(() => { - txMeta = { + it('should update and approve transactions', async function () { + const txMeta = { id: 1, status: 'unapproved', txParams: { @@ -380,8 +369,6 @@ describe('Transaction Controller', function () { }, metamaskNetworkId: currentNetworkId, } - }) - it('should update and approve transactions', async () => { txController.txStateManager.addTx(txMeta) const approvalPromise = txController.updateAndApproveTransaction(txMeta) const tx = txController.txStateManager.getTx(1) @@ -398,7 +385,7 @@ describe('Transaction Controller', function () { }) describe('#cancelTransaction', function () { - beforeEach(function () { + it('should emit a status change to rejected', function (done) { txController.txStateManager._saveTxList([ { id: 0, status: 'unapproved', txParams: {}, metamaskNetworkId: currentNetworkId, history: [{}] }, { id: 1, status: 'rejected', txParams: {}, metamaskNetworkId: currentNetworkId, history: [{}] }, @@ -408,9 +395,7 @@ describe('Transaction Controller', function () { { id: 5, status: 'confirmed', txParams: {}, metamaskNetworkId: currentNetworkId, history: [{}] }, { id: 6, status: 'failed', txParams: {}, metamaskNetworkId: currentNetworkId, history: [{}] }, ]) - }) - it('should emit a status change to rejected', function (done) { txController.once('tx:status-update', (txId, status) => { try { assert.equal(status, 'rejected', 'status should e rejected') @@ -426,13 +411,13 @@ describe('Transaction Controller', function () { }) - describe('#createSpeedUpTransaction', () => { + describe('#createSpeedUpTransaction', function () { let addTxSpy let approveTransactionSpy let txParams let expectedTxParams - beforeEach(() => { + beforeEach(function () { addTxSpy = sinon.spy(txController, 'addTx') approveTransactionSpy = sinon.spy(txController, 'approveTransaction') @@ -450,12 +435,12 @@ describe('Transaction Controller', function () { expectedTxParams = Object.assign({}, txParams, { gasPrice: '0xb' }) }) - afterEach(() => { + afterEach(function () { addTxSpy.restore() approveTransactionSpy.restore() }) - it('should call this.addTx and this.approveTransaction with the expected args', async () => { + it('should call this.addTx and this.approveTransaction with the expected args', async function () { await txController.createSpeedUpTransaction(1) assert.equal(addTxSpy.callCount, 1) @@ -469,7 +454,7 @@ describe('Transaction Controller', function () { }) }) - it('should call this.approveTransaction with the id of the returned tx', async () => { + it('should call this.approveTransaction with the id of the returned tx', async function () { const result = await txController.createSpeedUpTransaction(1) assert.equal(approveTransactionSpy.callCount, 1) @@ -477,7 +462,7 @@ describe('Transaction Controller', function () { assert.equal(result.id, approveTransactionArg) }) - it('should return the expected txMeta', async () => { + it('should return the expected txMeta', async function () { const result = await txController.createSpeedUpTransaction(1) assert.deepEqual(result.txParams, expectedTxParams) @@ -686,7 +671,7 @@ describe('Transaction Controller', function () { }) describe('#getPendingTransactions', function () { - beforeEach(function () { + it('should show only submitted and approved transactions as pending transasction', function () { txController.txStateManager._saveTxList([ { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} }, { id: 2, status: 'rejected', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] }, @@ -696,8 +681,7 @@ describe('Transaction Controller', function () { { id: 6, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] }, { id: 7, status: 'failed', metamaskNetworkId: currentNetworkId, txParams: {}, history: [{}] }, ]) - }) - it('should show only submitted and approved transactions as pending transasction', function () { + assert(txController.pendingTxTracker.getPendingTransactions().length, 2) const states = txController.pendingTxTracker.getPendingTransactions().map(tx => tx.status) assert(states.includes('approved'), 'includes approved') diff --git a/test/unit/app/controllers/transactions/tx-state-manager-test.js b/test/unit/app/controllers/transactions/tx-state-manager-test.js index 1dbeddce0..49ede17e9 100644 --- a/test/unit/app/controllers/transactions/tx-state-manager-test.js +++ b/test/unit/app/controllers/transactions/tx-state-manager-test.js @@ -30,7 +30,7 @@ describe('TransactionStateManager', function () { assert.equal(result[0].status, 'signed') }) - it('should emit a signed event to signal the exciton of callback', (done) => { + it('should emit a signed event to signal the exciton of callback', function (done) { const tx = { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} } const noop = function () { assert(true, 'event listener has been triggered and noop executed') @@ -53,7 +53,7 @@ describe('TransactionStateManager', function () { assert.equal(result.length, 0) }) - it('should emit a rejected event to signal the exciton of callback', (done) => { + it('should emit a rejected event to signal the exciton of callback', function (done) { const tx = { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} } txStateManager.addTx(tx) const noop = () => { @@ -303,7 +303,6 @@ describe('TransactionStateManager', function () { assert.equal(txStateManager.getFilteredTxList(filterParams).length, 5, `getFilteredTxList - ${JSON.stringify(filterParams)}`) filterParams = { status: (status) => status !== 'confirmed' } assert.equal(txStateManager.getFilteredTxList(filterParams).length, 5, `getFilteredTxList - ${JSON.stringify(filterParams)}`) - }) }) @@ -346,18 +345,17 @@ describe('TransactionStateManager', function () { assert.equal(txsFromCurrentNetworkAndAddress.length, 0) assert.equal(txFromOtherNetworks.length, 2) - }) }) describe('#_removeTx', function () { - it('should remove the transaction from the storage', () => { + it('should remove the transaction from the storage', function () { txStateManager._saveTxList([ { id: 1 } ]) txStateManager._removeTx(1) assert(!txStateManager.getFullTxList().length, 'txList should be empty') }) - it('should only remove the transaction with ID 1 from the storage', () => { + it('should only remove the transaction with ID 1 from the storage', function () { txStateManager._saveTxList([ { id: 1 }, { id: 2 } ]) txStateManager._removeTx(1) assert.equal(txStateManager.getFullTxList()[0].id, 2, 'txList should have a id of 2') diff --git a/test/unit/app/controllers/transactions/tx-utils-test.js b/test/unit/app/controllers/transactions/tx-utils-test.js index 88cfd8d14..2b87ea93c 100644 --- a/test/unit/app/controllers/transactions/tx-utils-test.js +++ b/test/unit/app/controllers/transactions/tx-utils-test.js @@ -25,8 +25,8 @@ describe('txUtils', function () { }) }) - describe('#normalizeTxParams', () => { - it('should normalize txParams', () => { + describe('#normalizeTxParams', function () { + it('should normalize txParams', function () { const txParams = { chainId: '0x1', from: 'a7df1beDBF813f57096dF77FCd515f0B3900e402', @@ -50,7 +50,7 @@ describe('txUtils', function () { }) }) - describe('#validateRecipient', () => { + describe('#validateRecipient', function () { it('removes recipient for txParams with 0x when contract data is provided', function () { const zeroRecipientandDataTxParams = { from: '0x1678a085c290ebd122dc42cba69373b5953b831d', @@ -73,7 +73,7 @@ describe('txUtils', function () { }) - describe('#validateFrom', () => { + describe('#validateFrom', function () { it('should error when from is not a hex string', function () { // where from is undefined diff --git a/test/unit/app/fetch-with-timeout.test.js b/test/unit/app/fetch-with-timeout.test.js index ac0d50212..52b79c338 100644 --- a/test/unit/app/fetch-with-timeout.test.js +++ b/test/unit/app/fetch-with-timeout.test.js @@ -3,8 +3,8 @@ import nock from 'nock' import fetchWithTimeout from '../../../app/scripts/lib/fetch-with-timeout' -describe('fetchWithTimeout', () => { - it('fetches a url', async () => { +describe('fetchWithTimeout', function () { + it('fetches a url', async function () { nock('https://api.infura.io') .get('/money') .reply(200, '{"hodl": false}') @@ -16,7 +16,7 @@ describe('fetchWithTimeout', () => { }) }) - it('throws when the request hits a custom timeout', async () => { + it('throws when the request hits a custom timeout', async function () { nock('https://api.infura.io') .get('/moon') .delay(2000) @@ -34,7 +34,7 @@ describe('fetchWithTimeout', () => { } }) - it('should abort the request when the custom timeout is hit', async () => { + it('should abort the request when the custom timeout is hit', async function () { nock('https://api.infura.io') .get('/moon') .delay(2000) diff --git a/test/unit/app/nodeify-test.js b/test/unit/app/nodeify-test.js index c241a7985..04d56956e 100644 --- a/test/unit/app/nodeify-test.js +++ b/test/unit/app/nodeify-test.js @@ -12,7 +12,7 @@ describe('nodeify', function () { it('should retain original context', function (done) { const nodified = nodeify(obj.promiseFunc, obj) - nodified('baz', function (err, res) { + nodified('baz', (err, res) => { if (!err) { assert.equal(res, 'barbaz') done() @@ -36,7 +36,7 @@ describe('nodeify', function () { const nodified = nodeify(async () => { throw new Error('boom!') }, obj) - process.prependOnceListener('uncaughtException', function (err) { + process.prependOnceListener('uncaughtException', (err) => { assert.ok(err, 'got expected error') assert.ok(err.message.includes('boom!'), 'got expected error message') done() diff --git a/test/unit/app/pending-balance-test.js b/test/unit/app/pending-balance-test.js index 32201671c..2fe405eb5 100644 --- a/test/unit/app/pending-balance-test.js +++ b/test/unit/app/pending-balance-test.js @@ -45,19 +45,15 @@ describe('PendingBalanceCalculator', function () { }) describe('if you have no pending txs and one ether', function () { - - beforeEach(function () { - balanceCalculator = generateBalanceCalcWith([], etherBn) - }) - it('returns the network balance', async function () { + balanceCalculator = generateBalanceCalcWith([], etherBn) const result = await balanceCalculator.getBalance() assert.equal(result, ether, `gave ${result} needed ${ether}`) }) }) describe('if you have a one ether pending tx and one ether', function () { - beforeEach(function () { + it('returns the subtracted result', async function () { const txGen = new MockTxGen() pendingTxs = txGen.generate({ status: 'submitted', @@ -69,14 +65,11 @@ describe('PendingBalanceCalculator', function () { }, { count: 1 }) balanceCalculator = generateBalanceCalcWith(pendingTxs, etherBn) - }) - it('returns the subtracted result', async function () { const result = await balanceCalculator.getBalance() assert.equal(result, '0x0', `gave ${result} needed '0x0'`) return true }) - }) }) diff --git a/test/unit/app/typed-message-manager.spec.js b/test/unit/app/typed-message-manager.spec.js index f408530a6..c69e407a3 100644 --- a/test/unit/app/typed-message-manager.spec.js +++ b/test/unit/app/typed-message-manager.spec.js @@ -3,14 +3,14 @@ import sinon from 'sinon' import NetworkController from '../../../app/scripts/controllers/network/index' import TypedMessageManager from '../../../app/scripts/lib/typed-message-manager' -describe('Typed Message Manager', () => { +describe('Typed Message Manager', function () { let typedMessageManager, msgParamsV1, msgParamsV3, typedMsgs, messages, msgId, numberMsgId const address = '0xc42edfcc21ed14dda456aa0756c153f7985d8813' const networkController = new NetworkController() sinon.stub(networkController, 'getNetworkState').returns('1') - beforeEach(() => { + beforeEach(function () { typedMessageManager = new TypedMessageManager({ networkController, }) @@ -72,7 +72,7 @@ describe('Typed Message Manager', () => { numberMsgId = parseInt(msgId) }) - it('supports version 1 of signedTypedData', () => { + it('supports version 1 of signedTypedData', function () { typedMessageManager.addUnapprovedMessage(msgParamsV1, null, 'V1') assert.equal(messages[messages.length - 1].msgParams.data, msgParamsV1.data) }) diff --git a/test/unit/app/util-test.js b/test/unit/app/util-test.js index 97029e797..a15b8ce72 100644 --- a/test/unit/app/util-test.js +++ b/test/unit/app/util-test.js @@ -8,82 +8,84 @@ import { ENVIRONMENT_TYPE_BACKGROUND, } from '../../../app/scripts/lib/enums' -describe('getEnvironmentType', function () { - it('should return popup type', function () { - const environmentType = getEnvironmentType('http://extension-id/popup.html') - assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP) - }) +describe('app utils', function () { + describe('getEnvironmentType', function () { + it('should return popup type', function () { + const environmentType = getEnvironmentType('http://extension-id/popup.html') + assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP) + }) - it('should return notification type', function () { - const environmentType = getEnvironmentType('http://extension-id/notification.html') - assert.equal(environmentType, ENVIRONMENT_TYPE_NOTIFICATION) - }) + it('should return notification type', function () { + const environmentType = getEnvironmentType('http://extension-id/notification.html') + assert.equal(environmentType, ENVIRONMENT_TYPE_NOTIFICATION) + }) - it('should return fullscreen type for home.html', function () { - const environmentType = getEnvironmentType('http://extension-id/home.html') - assert.equal(environmentType, ENVIRONMENT_TYPE_FULLSCREEN) - }) + it('should return fullscreen type for home.html', function () { + const environmentType = getEnvironmentType('http://extension-id/home.html') + assert.equal(environmentType, ENVIRONMENT_TYPE_FULLSCREEN) + }) - it('should return fullscreen type for phishing.html', function () { - const environmentType = getEnvironmentType('http://extension-id/phishing.html') - assert.equal(environmentType, ENVIRONMENT_TYPE_FULLSCREEN) - }) + it('should return fullscreen type for phishing.html', function () { + const environmentType = getEnvironmentType('http://extension-id/phishing.html') + assert.equal(environmentType, ENVIRONMENT_TYPE_FULLSCREEN) + }) - it('should return background type', function () { - const environmentType = getEnvironmentType('http://extension-id/_generated_background_page.html') - assert.equal(environmentType, ENVIRONMENT_TYPE_BACKGROUND) - }) + it('should return background type', function () { + const environmentType = getEnvironmentType('http://extension-id/_generated_background_page.html') + assert.equal(environmentType, ENVIRONMENT_TYPE_BACKGROUND) + }) - it('should return the correct type for a URL with a hash fragment', function () { - const environmentType = getEnvironmentType('http://extension-id/popup.html#hash') - assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP) - }) + it('should return the correct type for a URL with a hash fragment', function () { + const environmentType = getEnvironmentType('http://extension-id/popup.html#hash') + assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP) + }) - it('should return the correct type for a URL with query parameters', function () { - const environmentType = getEnvironmentType('http://extension-id/popup.html?param=foo') - assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP) - }) + it('should return the correct type for a URL with query parameters', function () { + const environmentType = getEnvironmentType('http://extension-id/popup.html?param=foo') + assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP) + }) - it('should return the correct type for a URL with query parameters and a hash fragment', function () { - const environmentType = getEnvironmentType('http://extension-id/popup.html?param=foo#hash') - assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP) + it('should return the correct type for a URL with query parameters and a hash fragment', function () { + const environmentType = getEnvironmentType('http://extension-id/popup.html?param=foo#hash') + assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP) + }) }) -}) -describe('SufficientBalance', function () { - it('returns true if max tx cost is equal to balance.', function () { - const tx = { - 'value': '0x1', - 'gas': '0x2', - 'gasPrice': '0x3', - } - const balance = '0x8' + describe('SufficientBalance', function () { + it('returns true if max tx cost is equal to balance.', function () { + const tx = { + 'value': '0x1', + 'gas': '0x2', + 'gasPrice': '0x3', + } + const balance = '0x8' - const result = sufficientBalance(tx, balance) - assert.ok(result, 'sufficient balance found.') - }) + const result = sufficientBalance(tx, balance) + assert.ok(result, 'sufficient balance found.') + }) - it('returns true if max tx cost is less than balance.', function () { - const tx = { - 'value': '0x1', - 'gas': '0x2', - 'gasPrice': '0x3', - } - const balance = '0x9' + it('returns true if max tx cost is less than balance.', function () { + const tx = { + 'value': '0x1', + 'gas': '0x2', + 'gasPrice': '0x3', + } + const balance = '0x9' - const result = sufficientBalance(tx, balance) - assert.ok(result, 'sufficient balance found.') - }) + const result = sufficientBalance(tx, balance) + assert.ok(result, 'sufficient balance found.') + }) - it('returns false if max tx cost is more than balance.', function () { - const tx = { - 'value': '0x1', - 'gas': '0x2', - 'gasPrice': '0x3', - } - const balance = '0x6' + it('returns false if max tx cost is more than balance.', function () { + const tx = { + 'value': '0x1', + 'gas': '0x2', + 'gasPrice': '0x3', + } + const balance = '0x6' - const result = sufficientBalance(tx, balance) - assert.ok(!result, 'insufficient balance found.') + const result = sufficientBalance(tx, balance) + assert.ok(!result, 'insufficient balance found.') + }) }) }) diff --git a/test/unit/migrations/021-test.js b/test/unit/migrations/021-test.js index a6e0a3833..bc18d6cfe 100644 --- a/test/unit/migrations/021-test.js +++ b/test/unit/migrations/021-test.js @@ -2,8 +2,8 @@ import assert from 'assert' import wallet2 from '../../lib/migrations/002.json' import migration21 from '../../../app/scripts/migrations/021' -describe('wallet2 is migrated successfully with out the BlacklistController', () => { - it('should delete BlacklistController key', (done) => { +describe('wallet2 is migrated successfully with out the BlacklistController', function () { + it('should delete BlacklistController key', function (done) { migration21.migrate(wallet2) .then((migratedData) => { assert.equal(migratedData.meta.version, 21) diff --git a/test/unit/migrations/022-test.js b/test/unit/migrations/022-test.js index 7df47c1c5..8f33d62e2 100644 --- a/test/unit/migrations/022-test.js +++ b/test/unit/migrations/022-test.js @@ -15,8 +15,8 @@ const storage = { }, } -describe('storage is migrated successfully where transactions that are submitted have submittedTimes', () => { - it('should add submittedTime key on the txMeta if appropriate', (done) => { +describe('storage is migrated successfully where transactions that are submitted have submittedTimes', function () { + it('should add submittedTime key on the txMeta if appropriate', function (done) { migration22.migrate(storage) .then((migratedData) => { const [txMeta1, txMeta2, txMeta3] = migratedData.data.TransactionController.transactions diff --git a/test/unit/migrations/023-test.js b/test/unit/migrations/023-test.js index a1091f434..6b9d4de3f 100644 --- a/test/unit/migrations/023-test.js +++ b/test/unit/migrations/023-test.js @@ -57,8 +57,8 @@ while (transactions20.length < 20) { storage.data.TransactionController.transactions = transactions -describe('storage is migrated successfully and the proper transactions are remove from state', () => { - it('should remove transactions that are unneeded', (done) => { +describe('storage is migrated successfully and the proper transactions are remove from state', function () { + it('should remove transactions that are unneeded', function (done) { migration23.migrate(storage) .then((migratedData) => { let leftoverNonDeletableTxCount = 0 @@ -74,7 +74,7 @@ describe('storage is migrated successfully and the proper transactions are remov }).catch(done) }) - it('should not remove any transactions because 40 is the expectable limit', (done) => { + it('should not remove any transactions because 40 is the expectable limit', function (done) { storage.meta.version = 22 storage.data.TransactionController.transactions = transactions40 migration23.migrate(storage) @@ -86,7 +86,7 @@ describe('storage is migrated successfully and the proper transactions are remov }).catch(done) }) - it('should not remove any transactions because 20 txs is under the expectable limit', (done) => { + it('should not remove any transactions because 20 txs is under the expectable limit', function (done) { storage.meta.version = 22 storage.data.TransactionController.transactions = transactions20 migration23.migrate(storage) diff --git a/test/unit/migrations/024-test.js b/test/unit/migrations/024-test.js index c5536f894..1aa050b73 100644 --- a/test/unit/migrations/024-test.js +++ b/test/unit/migrations/024-test.js @@ -27,8 +27,8 @@ while (transactions.length <= 10) { storage.data.TransactionController.transactions = transactions -describe('storage is migrated successfully and the txParams.from are lowercase', () => { - it('should lowercase the from for unapproved txs', (done) => { +describe('storage is migrated successfully and the txParams.from are lowercase', function () { + it('should lowercase the from for unapproved txs', function (done) { migration24.migrate(storage) .then((migratedData) => { const migratedTransactions = migratedData.data.TransactionController.transactions @@ -43,7 +43,7 @@ describe('storage is migrated successfully and the txParams.from are lowercase', }).catch(done) }) - it('should migrate first time state', (done) => { + it('should migrate first time state', function (done) { migration24.migrate(firstTimeState) .then((migratedData) => { assert.equal(migratedData.meta.version, 24) diff --git a/test/unit/migrations/025-test.js b/test/unit/migrations/025-test.js index 4710f96c3..6224eef5a 100644 --- a/test/unit/migrations/025-test.js +++ b/test/unit/migrations/025-test.js @@ -28,8 +28,8 @@ while (transactions.length <= 10) { storage.data.TransactionController.transactions = transactions -describe('storage is migrated successfully and the txParams.from are lowercase', () => { - it('should lowercase the from for unapproved txs', (done) => { +describe('storage is migrated successfully and the txParams.from are lowercase', function () { + it('should lowercase the from for unapproved txs', function (done) { migration25.migrate(storage) .then((migratedData) => { const migratedTransactions = migratedData.data.TransactionController.transactions @@ -45,7 +45,7 @@ describe('storage is migrated successfully and the txParams.from are lowercase', }).catch(done) }) - it('should migrate first time state', (done) => { + it('should migrate first time state', function (done) { migration25.migrate(firstTimeState) .then((migratedData) => { assert.equal(migratedData.meta.version, 25) diff --git a/test/unit/migrations/026-test.js b/test/unit/migrations/026-test.js index d60d64a5d..cb64346dd 100644 --- a/test/unit/migrations/026-test.js +++ b/test/unit/migrations/026-test.js @@ -14,8 +14,8 @@ const oldStorage = { }, } -describe('migration #26', () => { - it('should move the identities from KeyringController', (done) => { +describe('migration #26', function () { + it('should move the identities from KeyringController', function (done) { migration26.migrate(oldStorage) .then((newStorage) => { const identities = newStorage.data.PreferencesController.identities @@ -29,7 +29,7 @@ describe('migration #26', () => { .catch(done) }) - it('should successfully migrate first time state', (done) => { + it('should successfully migrate first time state', function (done) { migration26.migrate({ meta: {}, data: require('../../../app/scripts/first-time-state'), diff --git a/test/unit/migrations/027-test.js b/test/unit/migrations/027-test.js index b1f6037fc..c8b947dcf 100644 --- a/test/unit/migrations/027-test.js +++ b/test/unit/migrations/027-test.js @@ -23,8 +23,8 @@ while (transactions.length < 9) { oldStorage.data.TransactionController.transactions = transactions -describe('migration #27', () => { - it('should remove rejected transactions', (done) => { +describe('migration #27', function () { + it('should remove rejected transactions', function (done) { migration27.migrate(oldStorage) .then((newStorage) => { const newTransactions = newStorage.data.TransactionController.transactions @@ -39,7 +39,7 @@ describe('migration #27', () => { .catch(done) }) - it('should successfully migrate first time state', (done) => { + it('should successfully migrate first time state', function (done) { migration27.migrate({ meta: {}, data: require('../../../app/scripts/first-time-state'), diff --git a/test/unit/migrations/028-test.js b/test/unit/migrations/028-test.js index b67c7faad..1207b2734 100644 --- a/test/unit/migrations/028-test.js +++ b/test/unit/migrations/028-test.js @@ -14,8 +14,8 @@ const oldStorage = { }, } -describe('migration #28', () => { - it('should add corresponding tokens to accountTokens', (done) => { +describe('migration #28', function () { + it('should add corresponding tokens to accountTokens', function (done) { migration28.migrate(oldStorage) .then((newStorage) => { const newTokens = newStorage.data.PreferencesController.tokens @@ -33,7 +33,7 @@ describe('migration #28', () => { .catch(done) }) - it('should successfully migrate first time state', (done) => { + it('should successfully migrate first time state', function (done) { migration28.migrate({ meta: {}, data: require('../../../app/scripts/first-time-state'), diff --git a/test/unit/migrations/029-test.js b/test/unit/migrations/029-test.js index 20b814904..b47bd1b6c 100644 --- a/test/unit/migrations/029-test.js +++ b/test/unit/migrations/029-test.js @@ -17,8 +17,8 @@ const storage = { }, } -describe('storage is migrated successfully where transactions that are submitted have submittedTimes', () => { - it('should auto fail transactions more than 12 hours old', (done) => { +describe('storage is migrated successfully where transactions that are submitted have submittedTimes', function () { + it('should auto fail transactions more than 12 hours old', function (done) { migration29.migrate(storage) .then((migratedData) => { const txs = migratedData.data.TransactionController.transactions diff --git a/test/unit/migrations/030-test.js b/test/unit/migrations/030-test.js index 62771bb1e..f575e4bcb 100644 --- a/test/unit/migrations/030-test.js +++ b/test/unit/migrations/030-test.js @@ -23,8 +23,8 @@ const storage = { }, } -describe('storage is migrated successfully', () => { - it('should work', (done) => { +describe('storage is migrated successfully', function () { + it('should work', function (done) { migrationTemplate.migrate(storage) .then((migratedData) => { assert.equal(migratedData.meta.version, 30) diff --git a/test/unit/migrations/031-test.js b/test/unit/migrations/031-test.js index 9492d96e6..8b040aed9 100644 --- a/test/unit/migrations/031-test.js +++ b/test/unit/migrations/031-test.js @@ -1,8 +1,8 @@ import assert from 'assert' import migration31 from '../../../app/scripts/migrations/031' -describe('migration #31', () => { - it('should set completedOnboarding to true if vault exists', done => { +describe('migration #31', function () { + it('should set completedOnboarding to true if vault exists', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -31,7 +31,7 @@ describe('migration #31', () => { .catch(done) }) - it('should set completedOnboarding to false if vault does not exist', done => { + it('should set completedOnboarding to false if vault does not exist', function (done) { const oldStorage = { 'meta': {}, 'data': { diff --git a/test/unit/migrations/033-test.js b/test/unit/migrations/033-test.js index 4166aa914..3e6065724 100644 --- a/test/unit/migrations/033-test.js +++ b/test/unit/migrations/033-test.js @@ -1,7 +1,7 @@ import assert from 'assert' import migration33 from '../../../app/scripts/migrations/033' -describe('Migration to delete notice controller', () => { +describe('Migration to delete notice controller', function () { const oldStorage = { 'meta': {}, 'data': { @@ -31,7 +31,7 @@ describe('Migration to delete notice controller', () => { }, } - it('removes notice controller from state', () => { + it('removes notice controller from state', function () { migration33.migrate(oldStorage) .then(newStorage => { assert.equal(newStorage.data.NoticeController, undefined) diff --git a/test/unit/migrations/034-test.js b/test/unit/migrations/034-test.js index 81de620fe..64af34b2e 100644 --- a/test/unit/migrations/034-test.js +++ b/test/unit/migrations/034-test.js @@ -1,8 +1,8 @@ import assert from 'assert' import migration34 from '../../../app/scripts/migrations/034' -describe('migration #34', () => { - it('should update the version metadata', (done) => { +describe('migration #34', function () { + it('should update the version metadata', function (done) { const oldStorage = { 'meta': { 'version': 33, @@ -20,7 +20,7 @@ describe('migration #34', () => { .catch(done) }) - it('should set migratedPrivacyMode & privacyMode if featureFlags.privacyMode was false', (done) => { + it('should set migratedPrivacyMode & privacyMode if featureFlags.privacyMode was false', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -45,7 +45,7 @@ describe('migration #34', () => { .catch(done) }) - it('should NOT change any state if migratedPrivacyMode is already set to true', (done) => { + it('should NOT change any state if migratedPrivacyMode is already set to true', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -66,7 +66,7 @@ describe('migration #34', () => { .catch(done) }) - it('should NOT change any state if migratedPrivacyMode is already set to false', (done) => { + it('should NOT change any state if migratedPrivacyMode is already set to false', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -87,7 +87,7 @@ describe('migration #34', () => { .catch(done) }) - it('should NOT change any state if PreferencesController is missing', (done) => { + it('should NOT change any state if PreferencesController is missing', function (done) { const oldStorage = { 'meta': {}, 'data': {}, @@ -101,7 +101,7 @@ describe('migration #34', () => { .catch(done) }) - it('should NOT change any state if featureFlags.privacyMode is already true', (done) => { + it('should NOT change any state if featureFlags.privacyMode is already true', function (done) { const oldStorage = { 'meta': {}, 'data': { diff --git a/test/unit/migrations/035-test.js b/test/unit/migrations/035-test.js index c0e062ed1..c6708bb99 100644 --- a/test/unit/migrations/035-test.js +++ b/test/unit/migrations/035-test.js @@ -1,8 +1,8 @@ import assert from 'assert' import migration35 from '../../../app/scripts/migrations/035' -describe('migration #35', () => { - it('should update the version metadata', (done) => { +describe('migration #35', function () { + it('should update the version metadata', function (done) { const oldStorage = { meta: { version: 34, @@ -20,7 +20,7 @@ describe('migration #35', () => { .catch(done) }) - it('should delete seedWords', (done) => { + it('should delete seedWords', function (done) { const oldStorage = { meta: {}, data: { @@ -38,7 +38,7 @@ describe('migration #35', () => { .catch(done) }) - it('should delete falsy seedWords', (done) => { + it('should delete falsy seedWords', function (done) { const oldStorage = { meta: {}, data: { @@ -56,7 +56,7 @@ describe('migration #35', () => { .catch(done) }) - it('should leave state without seedWords unchanged', (done) => { + it('should leave state without seedWords unchanged', function (done) { const oldStorage = { meta: {}, data: { diff --git a/test/unit/migrations/036-test.js b/test/unit/migrations/036-test.js index d4a58e14c..e1666e612 100644 --- a/test/unit/migrations/036-test.js +++ b/test/unit/migrations/036-test.js @@ -1,8 +1,8 @@ import assert from 'assert' import migration36 from '../../../app/scripts/migrations/036' -describe('migration #36', () => { - it('should update the version metadata', (done) => { +describe('migration #36', function () { + it('should update the version metadata', function (done) { const oldStorage = { 'meta': { 'version': 35, @@ -20,7 +20,7 @@ describe('migration #36', () => { .catch(done) }) - it('should remove privacyMode if featureFlags.privacyMode was false', (done) => { + it('should remove privacyMode if featureFlags.privacyMode was false', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -43,7 +43,7 @@ describe('migration #36', () => { .catch(done) }) - it('should remove privacyMode if featureFlags.privacyMode was true', (done) => { + it('should remove privacyMode if featureFlags.privacyMode was true', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -66,7 +66,7 @@ describe('migration #36', () => { .catch(done) }) - it('should NOT change any state if privacyMode does not exist', (done) => { + it('should NOT change any state if privacyMode does not exist', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -86,7 +86,7 @@ describe('migration #36', () => { .catch(done) }) - it('should NOT change any state if PreferencesController is missing', (done) => { + it('should NOT change any state if PreferencesController is missing', function (done) { const oldStorage = { 'meta': {}, 'data': {}, @@ -100,7 +100,7 @@ describe('migration #36', () => { .catch(done) }) - it('should NOT change any state if featureFlags is missing', (done) => { + it('should NOT change any state if featureFlags is missing', function (done) { const oldStorage = { 'meta': {}, 'data': { diff --git a/test/unit/migrations/037-test.js b/test/unit/migrations/037-test.js index 48580ece5..f67f8eb3f 100644 --- a/test/unit/migrations/037-test.js +++ b/test/unit/migrations/037-test.js @@ -1,8 +1,8 @@ import assert from 'assert' import migration37 from '../../../app/scripts/migrations/037' -describe('migration #37', () => { - it('should update the version metadata', (done) => { +describe('migration #37', function () { + it('should update the version metadata', function (done) { const oldStorage = { 'meta': { 'version': 36, @@ -20,7 +20,7 @@ describe('migration #37', () => { .catch(done) }) - it('should transform old state to new format', (done) => { + it('should transform old state to new format', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -84,7 +84,7 @@ describe('migration #37', () => { .catch(done) }) - it('ens validation test', (done) => { + it('ens validation test', function (done) { const oldStorage = { 'meta': {}, 'data': { diff --git a/test/unit/migrations/038-test.js b/test/unit/migrations/038-test.js index f34c8c024..c1625938d 100644 --- a/test/unit/migrations/038-test.js +++ b/test/unit/migrations/038-test.js @@ -1,8 +1,8 @@ import assert from 'assert' import migration38 from '../../../app/scripts/migrations/038' -describe('migration #38', () => { - it('should update the version metadata', (done) => { +describe('migration #38', function () { + it('should update the version metadata', function (done) { const oldStorage = { 'meta': { 'version': 37, @@ -20,7 +20,7 @@ describe('migration #38', () => { .catch(done) }) - it('should add a fullScreenVsPopup property set to either "control" or "fullScreen"', (done) => { + it('should add a fullScreenVsPopup property set to either "control" or "fullScreen"', function (done) { const oldStorage = { 'meta': {}, 'data': {}, @@ -34,7 +34,7 @@ describe('migration #38', () => { .catch(done) }) - it('should leave the fullScreenVsPopup property unchanged if it exists', (done) => { + it('should leave the fullScreenVsPopup property unchanged if it exists', function (done) { const oldStorage = { 'meta': {}, 'data': { diff --git a/test/unit/migrations/039-test.js b/test/unit/migrations/039-test.js index e9935e0e7..400a7a3ae 100644 --- a/test/unit/migrations/039-test.js +++ b/test/unit/migrations/039-test.js @@ -1,8 +1,8 @@ import assert from 'assert' import migration39 from '../../../app/scripts/migrations/039' -describe('migration #39', () => { - it('should update the version metadata', (done) => { +describe('migration #39', function () { + it('should update the version metadata', function (done) { const oldStorage = { 'meta': { 'version': 38, @@ -20,7 +20,7 @@ describe('migration #39', () => { .catch(done) }) - it('should update old DAI token symbol to SAI in tokens', (done) => { + it('should update old DAI token symbol to SAI in tokens', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -64,7 +64,7 @@ describe('migration #39', () => { .catch(done) }) - it('should update old DAI token symbol to SAI in accountTokens', (done) => { + it('should update old DAI token symbol to SAI in accountTokens', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -152,7 +152,7 @@ describe('migration #39', () => { .catch(done) }) - it('should NOT change any state if accountTokens is not an object', (done) => { + it('should NOT change any state if accountTokens is not an object', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -170,7 +170,7 @@ describe('migration #39', () => { .catch(done) }) - it('should NOT change any state if accountTokens is an object with invalid values', (done) => { + it('should NOT change any state if accountTokens is an object with invalid values', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -206,7 +206,7 @@ describe('migration #39', () => { .catch(done) }) - it('should NOT change any state if accountTokens includes the new DAI token', (done) => { + it('should NOT change any state if accountTokens includes the new DAI token', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -258,7 +258,7 @@ describe('migration #39', () => { .catch(done) }) - it('should NOT change any state if tokens includes the new DAI token', (done) => { + it('should NOT change any state if tokens includes the new DAI token', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -284,7 +284,7 @@ describe('migration #39', () => { .catch(done) }) - it('should NOT change any state if tokens does not include DAI', (done) => { + it('should NOT change any state if tokens does not include DAI', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -310,7 +310,7 @@ describe('migration #39', () => { .catch(done) }) - it('should NOT change any state if a tokens property has invalid entries', (done) => { + it('should NOT change any state if a tokens property has invalid entries', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -333,7 +333,7 @@ describe('migration #39', () => { .catch(done) }) - it('should NOT change any state if a tokens property is not an array', (done) => { + it('should NOT change any state if a tokens property is not an array', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -351,7 +351,7 @@ describe('migration #39', () => { .catch(done) }) - it('should NOT change any state if a tokens property is null', (done) => { + it('should NOT change any state if a tokens property is null', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -369,7 +369,7 @@ describe('migration #39', () => { .catch(done) }) - it('should NOT change any state if a tokens property is missing', (done) => { + it('should NOT change any state if a tokens property is missing', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -386,7 +386,7 @@ describe('migration #39', () => { .catch(done) }) - it('should NOT change any state if a accountTokens property is missing', (done) => { + it('should NOT change any state if a accountTokens property is missing', function (done) { const oldStorage = { 'meta': {}, 'data': { @@ -403,7 +403,7 @@ describe('migration #39', () => { .catch(done) }) - it('should NOT change any state if PreferencesController is missing', (done) => { + it('should NOT change any state if PreferencesController is missing', function (done) { const oldStorage = { 'meta': {}, 'data': {}, diff --git a/test/unit/migrations/migrations-test.js b/test/unit/migrations/migrations-test.js index ff55eeeac..29d941edb 100644 --- a/test/unit/migrations/migrations-test.js +++ b/test/unit/migrations/migrations-test.js @@ -19,8 +19,8 @@ let vault5, vault6, vault7, vault8, vault9 // vault10, vault11 const oldTestRpc = 'https://rawtestrpc.metamask.io/' const newTestRpc = 'https://testrpc.metamask.io/' -describe('wallet1 is migrated successfully', () => { - it('should convert providers', () => { +describe('wallet1 is migrated successfully', function () { + it('should convert providers', function () { wallet1.data.config.provider = { type: 'etherscan', rpcTarget: null } return migration2.migrate(wallet1) diff --git a/test/unit/migrations/migrator-test.js b/test/unit/migrations/migrator-test.js index 22485ff8f..959ad60be 100644 --- a/test/unit/migrations/migrator-test.js +++ b/test/unit/migrations/migrator-test.js @@ -40,47 +40,50 @@ const firstTimeState = { meta: { version: 0 }, data, } -describe('liveMigrations require list', () => { - it('should include all the migrations', async () => { - const fileNames = await pify(cb => fs.readdir('./app/scripts/migrations/', cb))() - const migrationNumbers = fileNames.reduce((agg, filename) => { - const name = filename.split('.')[0] - if (/^\d+$/.test(name)) { - agg.push(name) - } - return agg - }, []).map((num) => parseInt(num)) - migrationNumbers.forEach((num) => { - const migration = liveMigrations.find((m) => m.version === num) - assert(migration, `migration should be include in the index missing migration ${num}`) +describe('migrations', function () { + describe('liveMigrations require list', function () { + it('should include all the migrations', async function () { + const fileNames = await pify(cb => fs.readdir('./app/scripts/migrations/', cb))() + const migrationNumbers = fileNames.reduce((agg, filename) => { + const name = filename.split('.')[0] + if (/^\d+$/.test(name)) { + agg.push(name) + } + return agg + }, []).map((num) => parseInt(num)) + + migrationNumbers.forEach((num) => { + const migration = liveMigrations.find((m) => m.version === num) + assert(migration, `migration should be include in the index missing migration ${num}`) + }) }) }) -}) -describe('Migrator', () => { - const migrator = new Migrator({ migrations: stubMigrations }) - it('migratedData version should be version 3', async () => { - const migratedData = await migrator.migrateData(versionedData) - assert.equal(migratedData.meta.version, stubMigrations[2].version) - }) + describe('Migrator', function () { + const migrator = new Migrator({ migrations: stubMigrations }) + it('migratedData version should be version 3', async function () { + const migratedData = await migrator.migrateData(versionedData) + assert.equal(migratedData.meta.version, stubMigrations[2].version) + }) - it('should match the last version in live migrations', async () => { - const migrator = new Migrator({ migrations: liveMigrations }) - const migratedData = await migrator.migrateData(firstTimeState) - const last = liveMigrations.length - 1 - assert.equal(migratedData.meta.version, liveMigrations[last].version) - }) + it('should match the last version in live migrations', async function () { + const migrator = new Migrator({ migrations: liveMigrations }) + const migratedData = await migrator.migrateData(firstTimeState) + const last = liveMigrations.length - 1 + assert.equal(migratedData.meta.version, liveMigrations[last].version) + }) - it('should emit an error', async () => { - const migrator = new Migrator({ - migrations: [{ - version: 1, - async migrate () { - throw new Error('test') - }, - }], + it('should emit an error', async function () { + const migrator = new Migrator({ + migrations: [{ + version: 1, + async migrate () { + throw new Error('test') + }, + }], + }) + await assert.rejects(migrator.migrateData({ meta: { version: 0 } })) }) - await assert.rejects(migrator.migrateData({ meta: { version: 0 } })) }) }) diff --git a/test/unit/migrations/template-test.js b/test/unit/migrations/template-test.js index fd73dbcb8..e08ddf287 100644 --- a/test/unit/migrations/template-test.js +++ b/test/unit/migrations/template-test.js @@ -6,8 +6,8 @@ const storage = { data: {}, } -describe('storage is migrated successfully', () => { - it('should work', (done) => { +describe('storage is migrated successfully', function () { + it('should work', function (done) { migrationTemplate.migrate(storage) .then((migratedData) => { assert.equal(migratedData.meta.version, 0) diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js index f25b71de4..b2d8ba26a 100644 --- a/test/unit/ui/app/actions.spec.js +++ b/test/unit/ui/app/actions.spec.js @@ -19,7 +19,7 @@ const provider = createTestProviderTools({ scaffold: {} }).provider const middleware = [thunk] const mockStore = configureStore(middleware) -describe('Actions', () => { +describe('Actions', function () { const noop = () => {} @@ -31,7 +31,7 @@ describe('Actions', () => { const password = 'a-fake-password' const importPrivkey = '4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553' - beforeEach(async () => { + beforeEach(async function () { metamaskController = new MetaMaskController({ provider, @@ -66,16 +66,16 @@ describe('Actions', () => { global.ethQuery = new EthQuery(provider) }) - describe('#tryUnlockMetamask', () => { + describe('#tryUnlockMetamask', function () { let submitPasswordSpy, verifySeedPhraseSpy - afterEach(() => { + afterEach(function () { submitPasswordSpy.restore() verifySeedPhraseSpy.restore() }) - it('calls submitPassword and verifySeedPhrase', async () => { + it('calls submitPassword and verifySeedPhrase', async function () { const store = mockStore({}) @@ -87,7 +87,7 @@ describe('Actions', () => { assert(verifySeedPhraseSpy.calledOnce) }) - it('errors on submitPassword will fail', async () => { + it('errors on submitPassword will fail', async function () { const store = mockStore({}) @@ -113,7 +113,7 @@ describe('Actions', () => { } }) - it('displays warning error and unlock failed when verifySeed fails', async () => { + it('displays warning error and unlock failed when verifySeed fails', async function () { const store = mockStore({}) const displayWarningError = [ { type: 'DISPLAY_WARNING', value: 'error' } ] const unlockFailedError = [ { type: 'UNLOCK_FAILED', value: 'error' } ] @@ -136,15 +136,15 @@ describe('Actions', () => { }) }) - describe('#createNewVaultAndRestore', () => { + describe('#createNewVaultAndRestore', function () { let createNewVaultAndRestoreSpy - afterEach(() => { + afterEach(function () { createNewVaultAndRestoreSpy.restore() }) - it('restores new vault', async () => { + it('restores new vault', async function () { const store = mockStore({}) @@ -158,7 +158,7 @@ describe('Actions', () => { } }) - it('errors when callback in createNewVaultAndRestore throws', async () => { + it('errors when callback in createNewVaultAndRestore throws', async function () { const store = mockStore({}) const expectedActions = [ @@ -182,14 +182,14 @@ describe('Actions', () => { }) }) - describe('#requestRevealSeedWords', () => { + describe('#requestRevealSeedWords', function () { let submitPasswordSpy - afterEach(() => { + afterEach(function () { submitPasswordSpy.restore() }) - it('calls submitPassword in background', async () => { + it('calls submitPassword in background', async function () { const store = mockStore() submitPasswordSpy = sinon.spy(background, 'verifySeedPhrase') @@ -198,7 +198,7 @@ describe('Actions', () => { assert(submitPasswordSpy.calledOnce) }) - it('displays warning error message then callback in background errors', async () => { + it('displays warning error message then callback in background errors', async function () { const store = mockStore() const expectedActions = [ @@ -222,14 +222,14 @@ describe('Actions', () => { }) }) - describe('#removeAccount', () => { + describe('#removeAccount', function () { let removeAccountSpy - afterEach(() => { + afterEach(function () { removeAccountSpy.restore() }) - it('calls removeAccount in background and expect actions to show account', async () => { + it('calls removeAccount in background and expect actions to show account', async function () { const store = mockStore(devState) const expectedActions = [ @@ -249,7 +249,7 @@ describe('Actions', () => { assert.deepEqual(actionTypes, expectedActions) }) - it('displays warning error message when removeAccount callback errors', async () => { + it('displays warning error message when removeAccount callback errors', async function () { const store = mockStore() const expectedActions = [ @@ -276,18 +276,18 @@ describe('Actions', () => { }) }) - describe('#addNewKeyring', () => { + describe('#addNewKeyring', function () { let addNewKeyringSpy - beforeEach(() => { + beforeEach(function () { addNewKeyringSpy = sinon.stub(background, 'addNewKeyring') }) - afterEach(() => { + afterEach(function () { addNewKeyringSpy.restore() }) - it('calls addNewKeyring', () => { + it('calls addNewKeyring', function () { const privateKey = 'c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3' const store = mockStore() @@ -295,7 +295,7 @@ describe('Actions', () => { assert(addNewKeyringSpy.calledOnce) }) - it('errors then addNewKeyring in background throws', () => { + it('errors then addNewKeyring in background throws', function () { const store = mockStore() const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -313,15 +313,15 @@ describe('Actions', () => { }) - describe('#resetAccount', () => { + describe('#resetAccount', function () { let resetAccountSpy - afterEach(() => { + afterEach(function () { resetAccountSpy.restore() }) - it('resets account', async () => { + it('resets account', async function () { const store = mockStore() @@ -338,7 +338,7 @@ describe('Actions', () => { assert.deepEqual(store.getActions(), expectedActions) }) - it('throws if resetAccount throws', async () => { + it('throws if resetAccount throws', async function () { const store = mockStore() const expectedActions = [ @@ -361,15 +361,15 @@ describe('Actions', () => { }) }) - describe('#importNewAccount', () => { + describe('#importNewAccount', function () { let importAccountWithStrategySpy - afterEach(() => { + afterEach(function () { importAccountWithStrategySpy.restore() }) - it('calls importAccountWithStrategies in background', () => { + it('calls importAccountWithStrategies in background', function () { const store = mockStore() importAccountWithStrategySpy = sinon.spy(background, 'importAccountWithStrategy') @@ -380,7 +380,7 @@ describe('Actions', () => { assert(importAccountWithStrategySpy.calledOnce) }) - it('displays warning error message when importAccount in background callback errors', async () => { + it('displays warning error message when importAccount in background callback errors', async function () { const store = mockStore() const expectedActions = [ @@ -403,9 +403,9 @@ describe('Actions', () => { }) }) - describe('#addNewAccount', () => { + describe('#addNewAccount', function () { - it('Adds a new account', () => { + it('Adds a new account', function () { const store = mockStore({ metamask: devState }) const addNewAccountSpy = sinon.spy(background, 'addNewAccount') @@ -416,19 +416,19 @@ describe('Actions', () => { }) - describe('#checkHardwareStatus', () => { + describe('#checkHardwareStatus', function () { let checkHardwareStatusSpy - beforeEach(() => { + beforeEach(function () { checkHardwareStatusSpy = sinon.stub(background, 'checkHardwareStatus') }) - afterEach(() => { + afterEach(function () { checkHardwareStatusSpy.restore() }) - it('calls checkHardwareStatus in background', async () => { + it('calls checkHardwareStatus in background', async function () { const store = mockStore() @@ -436,7 +436,7 @@ describe('Actions', () => { assert.equal(checkHardwareStatusSpy.calledOnce, true) }) - it('shows loading indicator and displays error', async () => { + it('shows loading indicator and displays error', async function () { const store = mockStore() const expectedActions = [ @@ -457,19 +457,19 @@ describe('Actions', () => { }) }) - describe('#forgetDevice', () => { + describe('#forgetDevice', function () { let forgetDeviceSpy - beforeEach(() => { + beforeEach(function () { forgetDeviceSpy = sinon.stub(background, 'forgetDevice') }) - afterEach(() => { + afterEach(function () { forgetDeviceSpy.restore() }) - it('calls forgetDevice in background', () => { + it('calls forgetDevice in background', function () { const store = mockStore() @@ -478,7 +478,7 @@ describe('Actions', () => { }) - it('shows loading indicator and displays error', async () => { + it('shows loading indicator and displays error', async function () { const store = mockStore() const expectedActions = [ @@ -499,19 +499,19 @@ describe('Actions', () => { }) }) - describe('#connectHardware', () => { + describe('#connectHardware', function () { let connectHardwareSpy - beforeEach(() => { + beforeEach(function () { connectHardwareSpy = sinon.stub(background, 'connectHardware') }) - afterEach(() => { + afterEach(function () { connectHardwareSpy.restore() }) - it('calls connectHardware in background', () => { + it('calls connectHardware in background', function () { const store = mockStore() @@ -520,7 +520,7 @@ describe('Actions', () => { }) - it('shows loading indicator and displays error', async () => { + it('shows loading indicator and displays error', async function () { const store = mockStore() const expectedActions = [ @@ -541,19 +541,19 @@ describe('Actions', () => { }) }) - describe('#unlockHardwareWalletAccount', () => { + describe('#unlockHardwareWalletAccount', function () { let unlockHardwareWalletAccountSpy - beforeEach(() => { + beforeEach(function () { unlockHardwareWalletAccountSpy = sinon.stub(background, 'unlockHardwareWalletAccount') }) - afterEach(() => { + afterEach(function () { unlockHardwareWalletAccountSpy.restore() }) - it('calls unlockHardwareWalletAccount in background', () => { + it('calls unlockHardwareWalletAccount in background', function () { const store = mockStore() @@ -562,7 +562,7 @@ describe('Actions', () => { }) - it('shows loading indicator and displays error', async () => { + it('shows loading indicator and displays error', async function () { const store = mockStore() const expectedActions = [ @@ -583,26 +583,26 @@ describe('Actions', () => { }) }) - describe('#setCurrentCurrency', () => { + describe('#setCurrentCurrency', function () { let setCurrentCurrencySpy - beforeEach(() => { + beforeEach(function () { setCurrentCurrencySpy = sinon.stub(background, 'setCurrentCurrency') }) - afterEach(() => { + afterEach(function () { setCurrentCurrencySpy.restore() }) - it('calls setCurrentCurrency', () => { + it('calls setCurrentCurrency', function () { const store = mockStore() store.dispatch(actions.setCurrentCurrency('jpy')) assert(setCurrentCurrencySpy.calledOnce) }) - it('throws if setCurrentCurrency throws', () => { + it('throws if setCurrentCurrency throws', function () { const store = mockStore() const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -618,7 +618,7 @@ describe('Actions', () => { }) }) - describe('#signMsg', () => { + describe('#signMsg', function () { let signMessageSpy, metamaskMsgs, msgId, messages @@ -627,7 +627,7 @@ describe('Actions', () => { data: '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0', } - beforeEach(() => { + beforeEach(function () { metamaskController.newUnsignedMessage(msgParams, noop) metamaskMsgs = metamaskController.messageManager.getUnapprovedMsgs() messages = metamaskController.messageManager.messages @@ -635,11 +635,11 @@ describe('Actions', () => { messages[0].msgParams.metamaskId = parseInt(msgId) }) - afterEach(() => { + afterEach(function () { signMessageSpy.restore() }) - it('calls signMsg in background', () => { + it('calls signMsg in background', function () { const store = mockStore({ metamask: {}, }) @@ -650,7 +650,7 @@ describe('Actions', () => { }) - it('errors when signMessage in background throws', async () => { + it('errors when signMessage in background throws', async function () { const store = mockStore({ metamask: {}, }) @@ -676,7 +676,7 @@ describe('Actions', () => { }) - describe('#signPersonalMsg', () => { + describe('#signPersonalMsg', function () { let signPersonalMessageSpy, metamaskMsgs, msgId, personalMessages @@ -685,7 +685,7 @@ describe('Actions', () => { data: '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0', } - beforeEach(() => { + beforeEach(function () { metamaskController.newUnsignedPersonalMessage(msgParams, noop) metamaskMsgs = metamaskController.personalMessageManager.getUnapprovedMsgs() personalMessages = metamaskController.personalMessageManager.messages @@ -693,11 +693,11 @@ describe('Actions', () => { personalMessages[0].msgParams.metamaskId = parseInt(msgId) }) - afterEach(() => { + afterEach(function () { signPersonalMessageSpy.restore() }) - it('calls signPersonalMessage', () => { + it('calls signPersonalMessage', function () { const store = mockStore({ metamask: {}, }) @@ -709,7 +709,7 @@ describe('Actions', () => { }) - it('throws if signPersonalMessage throws', async () => { + it('throws if signPersonalMessage throws', async function () { const store = mockStore() const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -733,7 +733,7 @@ describe('Actions', () => { }) - describe('#signTypedMsg', () => { + describe('#signTypedMsg', function () { let signTypedMsgSpy, messages, typedMessages, msgId const msgParamsV3 = { @@ -776,7 +776,7 @@ describe('Actions', () => { }), } - beforeEach(() => { + beforeEach(function () { metamaskController.newUnsignedTypedMessage(msgParamsV3, null, 'V3') messages = metamaskController.typedMessageManager.getUnapprovedMsgs() typedMessages = metamaskController.typedMessageManager.messages @@ -785,18 +785,18 @@ describe('Actions', () => { signTypedMsgSpy = sinon.stub(background, 'signTypedMessage') }) - afterEach(() => { + afterEach(function () { signTypedMsgSpy.restore() }) - it('calls signTypedMsg in background with no error', () => { + it('calls signTypedMsg in background with no error', function () { const store = mockStore() store.dispatch(actions.signTypedMsg(msgParamsV3)) assert(signTypedMsgSpy.calledOnce) }) - it('returns expected actions with error', async () => { + it('returns expected actions with error', async function () { const store = mockStore() const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -819,26 +819,26 @@ describe('Actions', () => { }) - describe('#signTx', () => { + describe('#signTx', function () { let sendTransactionSpy - beforeEach(() => { + beforeEach(function () { sendTransactionSpy = sinon.stub(global.ethQuery, 'sendTransaction') }) - afterEach(() => { + afterEach(function () { sendTransactionSpy.restore() }) - it('calls sendTransaction in global ethQuery', () => { + it('calls sendTransaction in global ethQuery', function () { const store = mockStore() store.dispatch(actions.signTx()) assert(sendTransactionSpy.calledOnce) }) - it('errors in when sendTransaction throws', () => { + it('errors in when sendTransaction throws', function () { const store = mockStore() const expectedActions = [ { type: 'DISPLAY_WARNING', value: 'error' }, @@ -853,8 +853,8 @@ describe('Actions', () => { }) }) - describe('#updatedGasData', () => { - it('errors when get code does not return', async () => { + describe('#updatedGasData', function () { + it('errors when get code does not return', async function () { const store = mockStore() const expectedActions = [ @@ -878,31 +878,19 @@ describe('Actions', () => { assert.deepEqual(store.getActions(), expectedActions) } }) - }) - - describe('#updatedGasData', () => { - - const stub = sinon.stub().returns('0x') - const mockData = { - gasPrice: '0x3b9aca00', // - blockGasLimit: '0x6ad79a', // 7002010 - selectedAddress: '0x0DCD5D886577d5081B0c52e242Ef29E70Be3E7bc', - to: '0xEC1Adf982415D2Ef5ec55899b9Bfb8BC0f29251B', - value: '0xde0b6b3a7640000', // 1000000000000000000 - } + it('returns default gas limit for basic eth transaction', async function () { + const mockData = { + gasPrice: '0x3b9aca00', + blockGasLimit: '0x6ad79a', // 7002010 + selectedAddress: '0x0DCD5D886577d5081B0c52e242Ef29E70Be3E7bc', + to: '0xEC1Adf982415D2Ef5ec55899b9Bfb8BC0f29251B', + value: '0xde0b6b3a7640000', // 1000000000000000000 + } - beforeEach(() => { global.eth = { - getCode: stub, + getCode: sinon.stub().returns('0x'), } - }) - - afterEach(() => { - stub.reset() - }) - - it('returns default gas limit for basic eth transaction', async () => { const store = mockStore() const expectedActions = [ @@ -915,30 +903,22 @@ describe('Actions', () => { await store.dispatch(actions.updateGasData(mockData)) assert.deepEqual(store.getActions(), expectedActions) + global.eth.getCode.reset() }) }) - describe('#signTokenTx', () => { - - let tokenSpy - - beforeEach(() => { + describe('#signTokenTx', function () { + it('calls eth.contract', function () { global.eth = new Eth(provider) - tokenSpy = sinon.spy(global.eth, 'contract') - }) - - afterEach(() => { - tokenSpy.restore() - }) - - it('calls eth.contract', () => { + const tokenSpy = sinon.spy(global.eth, 'contract') const store = mockStore() store.dispatch(actions.signTokenTx()) assert(tokenSpy.calledOnce) + tokenSpy.restore() }) }) - describe('#updateTransaction', () => { + describe('#updateTransaction', function () { let updateTransactionSpy @@ -952,15 +932,15 @@ describe('Actions', () => { const txData = { id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: txParams } - beforeEach(async () => { + beforeEach(async function () { await metamaskController.txController.txStateManager.addTx(txData) }) - afterEach(() => { + afterEach(function () { updateTransactionSpy.restore() }) - it('updates transaction', async () => { + it('updates transaction', async function () { const store = mockStore() updateTransactionSpy = sinon.spy(background, 'updateTransaction') @@ -972,7 +952,7 @@ describe('Actions', () => { assert.deepEqual(resultantActions[1], { type: 'UPDATE_TRANSACTION_PARAMS', id: txData.id, value: txParams }) }) - it('rejects with error message', async () => { + it('rejects with error message', async function () { const store = mockStore() updateTransactionSpy = sinon.stub(background, 'updateTransaction') @@ -989,14 +969,14 @@ describe('Actions', () => { }) }) - describe('#lockMetamask', () => { + describe('#lockMetamask', function () { let backgroundSetLockedSpy - afterEach(() => { + afterEach(function () { backgroundSetLockedSpy.restore() }) - it('calls setLocked', async () => { + it('calls setLocked', async function () { const store = mockStore() backgroundSetLockedSpy = sinon.spy(background, 'setLocked') @@ -1005,7 +985,7 @@ describe('Actions', () => { assert(backgroundSetLockedSpy.calledOnce) }) - it('returns display warning error with value when setLocked in background callback errors', async () => { + it('returns display warning error with value when setLocked in background callback errors', async function () { const store = mockStore() const expectedActions = [ @@ -1029,25 +1009,25 @@ describe('Actions', () => { }) }) - describe('#setSelectedAddress', () => { + describe('#setSelectedAddress', function () { let setSelectedAddressSpy - beforeEach(() => { + beforeEach(function () { setSelectedAddressSpy = sinon.stub(background, 'setSelectedAddress') }) - afterEach(() => { + afterEach(function () { setSelectedAddressSpy.restore() }) - it('calls setSelectedAddress in background', () => { + it('calls setSelectedAddress in background', function () { const store = mockStore({ metamask: devState }) store.dispatch(actions.setSelectedAddress('0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc')) assert(setSelectedAddressSpy.calledOnce) }) - it('errors when setSelectedAddress throws', () => { + it('errors when setSelectedAddress throws', function () { const store = mockStore() const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -1065,25 +1045,25 @@ describe('Actions', () => { }) }) - describe('#showAccountDetail', () => { + describe('#showAccountDetail', function () { let setSelectedAddressSpy - beforeEach(() => { + beforeEach(function () { setSelectedAddressSpy = sinon.stub(background, 'setSelectedAddress') }) - afterEach(() => { + afterEach(function () { setSelectedAddressSpy.restore() }) - it('#showAccountDetail', () => { + it('#showAccountDetail', function () { const store = mockStore() store.dispatch(actions.showAccountDetail()) assert(setSelectedAddressSpy.calledOnce) }) - it('displays warning if setSelectedAddress throws', () => { + it('displays warning if setSelectedAddress throws', function () { const store = mockStore() const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -1099,25 +1079,25 @@ describe('Actions', () => { }) }) - describe('#addToken', () => { + describe('#addToken', function () { let addTokenSpy - beforeEach(() => { + beforeEach(function () { addTokenSpy = sinon.stub(background, 'addToken') }) - afterEach(() => { + afterEach(function () { addTokenSpy.restore() }) - it('calls addToken in background', async () => { + it('calls addToken in background', async function () { const store = mockStore() store.dispatch(actions.addToken()) assert(addTokenSpy.calledOnce) }) - it('errors when addToken in background throws', async () => { + it('errors when addToken in background throws', async function () { const store = mockStore() const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -1138,25 +1118,25 @@ describe('Actions', () => { }) }) - describe('#removeToken', () => { + describe('#removeToken', function () { let removeTokenSpy - beforeEach(() => { + beforeEach(function () { removeTokenSpy = sinon.stub(background, 'removeToken') }) - afterEach(() => { + afterEach(function () { removeTokenSpy.restore() }) - it('calls removeToken in background', async () => { + it('calls removeToken in background', async function () { const store = mockStore() store.dispatch(await actions.removeToken()) assert(removeTokenSpy.calledOnce) }) - it('errors when removeToken in background fails', async () => { + it('errors when removeToken in background fails', async function () { const store = mockStore() const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -1177,25 +1157,25 @@ describe('Actions', () => { }) }) - describe('#setProviderType', () => { + describe('#setProviderType', function () { let setProviderTypeSpy let store - beforeEach(() => { + beforeEach(function () { store = mockStore({ metamask: { provider: {} } }) setProviderTypeSpy = sinon.stub(background, 'setProviderType') }) - afterEach(() => { + afterEach(function () { setProviderTypeSpy.restore() }) - it('calls setProviderType', () => { + it('calls setProviderType', function () { store.dispatch(actions.setProviderType()) assert(setProviderTypeSpy.calledOnce) }) - it('displays warning when setProviderType throws', () => { + it('displays warning when setProviderType throws', function () { const expectedActions = [ { type: 'DISPLAY_WARNING', value: 'Had a problem changing networks!' }, ] @@ -1210,24 +1190,24 @@ describe('Actions', () => { }) }) - describe('#setRpcTarget', () => { + describe('#setRpcTarget', function () { let setRpcTargetSpy - beforeEach(() => { + beforeEach(function () { setRpcTargetSpy = sinon.stub(background, 'setCustomRpc') }) - afterEach(() => { + afterEach(function () { setRpcTargetSpy.restore() }) - it('calls setRpcTarget', () => { + it('calls setRpcTarget', function () { const store = mockStore() store.dispatch(actions.setRpcTarget('http://localhost:8545')) assert(setRpcTargetSpy.calledOnce) }) - it('displays warning when setRpcTarget throws', () => { + it('displays warning when setRpcTarget throws', function () { const store = mockStore() const expectedActions = [ { type: 'DISPLAY_WARNING', value: 'Had a problem changing networks!' }, @@ -1242,33 +1222,25 @@ describe('Actions', () => { }) }) - describe('#addToAddressBook', () => { - let addToAddressBookSpy - - beforeEach(() => { - addToAddressBookSpy = sinon.stub(background, 'setAddressBook') - }) - - afterEach(() => { - addToAddressBookSpy.restore() - }) - - it('calls setAddressBook', () => { + describe('#addToAddressBook', function () { + it('calls setAddressBook', function () { + const addToAddressBookSpy = sinon.stub(background, 'setAddressBook') const store = mockStore({ metamask: devState }) store.dispatch(actions.addToAddressBook('test')) assert(addToAddressBookSpy.calledOnce) + addToAddressBookSpy.restore() }) }) - describe('#exportAccount', () => { + describe('#exportAccount', function () { let submitPasswordSpy, exportAccountSpy - afterEach(() => { + afterEach(function () { submitPasswordSpy.restore() exportAccountSpy.restore() }) - it('returns expected actions for successful action', async () => { + it('returns expected actions for successful action', async function () { const store = mockStore(devState) const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -1285,7 +1257,7 @@ describe('Actions', () => { assert.deepEqual(store.getActions(), expectedActions) }) - it('returns action errors when first func callback errors', async () => { + it('returns action errors when first func callback errors', async function () { const store = mockStore(devState) const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -1306,7 +1278,7 @@ describe('Actions', () => { } }) - it('returns action errors when second func callback errors', async () => { + it('returns action errors when second func callback errors', async function () { const store = mockStore(devState) const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -1328,22 +1300,17 @@ describe('Actions', () => { }) }) - describe('#setAccountLabel', () => { - let setAccountLabelSpy - - beforeEach(() => { - setAccountLabelSpy = sinon.stub(background, 'setAccountLabel') - }) - - it('calls setAccountLabel', () => { + describe('#setAccountLabel', function () { + it('calls setAccountLabel', function () { + const setAccountLabelSpy = sinon.stub(background, 'setAccountLabel') const store = mockStore() store.dispatch(actions.setAccountLabel('0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', 'test')) assert(setAccountLabelSpy.calledOnce) }) }) - describe('#pairUpdate', () => { - beforeEach(() => { + describe('#pairUpdate', function () { + it('calls expected actions', function () { nock('https://shapeshift.io') .defaultReplyHeaders({ 'access-control-allow-origin': '*' }) .get('/marketinfo/btc_eth') @@ -1353,9 +1320,7 @@ describe('Actions', () => { .defaultReplyHeaders({ 'access-control-allow-origin': '*' }) .get('/coins') .reply(200) - }) - it('calls expected actions', () => { const store = mockStore() // issue with dispatch action in callback not showing const expectedActions = [ @@ -1368,25 +1333,25 @@ describe('Actions', () => { }) }) - describe('#setFeatureFlag', () => { + describe('#setFeatureFlag', function () { let setFeatureFlagSpy - beforeEach(() => { + beforeEach(function () { setFeatureFlagSpy = sinon.stub(background, 'setFeatureFlag') }) - afterEach(() => { + afterEach(function () { setFeatureFlagSpy.restore() }) - it('calls setFeatureFlag in the background', () => { + it('calls setFeatureFlag in the background', function () { const store = mockStore() store.dispatch(actions.setFeatureFlag()) assert(setFeatureFlagSpy.calledOnce) }) - it('errors when setFeatureFlag in background throws', async () => { + it('errors when setFeatureFlag in background throws', async function () { const store = mockStore() const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -1407,33 +1372,25 @@ describe('Actions', () => { }) }) - describe('#setCompletedOnboarding', () => { - let completeOnboardingSpy - - beforeEach(() => { - completeOnboardingSpy = sinon.stub(background, 'completeOnboarding') + describe('#setCompletedOnboarding', function () { + it('completes onboarding', async function () { + const completeOnboardingSpy = sinon.stub(background, 'completeOnboarding') completeOnboardingSpy.callsFake(cb => cb()) - }) - - after(() => { - completeOnboardingSpy.restore() - }) - - it('completes onboarding', async () => { const store = mockStore() await store.dispatch(actions.setCompletedOnboarding()) assert.equal(completeOnboardingSpy.callCount, 1) + completeOnboardingSpy.restore() }) }) - describe('#updateNetworkNonce', () => { + describe('#updateNetworkNonce', function () { let getTransactionCountSpy - afterEach(() => { + afterEach(function () { getTransactionCountSpy.restore() }) - it('calls getTransactionCount', () => { + it('calls getTransactionCount', function () { const store = mockStore() getTransactionCountSpy = sinon.spy(global.ethQuery, 'getTransactionCount') @@ -1441,7 +1398,7 @@ describe('Actions', () => { assert(getTransactionCountSpy.calledOnce) }) - it('errors when getTransactionCount throws', async () => { + it('errors when getTransactionCount throws', async function () { const store = mockStore() const expectedActions = [ { type: 'DISPLAY_WARNING', value: 'error' }, @@ -1461,25 +1418,25 @@ describe('Actions', () => { }) }) - describe('#setUseBlockie', () => { + describe('#setUseBlockie', function () { let setUseBlockieSpy - beforeEach(() => { + beforeEach(function () { setUseBlockieSpy = sinon.stub(background, 'setUseBlockie') }) - afterEach(() => { + afterEach(function () { setUseBlockieSpy.restore() }) - it('calls setUseBlockie in background', () => { + it('calls setUseBlockie in background', function () { const store = mockStore() store.dispatch(actions.setUseBlockie()) assert(setUseBlockieSpy.calledOnce) }) - it('errors when setUseBlockie in background throws', () => { + it('errors when setUseBlockie in background throws', function () { const store = mockStore() const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -1497,19 +1454,19 @@ describe('Actions', () => { }) }) - describe('#updateCurrentLocale', () => { + describe('#updateCurrentLocale', function () { let setCurrentLocaleSpy - beforeEach(() => { + beforeEach(function () { fetchMock.get('*', enLocale) }) - afterEach(() => { + afterEach(function () { setCurrentLocaleSpy.restore() fetchMock.restore() }) - it('calls expected actions', async () => { + it('calls expected actions', async function () { const store = mockStore() setCurrentLocaleSpy = sinon.spy(background, 'setCurrentLocale') @@ -1524,7 +1481,7 @@ describe('Actions', () => { assert.deepEqual(store.getActions(), expectedActions) }) - it('errors when setCurrentLocale throws', async () => { + it('errors when setCurrentLocale throws', async function () { const store = mockStore() const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -1546,8 +1503,8 @@ describe('Actions', () => { }) }) - describe('#markPasswordForgotten', () => { - it('calls markPasswordForgotten', () => { + describe('#markPasswordForgotten', function () { + it('calls markPasswordForgotten', function () { const store = mockStore() const markPasswordForgottenSpy = sinon.stub(background, 'markPasswordForgotten').callsArg(0) @@ -1560,8 +1517,8 @@ describe('Actions', () => { }) }) - describe('#unMarkPasswordForgotten', () => { - it('calls unMarkPasswordForgotten', async () => { + describe('#unMarkPasswordForgotten', function () { + it('calls unMarkPasswordForgotten', async function () { const store = mockStore() const unMarkPasswordForgottenSpy = sinon.stub(background, 'unMarkPasswordForgotten').callsArg(0) diff --git a/test/unit/ui/app/components/token-cell.spec.js b/test/unit/ui/app/components/token-cell.spec.js index 5deafd8d7..a095fedce 100644 --- a/test/unit/ui/app/components/token-cell.spec.js +++ b/test/unit/ui/app/components/token-cell.spec.js @@ -8,7 +8,7 @@ import { mount } from 'enzyme' import TokenCell from '../../../../../ui/app/components/app/token-cell' import Identicon from '../../../../../ui/app/components/ui/identicon' -describe('Token Cell', () => { +describe('Token Cell', function () { let wrapper const state = { @@ -33,7 +33,7 @@ describe('Token Cell', () => { const mockStore = configureMockStore(middlewares) const store = mockStore(state) - beforeEach(() => { + beforeEach(function () { wrapper = mount( { ) }) - it('renders Identicon with props from token cell', () => { + it('renders Identicon with props from token cell', function () { assert.equal(wrapper.find(Identicon).prop('address'), '0xAnotherToken') assert.equal(wrapper.find(Identicon).prop('network'), 'test') assert.equal(wrapper.find(Identicon).prop('image'), './test-image') }) - it('renders token balance', () => { + it('renders token balance', function () { assert.equal(wrapper.find('.token-list-item__token-balance').text(), '5.000') }) - it('renders token symbol', () => { + it('renders token symbol', function () { assert.equal(wrapper.find('.token-list-item__token-symbol').text(), 'TEST') }) - it('renders converted fiat amount', () => { + it('renders converted fiat amount', function () { assert.equal(wrapper.find('.token-list-item__fiat-amount').text(), '0.52 USD') }) diff --git a/test/unit/ui/app/reducers/app.spec.js b/test/unit/ui/app/reducers/app.spec.js index ea4215f06..be90bf53c 100644 --- a/test/unit/ui/app/reducers/app.spec.js +++ b/test/unit/ui/app/reducers/app.spec.js @@ -4,7 +4,7 @@ import { actionConstants } from '../../../../../ui/app/store/actions' const actions = actionConstants -describe('App State', () => { +describe('App State', function () { const metamaskState = { selectedAddress: '0xAddress', @@ -16,13 +16,13 @@ describe('App State', () => { }, } - it('App init state', () => { + it('App init state', function () { const initState = reduceApp(metamaskState, {}) assert(initState) }) - it('sets networkDropdownOpen dropdown to true', () => { + it('sets networkDropdownOpen dropdown to true', function () { const state = reduceApp(metamaskState, { type: actions.NETWORK_DROPDOWN_OPEN, }) @@ -30,7 +30,7 @@ describe('App State', () => { assert.equal(state.networkDropdownOpen, true) }) - it('sets networkDropdownOpen dropdown to false', () => { + it('sets networkDropdownOpen dropdown to false', function () { const dropdown = { networkDropdowopen: true } const state = { ...metamaskState, ...dropdown } const newState = reduceApp(state, { @@ -40,7 +40,7 @@ describe('App State', () => { assert.equal(newState.networkDropdownOpen, false) }) - it('opens sidebar', () => { + it('opens sidebar', function () { const value = { 'transitionName': 'sidebar-right', 'type': 'wallet-view', @@ -54,7 +54,7 @@ describe('App State', () => { assert.deepEqual(state.sidebar, value) }) - it('closes sidebar', () => { + it('closes sidebar', function () { const openSidebar = { sidebar: { isOpen: true } } const state = { ...metamaskState, ...openSidebar } @@ -65,7 +65,7 @@ describe('App State', () => { assert.equal(newState.sidebar.isOpen, false) }) - it('opens alert', () => { + it('opens alert', function () { const state = reduceApp(metamaskState, { type: actions.ALERT_OPEN, value: 'test message', @@ -75,7 +75,7 @@ describe('App State', () => { assert.equal(state.alertMessage, 'test message') }) - it('closes alert', () => { + it('closes alert', function () { const alert = { alertOpen: true, alertMessage: 'test message' } const state = { ...metamaskState, ...alert } const newState = reduceApp(state, { @@ -86,7 +86,7 @@ describe('App State', () => { assert.equal(newState.alertMessage, null) }) - it('detects qr code data', () => { + it('detects qr code data', function () { const state = reduceApp(metamaskState, { type: actions.QR_CODE_DETECTED, value: 'qr data', @@ -95,7 +95,7 @@ describe('App State', () => { assert.equal(state.qrCodeData, 'qr data') }) - it('opens modal', () => { + it('opens modal', function () { const state = reduceApp(metamaskState, { type: actions.MODAL_OPEN, payload: { @@ -107,7 +107,7 @@ describe('App State', () => { assert.equal(state.modal.modalState.name, 'test') }) - it('closes modal, but moves open modal state to previous modal state', () => { + it('closes modal, but moves open modal state to previous modal state', function () { const opensModal = { modal: { open: true, @@ -127,7 +127,7 @@ describe('App State', () => { assert.equal(newState.modal.modalState.name, null) }) - it('transitions forwards', () => { + it('transitions forwards', function () { const state = reduceApp(metamaskState, { type: actions.TRANSITION_FORWARD, }) @@ -135,7 +135,7 @@ describe('App State', () => { assert.equal(state.transForward, true) }) - it('shows send token page', () => { + it('shows send token page', function () { const state = reduceApp(metamaskState, { type: actions.SHOW_SEND_TOKEN_PAGE, }) @@ -144,7 +144,7 @@ describe('App State', () => { assert.equal(state.warning, null) }) - it('unlocks Metamask', () => { + it('unlocks Metamask', function () { const state = reduceApp(metamaskState, { type: actions.UNLOCK_METAMASK, }) @@ -155,7 +155,7 @@ describe('App State', () => { assert.equal(state.warning, null) }) - it('locks Metamask', () => { + it('locks Metamask', function () { const state = reduceApp(metamaskState, { type: actions.LOCK_METAMASK, }) @@ -164,7 +164,7 @@ describe('App State', () => { assert.equal(state.warning, null) }) - it('goes home', () => { + it('goes home', function () { const state = reduceApp(metamaskState, { type: actions.GO_HOME, }) @@ -177,7 +177,7 @@ describe('App State', () => { }) - it('shows account detail', () => { + it('shows account detail', function () { const state = reduceApp(metamaskState, { type: actions.SHOW_ACCOUNT_DETAIL, value: 'context address', @@ -190,7 +190,7 @@ describe('App State', () => { }) - it('shoes account page', () => { + it('shoes account page', function () { const state = reduceApp(metamaskState, { type: actions.SHOW_ACCOUNTS_PAGE, }) @@ -202,7 +202,7 @@ describe('App State', () => { assert.equal(state.forgottenPassword, false) }) - it('shows confirm tx page', () => { + it('shows confirm tx page', function () { const txs = { unapprovedTxs: { 1: { @@ -227,7 +227,7 @@ describe('App State', () => { }) - it('completes tx continues to show pending txs current view context', () => { + it('completes tx continues to show pending txs current view context', function () { const txs = { unapprovedTxs: { 1: { @@ -253,7 +253,7 @@ describe('App State', () => { assert.equal(state.warning, null) }) - it('returns to account detail page when no unconf actions completed tx', () => { + it('returns to account detail page when no unconf actions completed tx', function () { const state = reduceApp(metamaskState, { type: actions.COMPLETED_TX, value: { @@ -264,10 +264,9 @@ describe('App State', () => { assert.equal(state.transForward, false) assert.equal(state.warning, null) assert.equal(state.accountDetail.subview, 'transactions') - }) - it('sets default warning when unlock fails', () => { + it('sets default warning when unlock fails', function () { const state = reduceApp(metamaskState, { type: actions.UNLOCK_FAILED, }) @@ -275,7 +274,7 @@ describe('App State', () => { assert.equal(state.warning, 'Incorrect password. Try again.') }) - it('sets default warning when unlock fails', () => { + it('sets errors when unlock fails', function () { const state = reduceApp(metamaskState, { type: actions.UNLOCK_FAILED, value: 'errors', @@ -284,7 +283,7 @@ describe('App State', () => { assert.equal(state.warning, 'errors') }) - it('sets warning to empty string when unlock succeeds', () => { + it('sets warning to empty string when unlock succeeds', function () { const errorState = { warning: 'errors' } const oldState = { ...metamaskState, ...errorState } const state = reduceApp(oldState, { @@ -294,7 +293,7 @@ describe('App State', () => { assert.equal(state.warning, '') }) - it('sets hardware wallet default hd path', () => { + it('sets hardware wallet default hd path', function () { const hdPaths = { trezor: "m/44'/60'/0'/0", ledger: "m/44'/60'/0'", @@ -310,7 +309,7 @@ describe('App State', () => { assert.deepEqual(state.defaultHdPaths, hdPaths) }) - it('shows loading message', () => { + it('shows loading message', function () { const state = reduceApp(metamaskState, { type: actions.SHOW_LOADING, value: 'loading', @@ -320,7 +319,7 @@ describe('App State', () => { assert.equal(state.loadingMessage, 'loading') }) - it('hides loading message', () => { + it('hides loading message', function () { const loadingState = { isLoading: true } const oldState = { ...metamaskState, ...loadingState } @@ -331,7 +330,7 @@ describe('App State', () => { assert.equal(state.isLoading, false) }) - it('shows sub loading indicator', () => { + it('shows sub loading indicator', function () { const state = reduceApp(metamaskState, { type: actions.SHOW_SUB_LOADING_INDICATION, }) @@ -339,7 +338,7 @@ describe('App State', () => { assert.equal(state.isSubLoading, true) }) - it('hides sub loading indicator', () => { + it('hides sub loading indicator', function () { const oldState = { ...metamaskState, isSubLoading: true } const state = reduceApp(oldState, { type: actions.HIDE_SUB_LOADING_INDICATION, @@ -348,7 +347,7 @@ describe('App State', () => { assert.equal(state.isSubLoading, false) }) - it('displays warning', () => { + it('displays warning', function () { const state = reduceApp(metamaskState, { type: actions.DISPLAY_WARNING, value: 'warning', @@ -358,7 +357,7 @@ describe('App State', () => { assert.equal(state.warning, 'warning') }) - it('hides warning', () => { + it('hides warning', function () { const displayWarningState = { warning: 'warning' } const oldState = { ...metamaskState, ...displayWarningState } const state = reduceApp(oldState, { @@ -368,7 +367,7 @@ describe('App State', () => { assert.equal(state.warning, undefined) }) - it('shows private key', () => { + it('shows private key', function () { const state = reduceApp(metamaskState, { type: actions.SHOW_PRIVATE_KEY, value: 'private key', @@ -379,7 +378,7 @@ describe('App State', () => { assert.equal(state.accountDetail.privateKey, 'private key') }) - it('updates pair', () => { + it('updates pair', function () { const coinOptions = { BTC: { symbol: 'BTC', @@ -427,7 +426,7 @@ describe('App State', () => { assert.equal(state.buyView.amount, '12.00') }) - it('shows QR', () => { + it('shows QR', function () { const state = reduceApp(metamaskState, { type: actions.SHOW_QR, value: { @@ -442,7 +441,7 @@ describe('App State', () => { assert.equal(state.Qr.data, 'data') }) - it('shows qr view', () => { + it('shows qr view', function () { const appState = { currentView: { context: 'accounts', @@ -463,7 +462,7 @@ describe('App State', () => { assert.equal(state.Qr.data, 'data') }) - it('set mouse user state', () => { + it('set mouse user state', function () { const state = reduceApp(metamaskState, { type: actions.SET_MOUSE_USER_STATE, value: true, @@ -472,7 +471,7 @@ describe('App State', () => { assert.equal(state.isMouseUser, true) }) - it('sets gas loading', () => { + it('sets gas loading', function () { const state = reduceApp(metamaskState, { type: actions.GAS_LOADING_STARTED, }) @@ -480,7 +479,7 @@ describe('App State', () => { assert.equal(state.gasIsLoading, true) }) - it('unsets gas loading', () => { + it('unsets gas loading', function () { const gasLoadingState = { gasIsLoading: true } const oldState = { ...metamaskState, ...gasLoadingState } const state = reduceApp(oldState, { @@ -490,7 +489,7 @@ describe('App State', () => { assert.equal(state.gasIsLoading, false) }) - it('sets network nonce', () => { + it('sets network nonce', function () { const state = reduceApp(metamaskState, { type: actions.SET_NETWORK_NONCE, value: '33', diff --git a/test/unit/ui/app/reducers/metamask.spec.js b/test/unit/ui/app/reducers/metamask.spec.js index 68c467781..bf16dd404 100644 --- a/test/unit/ui/app/reducers/metamask.spec.js +++ b/test/unit/ui/app/reducers/metamask.spec.js @@ -2,14 +2,14 @@ import assert from 'assert' import reduceMetamask from '../../../../../ui/app/ducks/metamask/metamask' import { actionConstants as actions } from '../../../../../ui/app/store/actions' -describe('MetaMask Reducers', () => { +describe('MetaMask Reducers', function () { - it('init state', () => { + it('init state', function () { const initState = reduceMetamask(undefined, {}) assert(initState) }) - it('unlocks MetaMask', () => { + it('unlocks MetaMask', function () { const state = reduceMetamask({}, { type: actions.UNLOCK_METAMASK, value: 'test address', @@ -20,7 +20,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.selectedAddress, 'test address') }) - it('locks MetaMask', () => { + it('locks MetaMask', function () { const unlockMetaMaskState = { isUnlocked: true, isInitialzed: false, @@ -33,7 +33,7 @@ describe('MetaMask Reducers', () => { assert.equal(lockMetaMask.isUnlocked, false) }) - it('sets rpc target', () => { + it('sets rpc target', function () { const state = reduceMetamask({}, { type: actions.SET_RPC_TARGET, value: 'https://custom.rpc', @@ -42,7 +42,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.provider.rpcTarget, 'https://custom.rpc') }) - it('sets provider type', () => { + it('sets provider type', function () { const state = reduceMetamask({}, { type: actions.SET_PROVIDER_TYPE, value: 'provider type', @@ -51,7 +51,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.provider.type, 'provider type') }) - it('shows account detail', () => { + it('shows account detail', function () { const state = reduceMetamask({}, { type: actions.SHOW_ACCOUNT_DETAIL, @@ -63,7 +63,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.selectedAddress, 'test address') }) - it('sets select ', () => { + it('sets select ', function () { const state = reduceMetamask({}, { type: actions.SET_SELECTED_TOKEN, value: 'test token', @@ -72,7 +72,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.selectedTokenAddress, 'test token') }) - it('sets account label', () => { + it('sets account label', function () { const state = reduceMetamask({}, { type: actions.SET_ACCOUNT_LABEL, value: { @@ -84,7 +84,7 @@ describe('MetaMask Reducers', () => { assert.deepEqual(state.identities, { 'test account': { name: 'test label' } }) }) - it('sets current fiat', () => { + it('sets current fiat', function () { const value = { currentCurrency: 'yen', conversionRate: 3.14, @@ -101,7 +101,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.conversionDate, value.conversionDate) }) - it('updates tokens', () => { + it('updates tokens', function () { const newTokens = { 'address': '0x617b3f8050a0bd94b6b1da02b4384ee5b4df13f4', 'decimals': 18, @@ -116,7 +116,7 @@ describe('MetaMask Reducers', () => { assert.deepEqual(state.tokens, newTokens) }) - it('updates send gas limit', () => { + it('updates send gas limit', function () { const state = reduceMetamask({}, { type: actions.UPDATE_GAS_LIMIT, @@ -126,7 +126,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.send.gasLimit, '0xGasLimit') }) - it('updates send gas price', () => { + it('updates send gas price', function () { const state = reduceMetamask({}, { type: actions.UPDATE_GAS_PRICE, value: '0xGasPrice', @@ -135,7 +135,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.send.gasPrice, '0xGasPrice') }) - it('toggles account menu ', () => { + it('toggles account menu ', function () { const state = reduceMetamask({}, { type: actions.TOGGLE_ACCOUNT_MENU, }) @@ -143,7 +143,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.isAccountMenuOpen, true) }) - it('updates gas total', () => { + it('updates gas total', function () { const state = reduceMetamask({}, { type: actions.UPDATE_GAS_TOTAL, value: '0xGasTotal', @@ -152,7 +152,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.send.gasTotal, '0xGasTotal') }) - it('updates send token balance', () => { + it('updates send token balance', function () { const state = reduceMetamask({}, { type: actions.UPDATE_SEND_TOKEN_BALANCE, value: '0xTokenBalance', @@ -161,7 +161,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.send.tokenBalance, '0xTokenBalance') }) - it('updates data', () => { + it('updates data', function () { const state = reduceMetamask({}, { type: actions.UPDATE_SEND_HEX_DATA, value: '0xData', @@ -170,7 +170,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.send.data, '0xData') }) - it('updates send to', () => { + it('updates send to', function () { const state = reduceMetamask({}, { type: actions.UPDATE_SEND_TO, value: { @@ -183,7 +183,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.send.toNickname, 'nickname') }) - it('update send amount', () => { + it('update send amount', function () { const state = reduceMetamask({}, { type: actions.UPDATE_SEND_AMOUNT, value: '0xAmount', @@ -192,7 +192,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.send.amount, '0xAmount') }) - it('updates max mode', () => { + it('updates max mode', function () { const state = reduceMetamask({}, { type: actions.UPDATE_MAX_MODE, value: true, @@ -201,7 +201,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.send.maxModeOn, true) }) - it('update send', () => { + it('update send', function () { const value = { gasLimit: '0xGasLimit', gasPrice: '0xGasPrice', @@ -228,7 +228,7 @@ describe('MetaMask Reducers', () => { assert.deepEqual(sendState.send, value) }) - it('clears send', () => { + it('clears send', function () { const initStateSend = { send: { gasLimit: null, @@ -272,7 +272,7 @@ describe('MetaMask Reducers', () => { assert.deepEqual(state.send, initStateSend.send) }) - it('updates value of tx by id', () => { + it('updates value of tx by id', function () { const oldState = { selectedAddressTxList: [ { @@ -291,7 +291,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.selectedAddressTxList[0].txParams, 'bar') }) - it('updates pair for shapeshift', () => { + it('updates pair for shapeshift', function () { const state = reduceMetamask({}, { type: actions.PAIR_UPDATE, value: { @@ -304,7 +304,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.tokenExchangeRates['test pair'].pair, 'test pair') }) - it('sets blockies', () => { + it('sets blockies', function () { const state = reduceMetamask({}, { type: actions.SET_USE_BLOCKIE, value: true, @@ -313,7 +313,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.useBlockie, true) }) - it('updates an arbitrary feature flag', () => { + it('updates an arbitrary feature flag', function () { const state = reduceMetamask({}, { type: actions.UPDATE_FEATURE_FLAGS, value: { @@ -324,7 +324,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.featureFlags.foo, true) }) - it('close welcome screen', () => { + it('close welcome screen', function () { const state = reduceMetamask({}, { type: actions.CLOSE_WELCOME_SCREEN, }) @@ -332,7 +332,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.welcomeScreenSeen, true) }) - it('sets current locale', () => { + it('sets current locale', function () { const state = reduceMetamask({}, { type: actions.SET_CURRENT_LOCALE, value: { locale: 'ge' }, @@ -341,7 +341,7 @@ describe('MetaMask Reducers', () => { assert.equal(state.currentLocale, 'ge') }) - it('sets pending tokens ', () => { + it('sets pending tokens ', function () { const payload = { 'address': '0x617b3f8050a0bd94b6b1da02b4384ee5b4df13f4', 'decimals': 18, @@ -356,7 +356,7 @@ describe('MetaMask Reducers', () => { assert.deepEqual(pendingTokensState.pendingTokens, payload) }) - it('clears pending tokens', () => { + it('clears pending tokens', function () { const payload = { 'address': '0x617b3f8050a0bd94b6b1da02b4384ee5b4df13f4', 'decimals': 18, @@ -374,7 +374,7 @@ describe('MetaMask Reducers', () => { assert.deepEqual(state.pendingTokens, {}) }) - it('update ensResolution', () => { + it('update ensResolution', function () { const state = reduceMetamask({}, { type: actions.UPDATE_SEND_ENS_RESOLUTION, payload: '0x1337', @@ -384,7 +384,7 @@ describe('MetaMask Reducers', () => { assert.deepEqual(state.send.ensResolutionError, '') }) - it('update ensResolutionError', () => { + it('update ensResolutionError', function () { const state = reduceMetamask({}, { type: actions.UPDATE_SEND_ENS_RESOLUTION_ERROR, payload: 'ens name not found', diff --git a/test/unit/ui/app/selectors.spec.js b/test/unit/ui/app/selectors.spec.js index a8e1079d0..a9a10e2a9 100644 --- a/test/unit/ui/app/selectors.spec.js +++ b/test/unit/ui/app/selectors.spec.js @@ -109,50 +109,50 @@ describe('Selectors', function () { assert.equal(currentAccountwithSendEther.name, 'Test Account') }) - it('#getGasIsLoading', () => { + it('#getGasIsLoading', function () { const gasIsLoading = selectors.getGasIsLoading(mockState) assert.equal(gasIsLoading, false) }) - describe('Send From', () => { - it('#getSendFrom', () => { + describe('Send From', function () { + it('#getSendFrom', function () { const sendFrom = selectors.getSendFrom(mockState) assert.equal(sendFrom, '0xc42edfcc21ed14dda456aa0756c153f7985d8813') }) - it('#getForceGasMin', () => { + it('#getForceGasMin', function () { const forceGasMin = selectors.getForceGasMin(mockState) assert.equal(forceGasMin, null) }) - it('#getSendAmount', () => { + it('#getSendAmount', function () { const sendAmount = selectors.getSendAmount(mockState) assert.equal(sendAmount, '1bc16d674ec80000') }) - it('#getSendMaxModeState', () => { + it('#getSendMaxModeState', function () { const sendMaxModeState = selectors.getSendMaxModeState(mockState) assert.equal(sendMaxModeState, false) }) }) - it('#getCurrentCurrency', () => { + it('#getCurrentCurrency', function () { const currentCurrency = selectors.getCurrentCurrency(mockState) assert.equal(currentCurrency, 'usd') }) - it('#getSelectedTokenToFiatRate', () => { + it('#getSelectedTokenToFiatRate', function () { const selectedTokenToFiatRate = selectors.getSelectedTokenToFiatRate(mockState) assert.equal(selectedTokenToFiatRate, '0.21880988420033492152') }) - it('#getSelectedTokenContract', () => { + it('#getSelectedTokenContract', function () { global.eth = new Eth(provider) const selectedTokenContract = selectors.getSelectedTokenContract(mockState) assert(selectedTokenContract.abi) }) - it('#getTotalUnapprovedCount', () => { + it('#getTotalUnapprovedCount', function () { const totalUnapprovedCount = selectors.getTotalUnapprovedCount(mockState) assert.equal(totalUnapprovedCount, 1) }) diff --git a/test/unit/ui/etherscan-prefix-for-network.spec.js b/test/unit/ui/etherscan-prefix-for-network.spec.js index 68e9cbea2..74da924d1 100644 --- a/test/unit/ui/etherscan-prefix-for-network.spec.js +++ b/test/unit/ui/etherscan-prefix-for-network.spec.js @@ -1,29 +1,29 @@ import assert from 'assert' import etherscanNetworkPrefix from '../../../ui/lib/etherscan-prefix-for-network' -describe('Etherscan Network Prefix', () => { +describe('Etherscan Network Prefix', function () { - it('returns empy string as default value', () => { + it('returns empy string as default value', function () { assert.equal(etherscanNetworkPrefix(), '') }) - it('returns empty string as a prefix for networkId of 1', () => { + it('returns empty string as a prefix for networkId of 1', function () { assert.equal(etherscanNetworkPrefix(1), '') }) - it('returns ropsten as prefix for networkId of 3', () => { + it('returns ropsten as prefix for networkId of 3', function () { assert.equal(etherscanNetworkPrefix(3), 'ropsten.') }) - it('returns rinkeby as prefix for networkId of 4', () => { + it('returns rinkeby as prefix for networkId of 4', function () { assert.equal(etherscanNetworkPrefix(4), 'rinkeby.') }) - it('returs kovan as prefix for networkId of 42', () => { + it('returs kovan as prefix for networkId of 42', function () { assert.equal(etherscanNetworkPrefix(42), 'kovan.') }) - it('returs goerli as prefix for networkId of 5', () => { + it('returs goerli as prefix for networkId of 5', function () { assert.equal(etherscanNetworkPrefix(5), 'goerli.') }) diff --git a/test/web3/web3.js b/test/web3/web3.js index 3431ee8ba..590a5d990 100644 --- a/test/web3/web3.js +++ b/test/web3/web3.js @@ -12,12 +12,12 @@ web3.currentProvider.enable().then(() => { Object.keys(methodGroup).forEach(methodKey => { const methodButton = document.getElementById(methodKey) - methodButton.addEventListener('click', function () { + methodButton.addEventListener('click', () => { window.ethereum.sendAsync({ method: methodKey, params: methodGroup[methodKey][1], - }, function (err, result) { + }, (err, result) => { if (err) { console.log(err) console.log(methodKey) diff --git a/ui/app/components/app/account-menu/tests/account-menu.test.js b/ui/app/components/app/account-menu/tests/account-menu.test.js index b1ebcf61c..9d03c7616 100644 --- a/ui/app/components/app/account-menu/tests/account-menu.test.js +++ b/ui/app/components/app/account-menu/tests/account-menu.test.js @@ -6,7 +6,7 @@ import { mountWithRouter } from '../../../../../../test/lib/render-helpers' import AccountMenu from '../index' import { Provider } from 'react-redux' -describe('Account Menu', async () => { +describe('Account Menu', function () { let wrapper @@ -63,7 +63,7 @@ describe('Account Menu', async () => { } - before(() => { + before(function () { wrapper = mountWithRouter( @@ -71,23 +71,23 @@ describe('Account Menu', async () => { ) }) - afterEach(() => { + afterEach(function () { props.toggleAccountMenu.resetHistory() props.history.push.resetHistory() }) - describe('Render Content', () => { - it('returns account name from identities', () => { + describe('Render Content', function () { + it('returns account name from identities', function () { const accountName = wrapper.find('.account-menu__name') assert.equal(accountName.length, 2) }) - it('renders user preference currency display balance from account balance', () => { + it('renders user preference currency display balance from account balance', function () { const accountBalance = wrapper.find('.currency-display-component.account-menu__balance') assert.equal(accountBalance.length, 2) }) - it('simulate click', () => { + it('simulate click', function () { const click = wrapper.find('.account-menu__account.menu__item--clickable') click.first().simulate('click') @@ -95,12 +95,12 @@ describe('Account Menu', async () => { assert.equal(props.showAccountDetail.getCall(0).args[0], '0xAddress') }) - it('render imported account label', () => { + it('render imported account label', function () { const importedAccount = wrapper.find('.keyring-label.allcaps') assert.equal(importedAccount.text(), 'imported') }) - it('remove account', () => { + it('remove account', function () { const removeAccount = wrapper.find('.remove-account-icon') removeAccount.simulate('click', { preventDefault: () => {}, @@ -114,93 +114,93 @@ describe('Account Menu', async () => { }) }) - describe('Log Out', () => { + describe('Log Out', function () { let logout - it('logout', () => { + it('logout', function () { logout = wrapper.find('.account-menu__lock-button') assert.equal(logout.length, 1) }) - it('simulate click', () => { + it('simulate click', function () { logout.simulate('click') assert(props.lockMetamask.calledOnce) assert.equal(props.history.push.getCall(0).args[0], '/') }) }) - describe('Create Account', () => { + describe('Create Account', function () { let createAccount - it('renders create account item', () => { + it('renders create account item', function () { createAccount = wrapper.find({ text: 'createAccount' }) assert.equal(createAccount.length, 1) }) - it('calls toggle menu and push new-account route to history', () => { + it('calls toggle menu and push new-account route to history', function () { createAccount.simulate('click') assert(props.toggleAccountMenu.calledOnce) assert.equal(props.history.push.getCall(0).args[0], '/new-account') }) }) - describe('Import Account', () => { + describe('Import Account', function () { let importAccount - it('renders import account item', () => { + it('renders import account item', function () { importAccount = wrapper.find({ text: 'importAccount' }) assert.equal(importAccount.length, 1) }) - it('calls toggle menu and push /new-account/import route to history', () => { + it('calls toggle menu and push /new-account/import route to history', function () { importAccount.simulate('click') assert(props.toggleAccountMenu.calledOnce) assert(props.history.push.getCall(0).args[0], '/new-account/import') }) }) - describe('Connect Hardware Wallet', () => { + describe('Connect Hardware Wallet', function () { let connectHardwareWallet - it('renders import account item', () => { + it('renders import account item', function () { connectHardwareWallet = wrapper.find({ text: 'connectHardwareWallet' }) assert.equal(connectHardwareWallet.length, 1) }) - it('calls toggle menu and push /new-account/connect route to history', () => { + it('calls toggle menu and push /new-account/connect route to history', function () { connectHardwareWallet.simulate('click') assert(props.toggleAccountMenu.calledOnce) assert.equal(props.history.push.getCall(0).args[0], '/new-account/connect') }) }) - describe('Info & Help', () => { + describe('Info & Help', function () { let infoHelp - it('renders import account item', () => { + it('renders import account item', function () { infoHelp = wrapper.find({ text: 'infoHelp' }) assert.equal(infoHelp.length, 1) }) - it('calls toggle menu and push /new-account/connect route to history', () => { + it('calls toggle menu and push /new-account/connect route to history', function () { infoHelp.simulate('click') assert(props.toggleAccountMenu.calledOnce) assert.equal(props.history.push.getCall(0).args[0], '/settings/about-us') }) }) - describe('Settings', () => { + describe('Settings', function () { let settings - it('renders import account item', () => { + it('renders import account item', function () { settings = wrapper.find({ text: 'settings' }) assert.equal(settings.length, 1) }) - it('calls toggle menu and push /new-account/connect route to history', () => { + it('calls toggle menu and push /new-account/connect route to history', function () { settings.simulate('click') assert(props.toggleAccountMenu.calledOnce) assert.equal(props.history.push.getCall(0).args[0], '/settings') diff --git a/ui/app/components/app/app-header/tests/app-header.test.js b/ui/app/components/app/app-header/tests/app-header.test.js index 37d1c32c4..f63567e95 100644 --- a/ui/app/components/app/app-header/tests/app-header.test.js +++ b/ui/app/components/app/app-header/tests/app-header.test.js @@ -5,7 +5,7 @@ import { shallow } from 'enzyme' import MetaFoxLogo from '../../../ui/metafox-logo' import AppHeader from '../index' -describe('App Header', () => { +describe('App Header', function () { let wrapper const props = { @@ -25,7 +25,7 @@ describe('App Header', () => { isUnlocked: true, } - beforeEach(() => { + beforeEach(function () { wrapper = shallow( , { context: { @@ -36,12 +36,12 @@ describe('App Header', () => { ) }) - afterEach(() => { + afterEach(function () { props.toggleAccountMenu.resetHistory() }) - describe('App Header Logo', () => { - it('routes to default route when logo is clicked', () => { + describe('App Header Logo', function () { + it('routes to default route when logo is clicked', function () { const appLogo = wrapper.find(MetaFoxLogo) appLogo.simulate('click') assert(props.history.push.calledOnce) @@ -49,8 +49,8 @@ describe('App Header', () => { }) }) - describe('Network', () => { - it('shows network dropdown when networkDropdownOpen is false', () => { + describe('Network', function () { + it('shows network dropdown when networkDropdownOpen is false', function () { const network = wrapper.find({ network: 'test' }) network.simulate('click', { @@ -61,7 +61,7 @@ describe('App Header', () => { assert(props.showNetworkDropdown.calledOnce) }) - it('hides network dropdown when networkDropdownOpen is true', () => { + it('hides network dropdown when networkDropdownOpen is true', function () { wrapper.setProps({ networkDropdownOpen: true }) const network = wrapper.find({ network: 'test' }) @@ -73,22 +73,22 @@ describe('App Header', () => { assert(props.hideNetworkDropdown.calledOnce) }) - it('hides network indicator', () => { + it('hides network indicator', function () { wrapper.setProps({ hideNetworkIndicator: true }) const network = wrapper.find({ network: 'test' }) assert.equal(network.length, 0) }) }) - describe('Account Menu', () => { + describe('Account Menu', function () { - it('toggles account menu', () => { + it('toggles account menu', function () { const accountMenu = wrapper.find('.account-menu__icon') accountMenu.simulate('click') assert(props.toggleAccountMenu.calledOnce) }) - it('does not toggle account menu when disabled', () => { + it('does not toggle account menu when disabled', function () { wrapper.setProps({ disabled: true }) const accountMenu = wrapper.find('.account-menu__icon') accountMenu.simulate('click') diff --git a/ui/app/components/app/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js b/ui/app/components/app/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js index d057bd449..40ac291e6 100644 --- a/ui/app/components/app/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js +++ b/ui/app/components/app/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js @@ -9,56 +9,56 @@ const propsMethodSpies = { } describe('Confirm Detail Row Component', function () { - let wrapper + describe('render', function () { + let wrapper - beforeEach(() => { - wrapper = shallow( - - ) - }) + beforeEach(function () { + wrapper = shallow( + + ) + }) - describe('render', () => { - it('should render a div with a confirm-detail-row class', () => { + it('should render a div with a confirm-detail-row class', function () { assert.equal(wrapper.find('div.confirm-detail-row').length, 1) }) - it('should render the label as a child of the confirm-detail-row__label', () => { + it('should render the label as a child of the confirm-detail-row__label', function () { assert.equal(wrapper.find('.confirm-detail-row > .confirm-detail-row__label').childAt(0).text(), 'mockLabel') }) - it('should render the headerText as a child of the confirm-detail-row__header-text', () => { + it('should render the headerText as a child of the confirm-detail-row__header-text', function () { assert.equal(wrapper.find('.confirm-detail-row__details > .confirm-detail-row__header-text').childAt(0).text(), 'mockHeaderText') }) - it('should render the primaryText as a child of the confirm-detail-row__primary', () => { + it('should render the primaryText as a child of the confirm-detail-row__primary', function () { assert.equal(wrapper.find('.confirm-detail-row__details > .confirm-detail-row__primary').childAt(0).text(), 'mockFiatText') }) - it('should render the ethText as a child of the confirm-detail-row__secondary', () => { + it('should render the ethText as a child of the confirm-detail-row__secondary', function () { assert.equal(wrapper.find('.confirm-detail-row__details > .confirm-detail-row__secondary').childAt(0).text(), 'mockEthText') }) - it('should set the fiatTextColor on confirm-detail-row__primary', () => { + it('should set the fiatTextColor on confirm-detail-row__primary', function () { assert.equal(wrapper.find('.confirm-detail-row__primary').props().style.color, 'mockColor') }) - it('should assure the confirm-detail-row__header-text classname is correct', () => { + it('should assure the confirm-detail-row__header-text classname is correct', function () { assert.equal(wrapper.find('.confirm-detail-row__header-text').props().className, 'confirm-detail-row__header-text mockHeaderClass') }) - it('should call onHeaderClick when headerText div gets clicked', () => { + it('should call onHeaderClick when headerText div gets clicked', function () { wrapper.find('.confirm-detail-row__header-text').props().onClick() - assert.equal(assert.equal(propsMethodSpies.onHeaderClick.callCount, 1)) + assert.ok(propsMethodSpies.onHeaderClick.calledOnce) }) }) }) diff --git a/ui/app/components/app/dropdowns/tests/dropdown.test.js b/ui/app/components/app/dropdowns/tests/dropdown.test.js index 4eb26ec59..83634429a 100644 --- a/ui/app/components/app/dropdowns/tests/dropdown.test.js +++ b/ui/app/components/app/dropdowns/tests/dropdown.test.js @@ -4,12 +4,12 @@ import sinon from 'sinon' import { shallow } from 'enzyme' import { DropdownMenuItem } from '../components/dropdown.js' -describe('Dropdown', () => { +describe('Dropdown', function () { let wrapper const onClickSpy = sinon.spy() const closeMenuSpy = sinon.spy() - beforeEach(() => { + beforeEach(function () { wrapper = shallow( { ) }) - it('renders li with dropdown-menu-item class', () => { + it('renders li with dropdown-menu-item class', function () { assert.equal(wrapper.find('li.dropdown-menu-item').length, 1) }) - it('adds style based on props passed', () => { + it('adds style based on props passed', function () { assert.equal(wrapper.prop('style').test, 'style') }) - it('simulates click event and calls onClick and closeMenu', () => { + it('simulates click event and calls onClick and closeMenu', function () { wrapper.prop('onClick')() assert.equal(onClickSpy.callCount, 1) assert.equal(closeMenuSpy.callCount, 1) diff --git a/ui/app/components/app/dropdowns/tests/menu.test.js b/ui/app/components/app/dropdowns/tests/menu.test.js index b3bc34fa9..a253f4aa9 100644 --- a/ui/app/components/app/dropdowns/tests/menu.test.js +++ b/ui/app/components/app/dropdowns/tests/menu.test.js @@ -4,29 +4,21 @@ import sinon from 'sinon' import { shallow } from 'enzyme' import { Menu, Item, Divider, CloseArea } from '../components/menu' -describe('Dropdown Menu Components', () => { - - describe('Menu', () => { - let wrapper - - beforeEach(() => { - wrapper = shallow( +describe('Dropdown Menu Components', function () { + describe('Menu', function () { + it('adds prop className to menu', function () { + const wrapper = shallow( ) - }) - - it('adds prop className to menu', () => { assert.equal(wrapper.find('.menu').prop('className'), 'menu Test Class') }) - }) - describe('Item', () => { + describe('Item', function () { let wrapper - const onClickSpy = sinon.spy() - beforeEach(() => { + beforeEach(function () { wrapper = shallow( { ) }) - it('add className based on props', () => { + it('add className based on props', function () { assert.equal(wrapper.find('.menu__item').prop('className'), 'menu__item test foo1 menu__item--clickable') }) - it('simulates onClick called', () => { + it('simulates onClick called', function () { wrapper.find('.menu__item').prop('onClick')() assert.equal(onClickSpy.callCount, 1) }) - it('adds icon based on icon props', () => { + it('adds icon based on icon props', function () { assert.equal(wrapper.find('.menu__item__icon').text(), 'test icon') }) - it('adds html text based on text props', () => { + it('adds html text based on text props', function () { assert.equal(wrapper.find('.menu__item__text').text(), 'test text') }) }) - describe('Divider', () => { - let wrapper - - before(() => { - wrapper = shallow() - }) - - it('renders menu divider', () => { + describe('Divider', function () { + it('renders menu divider', function () { + const wrapper = shallow() assert.equal(wrapper.find('.menu__divider').length, 1) }) }) - describe('CloseArea', () => { - let wrapper - - const onClickSpy = sinon.spy() - - beforeEach(() => { - wrapper = shallow(( + describe('CloseArea', function () { + it('simulates click', function () { + const onClickSpy = sinon.spy() + const wrapper = shallow(( )) - }) - - it('simulates click', () => { wrapper.prop('onClick')() - assert.equal(onClickSpy.callCount, 1) + assert.ok(onClickSpy.calledOnce) }) }) - }) diff --git a/ui/app/components/app/dropdowns/tests/network-dropdown-icon.test.js b/ui/app/components/app/dropdowns/tests/network-dropdown-icon.test.js index ce3853a63..2d1ad59b0 100644 --- a/ui/app/components/app/dropdowns/tests/network-dropdown-icon.test.js +++ b/ui/app/components/app/dropdowns/tests/network-dropdown-icon.test.js @@ -3,11 +3,9 @@ import assert from 'assert' import { shallow } from 'enzyme' import NetworkDropdownIcon from '../components/network-dropdown-icon' -describe('Network Dropdown Icon', () => { - let wrapper - - beforeEach(() => { - wrapper = shallow(( +describe('Network Dropdown Icon', function () { + it('adds style props based on props', function () { + const wrapper = shallow(( { diameter="12" /> )) - }) - - it('adds style props based on props', () => { const styleProp = wrapper.find('.menu-icon-circle').children().prop('style') assert.equal(styleProp.background, 'red') assert.equal(styleProp.border, 'none') diff --git a/ui/app/components/app/dropdowns/tests/network-dropdown.test.js b/ui/app/components/app/dropdowns/tests/network-dropdown.test.js index ec47bd0de..8ea53a7a7 100644 --- a/ui/app/components/app/dropdowns/tests/network-dropdown.test.js +++ b/ui/app/components/app/dropdowns/tests/network-dropdown.test.js @@ -6,10 +6,10 @@ import NetworkDropdown from '../network-dropdown' import { DropdownMenuItem } from '../components/dropdown' import NetworkDropdownIcon from '../components/network-dropdown-icon' -describe('Network Dropdown', () => { +describe('Network Dropdown', function () { let wrapper - describe('NetworkDropdown in appState in false', () => { + describe('NetworkDropdown in appState in false', function () { const mockState = { metamask: { network: '1', @@ -24,23 +24,23 @@ describe('Network Dropdown', () => { const store = createMockStore(mockState) - beforeEach(() => { + beforeEach(function () { wrapper = mountWithRouter( ) }) - it('checks for network droppo class', () => { + it('checks for network droppo class', function () { assert.equal(wrapper.find('.network-droppo').length, 1) }) - it('renders only one child when networkDropdown is false in state', () => { + it('renders only one child when networkDropdown is false in state', function () { assert.equal(wrapper.children().length, 1) }) }) - describe('NetworkDropdown in appState is true', () => { + describe('NetworkDropdown in appState is true', function () { const mockState = { metamask: { network: '1', @@ -57,45 +57,45 @@ describe('Network Dropdown', () => { } const store = createMockStore(mockState) - beforeEach(() => { + beforeEach(function () { wrapper = mountWithRouter( , ) }) - it('renders 7 DropDownMenuItems ', () => { + it('renders 7 DropDownMenuItems ', function () { assert.equal(wrapper.find(DropdownMenuItem).length, 8) }) - it('checks background color for first NetworkDropdownIcon', () => { + it('checks background color for first NetworkDropdownIcon', function () { assert.equal(wrapper.find(NetworkDropdownIcon).at(0).prop('backgroundColor'), '#29B6AF') // Main Ethereum Network Teal }) - it('checks background color for second NetworkDropdownIcon', () => { + it('checks background color for second NetworkDropdownIcon', function () { assert.equal(wrapper.find(NetworkDropdownIcon).at(1).prop('backgroundColor'), '#ff4a8d') // Ropsten Red }) - it('checks background color for third NetworkDropdownIcon', () => { + it('checks background color for third NetworkDropdownIcon', function () { assert.equal(wrapper.find(NetworkDropdownIcon).at(2).prop('backgroundColor'), '#7057ff') // Kovan Purple }) - it('checks background color for fourth NetworkDropdownIcon', () => { + it('checks background color for fourth NetworkDropdownIcon', function () { assert.equal(wrapper.find(NetworkDropdownIcon).at(3).prop('backgroundColor'), '#f6c343') // Rinkeby Yellow }) - it('checks background color for fifth NetworkDropdownIcon', () => { + it('checks background color for fifth NetworkDropdownIcon', function () { assert.equal(wrapper.find(NetworkDropdownIcon).at(4).prop('backgroundColor'), '#3099f2') // Goerli Blue }) - it('checks background color for sixth NetworkDropdownIcon', () => { + it('checks background color for sixth NetworkDropdownIcon', function () { assert.equal(wrapper.find(NetworkDropdownIcon).at(5).prop('innerBorder'), '1px solid #9b9b9b') }) - it('checks dropdown for frequestRPCList from state ', () => { + it('checks dropdown for frequestRPCList from state ', function () { assert.equal(wrapper.find(DropdownMenuItem).at(6).text(), '✓http://localhost:7545') }) - it('checks background color for seventh NetworkDropdownIcon', () => { + it('checks background color for seventh NetworkDropdownIcon', function () { assert.equal(wrapper.find(NetworkDropdownIcon).at(6).prop('innerBorder'), '1px solid #9b9b9b') }) diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js b/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js index e45740f5b..2da1911ea 100644 --- a/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js +++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js @@ -4,7 +4,7 @@ import sinon from 'sinon' import { mount } from 'enzyme' import AdvancedTabContent from '../index' -describe('Advanced Gas Inputs', () => { +describe('Advanced Gas Inputs', function () { let wrapper, clock const props = { @@ -19,7 +19,7 @@ describe('Advanced Gas Inputs', () => { isSpeedUp: false, } - beforeEach(() => { + beforeEach(function () { clock = sinon.useFakeTimers() wrapper = mount( @@ -32,11 +32,11 @@ describe('Advanced Gas Inputs', () => { }) }) - afterEach(() => { + afterEach(function () { clock.restore() }) - it('wont update gasPrice in props before debounce', () => { + it('wont update gasPrice in props before debounce', function () { const event = { target: { value: 1 } } wrapper.find('input').at(0).simulate('change', event) @@ -45,7 +45,7 @@ describe('Advanced Gas Inputs', () => { assert.equal(props.updateCustomGasPrice.callCount, 0) }) - it('simulates onChange on gas price after debounce', () => { + it('simulates onChange on gas price after debounce', function () { const event = { target: { value: 1 } } wrapper.find('input').at(0).simulate('change', event) @@ -55,7 +55,7 @@ describe('Advanced Gas Inputs', () => { assert.equal(props.updateCustomGasPrice.calledWith(1), true) }) - it('wont update gasLimit in props before debounce', () => { + it('wont update gasLimit in props before debounce', function () { const event = { target: { value: 21000 } } wrapper.find('input').at(1).simulate('change', event) @@ -64,7 +64,7 @@ describe('Advanced Gas Inputs', () => { assert.equal(props.updateCustomGasLimit.callCount, 0) }) - it('simulates onChange on gas limit after debounce', () => { + it('simulates onChange on gas limit after debounce', function () { const event = { target: { value: 21000 } } wrapper.find('input').at(1).simulate('change', event) @@ -74,7 +74,7 @@ describe('Advanced Gas Inputs', () => { assert.equal(props.updateCustomGasLimit.calledWith(21000), true) }) - it('errors when insuffientBalance under gas price and gas limit', () => { + it('errors when insuffientBalance under gas price and gas limit', function () { wrapper.setProps({ insufficientBalance: true }) const renderError = wrapper.find('.advanced-gas-inputs__gas-edit-row__error-text') assert.equal(renderError.length, 2) @@ -83,7 +83,7 @@ describe('Advanced Gas Inputs', () => { assert.equal(renderError.at(1).text(), 'insufficientBalance') }) - it('errors zero gas price / speed up', () => { + it('errors zero gas price / speed up', function () { wrapper.setProps({ isSpeedUp: true }) const renderError = wrapper.find('.advanced-gas-inputs__gas-edit-row__error-text') @@ -93,7 +93,7 @@ describe('Advanced Gas Inputs', () => { assert.equal(renderError.at(1).text(), 'gasLimitTooLow') }) - it('warns when custom gas price is too low', () => { + it('warns when custom gas price is too low', function () { wrapper.setProps({ customPriceIsSafe: false }) const renderWarning = wrapper.find('.advanced-gas-inputs__gas-edit-row__warning-text') diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js index 16b15df41..246c466a7 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js @@ -17,7 +17,7 @@ sinon.spy(AdvancedTabContent.prototype, 'renderDataSummary') describe('AdvancedTabContent Component', function () { let wrapper - beforeEach(() => { + beforeEach(function () { wrapper = shallow(( { + afterEach(function () { propsMethodSpies.updateCustomGasPrice.resetHistory() propsMethodSpies.updateCustomGasLimit.resetHistory() AdvancedTabContent.prototype.renderDataSummary.resetHistory() }) - describe('render()', () => { - it('should render the advanced-tab root node', () => { + describe('render()', function () { + it('should render the advanced-tab root node', function () { assert(wrapper.hasClass('advanced-tab')) }) - it('should render the expected four children of the advanced-tab div', () => { + it('should render the expected four children of the advanced-tab div', function () { const advancedTabChildren = wrapper.children() assert.equal(advancedTabChildren.length, 2) @@ -59,7 +59,7 @@ describe('AdvancedTabContent Component', function () { assert(feeChartDiv.childAt(1).childAt(2).hasClass('advanced-tab__fee-chart__speed-buttons')) }) - it('should render a loading component instead of the chart if gasEstimatesLoading is true', () => { + it('should render a loading component instead of the chart if gasEstimatesLoading is true', function () { wrapper.setProps({ gasEstimatesLoading: true }) const advancedTabChildren = wrapper.children() assert.equal(advancedTabChildren.length, 2) @@ -74,31 +74,31 @@ describe('AdvancedTabContent Component', function () { assert(feeChartDiv.childAt(1).childAt(2).hasClass('advanced-tab__fee-chart__speed-buttons')) }) - it('should call renderDataSummary with the expected params', () => { + it('should call renderDataSummary with the expected params', function () { const renderDataSummaryArgs = AdvancedTabContent.prototype.renderDataSummary.getCall(0).args assert.deepEqual(renderDataSummaryArgs, ['$0.25', 21500]) }) }) - describe('renderDataSummary()', () => { + describe('renderDataSummary()', function () { let dataSummary - beforeEach(() => { + beforeEach(function () { dataSummary = shallow(wrapper.instance().renderDataSummary('mockTotalFee', 'mockMsRemaining')) }) - it('should render the transaction-data-summary root node', () => { + it('should render the transaction-data-summary root node', function () { assert(dataSummary.hasClass('advanced-tab__transaction-data-summary')) }) - it('should render titles of the data', () => { + it('should render titles of the data', function () { const titlesNode = dataSummary.children().at(0) assert(titlesNode.hasClass('advanced-tab__transaction-data-summary__titles')) assert.equal(titlesNode.children().at(0).text(), 'newTransactionFee') assert.equal(titlesNode.children().at(1).text(), '~transactionTime') }) - it('should render the data', () => { + it('should render the data', function () { const dataNode = dataSummary.children().at(1) assert(dataNode.hasClass('advanced-tab__transaction-data-summary__container')) assert.equal(dataNode.children().at(0).text(), 'mockTotalFee') diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js index 790807450..87dbf73a7 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js @@ -2,7 +2,6 @@ import React from 'react' import assert from 'assert' import shallow from '../../../../../../../lib/shallow-with-context' import BasicTabContent from '../basic-tab-content.component' - import GasPriceButtonGroup from '../../../gas-price-button-group' import Loading from '../../../../../ui/loading-screen' import { GAS_ESTIMATE_TYPES } from '../../../../../../helpers/constants/common' @@ -39,26 +38,26 @@ const mockGasPriceButtonGroupProps = { } describe('BasicTabContent Component', function () { - let wrapper + describe('render', function () { + let wrapper - beforeEach(() => { - wrapper = shallow(( - - )) - }) + beforeEach(function () { + wrapper = shallow(( + + )) + }) - describe('render', () => { - it('should have a title', () => { + it('should have a title', function () { assert(wrapper.find('.basic-tab-content').childAt(0).hasClass('basic-tab-content__title')) }) - it('should render a GasPriceButtonGroup compenent', () => { + it('should render a GasPriceButtonGroup compenent', function () { assert.equal(wrapper.find(GasPriceButtonGroup).length, 1) }) - it('should pass correct props to GasPriceButtonGroup', () => { + it('should pass correct props to GasPriceButtonGroup', function () { const { buttonDataLoading, className, @@ -76,7 +75,7 @@ describe('BasicTabContent Component', function () { assert.equal(JSON.stringify(handleGasPriceSelection), JSON.stringify(mockGasPriceButtonGroupProps.handleGasPriceSelection)) }) - it('should render a loading component instead of the GasPriceButtonGroup if gasPriceButtonGroupProps.loading is true', () => { + it('should render a loading component instead of the GasPriceButtonGroup if gasPriceButtonGroupProps.loading is true', function () { wrapper.setProps({ gasPriceButtonGroupProps: { ...mockGasPriceButtonGroupProps, loading: true }, }) diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js index 32f144692..d15a557d7 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js @@ -62,7 +62,7 @@ const GP = GasModalPageContainer.prototype describe('GasModalPageContainer Component', function () { let wrapper - beforeEach(() => { + beforeEach(function () { wrapper = shallow(( { + afterEach(function () { propsMethodSpies.cancelAndClose.resetHistory() }) - describe('componentDidMount', () => { - it('should call props.fetchBasicGasAndTimeEstimates', () => { + describe('componentDidMount', function () { + it('should call props.fetchBasicGasAndTimeEstimates', function () { propsMethodSpies.fetchBasicGasAndTimeEstimates.resetHistory() assert.equal(propsMethodSpies.fetchBasicGasAndTimeEstimates.callCount, 0) wrapper.instance().componentDidMount() assert.equal(propsMethodSpies.fetchBasicGasAndTimeEstimates.callCount, 1) }) - it('should call props.fetchGasEstimates with the block time returned by fetchBasicGasAndTimeEstimates', async () => { + it('should call props.fetchGasEstimates with the block time returned by fetchBasicGasAndTimeEstimates', async function () { propsMethodSpies.fetchGasEstimates.resetHistory() assert.equal(propsMethodSpies.fetchGasEstimates.callCount, 0) wrapper.instance().componentDidMount() @@ -106,12 +106,12 @@ describe('GasModalPageContainer Component', function () { }) }) - describe('render', () => { - it('should render a PageContainer compenent', () => { + describe('render', function () { + it('should render a PageContainer compenent', function () { assert.equal(wrapper.find(PageContainer).length, 1) }) - it('should pass correct props to PageContainer', () => { + it('should pass correct props to PageContainer', function () { const { title, subtitle, @@ -122,7 +122,7 @@ describe('GasModalPageContainer Component', function () { assert.equal(disabled, false) }) - it('should pass the correct onCancel and onClose methods to PageContainer', () => { + it('should pass the correct onCancel and onClose methods to PageContainer', function () { const { onCancel, onClose, @@ -134,7 +134,7 @@ describe('GasModalPageContainer Component', function () { assert.equal(propsMethodSpies.cancelAndClose.callCount, 2) }) - it('should pass the correct renderTabs property to PageContainer', () => { + it('should pass the correct renderTabs property to PageContainer', function () { sinon.stub(GP, 'renderTabs').returns('mockTabs') const renderTabsWrapperTester = shallow(( { - beforeEach(() => { + describe('renderTabs', function () { + beforeEach(function () { sinon.spy(GP, 'renderBasicTabContent') sinon.spy(GP, 'renderAdvancedTabContent') sinon.spy(GP, 'renderInfoRows') }) - afterEach(() => { + afterEach(function () { GP.renderBasicTabContent.restore() GP.renderAdvancedTabContent.restore() GP.renderInfoRows.restore() }) - it('should render a Tabs component with "Basic" and "Advanced" tabs', () => { + it('should render a Tabs component with "Basic" and "Advanced" tabs', function () { const renderTabsResult = wrapper.instance().renderTabs() const renderedTabs = shallow(renderTabsResult) assert.equal(renderedTabs.props().className, 'tabs') @@ -176,7 +176,7 @@ describe('GasModalPageContainer Component', function () { assert.equal(tabs.at(1).childAt(0).props().className, 'gas-modal-content') }) - it('should call renderInfoRows with the expected props', () => { + it('should call renderInfoRows with the expected props', function () { assert.equal(GP.renderInfoRows.callCount, 0) wrapper.instance().renderTabs() @@ -187,7 +187,7 @@ describe('GasModalPageContainer Component', function () { assert.deepEqual(GP.renderInfoRows.getCall(1).args, ['mockNewTotalFiat', 'mockNewTotalEth', 'mockSendAmount', 'mockTransactionFee']) }) - it('should not render the basic tab if hideBasic is true', () => { + it('should not render the basic tab if hideBasic is true', function () { wrapper = shallow(( { - it('should render', () => { + describe('renderBasicTabContent', function () { + it('should render', function () { const renderBasicTabContentResult = wrapper.instance().renderBasicTabContent(mockGasPriceButtonGroupProps) assert.deepEqual( @@ -228,8 +228,8 @@ describe('GasModalPageContainer Component', function () { }) }) - describe('renderInfoRows', () => { - it('should render the info rows with the passed data', () => { + describe('renderInfoRows', function () { + it('should render the info rows with the passed data', function () { const baseClassName = 'gas-modal-content__info-row' const renderedInfoRowsContainer = shallow(wrapper.instance().renderInfoRows( 'mockNewTotalFiat', diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js index aa9e64eaf..73aeb4fdd 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js @@ -53,10 +53,10 @@ proxyquire('../gas-modal-page-container.container.js', { }, }) -describe('gas-modal-page-container container', () => { +describe('gas-modal-page-container container', function () { - describe('mapStateToProps()', () => { - it('should map the correct properties to props', () => { + describe('mapStateToProps()', function () { + it('should map the correct properties to props', function () { const baseMockState = { appState: { modal: { @@ -257,31 +257,31 @@ describe('gas-modal-page-container container', () => { }) - describe('mapDispatchToProps()', () => { + describe('mapDispatchToProps()', function () { let dispatchSpy let mapDispatchToPropsObject - beforeEach(() => { + beforeEach(function () { dispatchSpy = sinon.spy() mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) }) - afterEach(() => { + afterEach(function () { actionSpies.hideModal.resetHistory() gasActionSpies.setCustomGasPrice.resetHistory() gasActionSpies.setCustomGasLimit.resetHistory() }) - describe('hideGasButtonGroup()', () => { - it('should dispatch a hideGasButtonGroup action', () => { + describe('hideGasButtonGroup()', function () { + it('should dispatch a hideGasButtonGroup action', function () { mapDispatchToPropsObject.hideGasButtonGroup() assert(dispatchSpy.calledOnce) assert(sendActionSpies.hideGasButtonGroup.calledOnce) }) }) - describe('cancelAndClose()', () => { - it('should dispatch a hideModal action', () => { + describe('cancelAndClose()', function () { + it('should dispatch a hideModal action', function () { mapDispatchToPropsObject.cancelAndClose() assert(dispatchSpy.calledTwice) assert(actionSpies.hideModal.calledOnce) @@ -289,17 +289,15 @@ describe('gas-modal-page-container container', () => { }) }) - describe('updateCustomGasPrice()', () => { - it('should dispatch a setCustomGasPrice action with the arg passed to updateCustomGasPrice hex prefixed', () => { + describe('updateCustomGasPrice()', function () { + it('should dispatch a setCustomGasPrice action with the arg passed to updateCustomGasPrice hex prefixed', function () { mapDispatchToPropsObject.updateCustomGasPrice('ffff') assert(dispatchSpy.calledOnce) assert(gasActionSpies.setCustomGasPrice.calledOnce) assert.equal(gasActionSpies.setCustomGasPrice.getCall(0).args[0], '0xffff') }) - }) - describe('updateCustomGasPrice()', () => { - it('should dispatch a setCustomGasPrice action', () => { + it('should dispatch a setCustomGasPrice action', function () { mapDispatchToPropsObject.updateCustomGasPrice('0xffff') assert(dispatchSpy.calledOnce) assert(gasActionSpies.setCustomGasPrice.calledOnce) @@ -307,9 +305,8 @@ describe('gas-modal-page-container container', () => { }) }) - - describe('updateCustomGasLimit()', () => { - it('should dispatch a setCustomGasLimit action', () => { + describe('updateCustomGasLimit()', function () { + it('should dispatch a setCustomGasLimit action', function () { mapDispatchToPropsObject.updateCustomGasLimit('0x10') assert(dispatchSpy.calledOnce) assert(gasActionSpies.setCustomGasLimit.calledOnce) @@ -317,8 +314,8 @@ describe('gas-modal-page-container container', () => { }) }) - describe('setGasData()', () => { - it('should dispatch a setGasPrice and setGasLimit action with the correct props', () => { + describe('setGasData()', function () { + it('should dispatch a setGasPrice and setGasLimit action with the correct props', function () { mapDispatchToPropsObject.setGasData('ffff', 'aaaa') assert(dispatchSpy.calledTwice) assert(actionSpies.setGasPrice.calledOnce) @@ -328,8 +325,8 @@ describe('gas-modal-page-container container', () => { }) }) - describe('updateConfirmTxGasAndCalculate()', () => { - it('should dispatch a updateGasAndCalculate action with the correct props', () => { + describe('updateConfirmTxGasAndCalculate()', function () { + it('should dispatch a updateGasAndCalculate action with the correct props', function () { mapDispatchToPropsObject.updateConfirmTxGasAndCalculate('ffff', 'aaaa') assert.equal(dispatchSpy.callCount, 3) assert(actionSpies.setGasPrice.calledOnce) @@ -341,12 +338,12 @@ describe('gas-modal-page-container container', () => { }) - describe('mergeProps', () => { + describe('mergeProps', function () { let stateProps let dispatchProps let ownProps - beforeEach(() => { + beforeEach(function () { stateProps = { gasPriceButtonGroupProps: { someGasPriceButtonGroupProp: 'foo', @@ -370,7 +367,7 @@ describe('gas-modal-page-container container', () => { ownProps = { someOwnProp: 123 } }) - afterEach(() => { + afterEach(function () { dispatchProps.updateCustomGasPrice.resetHistory() dispatchProps.hideGasButtonGroup.resetHistory() dispatchProps.setGasData.resetHistory() @@ -380,7 +377,7 @@ describe('gas-modal-page-container container', () => { dispatchProps.hideSidebar.resetHistory() dispatchProps.hideModal.resetHistory() }) - it('should return the expected props when isConfirm is true', () => { + it('should return the expected props when isConfirm is true', function () { const result = mergeProps(stateProps, dispatchProps, ownProps) assert.equal(result.isConfirm, true) @@ -410,7 +407,7 @@ describe('gas-modal-page-container container', () => { assert.equal(dispatchProps.someOtherDispatchProp.callCount, 1) }) - it('should return the expected props when isConfirm is false', () => { + it('should return the expected props when isConfirm is false', function () { const result = mergeProps(Object.assign({}, stateProps, { isConfirm: false }), dispatchProps, ownProps) assert.equal(result.isConfirm, false) @@ -441,7 +438,7 @@ describe('gas-modal-page-container container', () => { assert.equal(dispatchProps.someOtherDispatchProp.callCount, 1) }) - it('should dispatch the expected actions from obSubmit when isConfirm is false and isSpeedUp is true', () => { + it('should dispatch the expected actions from obSubmit when isConfirm is false and isSpeedUp is true', function () { const result = mergeProps(Object.assign({}, stateProps, { isSpeedUp: true, isConfirm: false }), dispatchProps, ownProps) result.onSubmit() diff --git a/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js b/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js index 1d924f850..58424f095 100644 --- a/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js +++ b/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js @@ -47,7 +47,7 @@ sinon.spy(GasPriceButtonGroup.prototype, 'renderButtonContent') describe('GasPriceButtonGroup Component', function () { let wrapper - beforeEach(() => { + beforeEach(function () { wrapper = shallow(( { + afterEach(function () { GasPriceButtonGroup.prototype.renderButton.resetHistory() GasPriceButtonGroup.prototype.renderButtonContent.resetHistory() mockGasPriceButtonGroupProps.handleGasPriceSelection.resetHistory() }) - describe('render', () => { - it('should render a ButtonGroup', () => { + describe('render', function () { + it('should render a ButtonGroup', function () { assert(wrapper.is(ButtonGroup)) }) - it('should render the correct props on the ButtonGroup', () => { + it('should render the correct props on the ButtonGroup', function () { const { className, defaultActiveButtonIndex, @@ -88,14 +88,14 @@ describe('GasPriceButtonGroup Component', function () { ) } - it('should call this.renderButton 3 times, with the correct args', () => { + it('should call this.renderButton 3 times, with the correct args', function () { assert.equal(GasPriceButtonGroup.prototype.renderButton.callCount, 3) renderButtonArgsTest(0, mockButtonPropsAndFlags) renderButtonArgsTest(1, mockButtonPropsAndFlags) renderButtonArgsTest(2, mockButtonPropsAndFlags) }) - it('should show loading if buttonDataLoading', () => { + it('should show loading if buttonDataLoading', function () { wrapper.setProps({ buttonDataLoading: true }) assert(wrapper.is('div')) assert(wrapper.hasClass('gas-price-button-group__loading-container')) @@ -103,10 +103,10 @@ describe('GasPriceButtonGroup Component', function () { }) }) - describe('renderButton', () => { + describe('renderButton', function () { let wrappedRenderButtonResult - beforeEach(() => { + beforeEach(function () { GasPriceButtonGroup.prototype.renderButtonContent.resetHistory() const renderButtonResult = GasPriceButtonGroup.prototype.renderButton( Object.assign({}, mockGasPriceButtonGroupProps.gasButtonInfo[0]), @@ -115,11 +115,11 @@ describe('GasPriceButtonGroup Component', function () { wrappedRenderButtonResult = shallow(renderButtonResult) }) - it('should render a button', () => { + it('should render a button', function () { assert.equal(wrappedRenderButtonResult.type(), 'button') }) - it('should call the correct method when clicked', () => { + it('should call the correct method when clicked', function () { assert.equal(mockGasPriceButtonGroupProps.handleGasPriceSelection.callCount, 0) wrappedRenderButtonResult.props().onClick() assert.equal(mockGasPriceButtonGroupProps.handleGasPriceSelection.callCount, 1) @@ -129,7 +129,7 @@ describe('GasPriceButtonGroup Component', function () { ) }) - it('should call this.renderButtonContent with the correct args', () => { + it('should call this.renderButtonContent with the correct args', function () { assert.equal(GasPriceButtonGroup.prototype.renderButtonContent.callCount, 1) const { feeInPrimaryCurrency, @@ -157,8 +157,8 @@ describe('GasPriceButtonGroup Component', function () { }) }) - describe('renderButtonContent', () => { - it('should render a label if passed a gasEstimateType', () => { + describe('renderButtonContent', function () { + it('should render a label if passed a gasEstimateType', function () { const renderButtonContentResult = wrapper.instance().renderButtonContent({ gasEstimateType: 'SLOW', }, { @@ -169,7 +169,7 @@ describe('GasPriceButtonGroup Component', function () { assert.equal(wrappedRenderButtonContentResult.find('.someClass__label').text(), 'slow') }) - it('should render a feeInPrimaryCurrency if passed a feeInPrimaryCurrency', () => { + it('should render a feeInPrimaryCurrency if passed a feeInPrimaryCurrency', function () { const renderButtonContentResult = GasPriceButtonGroup.prototype.renderButtonContent({ feeInPrimaryCurrency: 'mockFeeInPrimaryCurrency', }, { @@ -180,7 +180,7 @@ describe('GasPriceButtonGroup Component', function () { assert.equal(wrappedRenderButtonContentResult.find('.someClass__primary-currency').text(), 'mockFeeInPrimaryCurrency') }) - it('should render a feeInSecondaryCurrency if passed a feeInSecondaryCurrency', () => { + it('should render a feeInSecondaryCurrency if passed a feeInSecondaryCurrency', function () { const renderButtonContentResult = GasPriceButtonGroup.prototype.renderButtonContent({ feeInSecondaryCurrency: 'mockFeeInSecondaryCurrency', }, { @@ -191,7 +191,7 @@ describe('GasPriceButtonGroup Component', function () { assert.equal(wrappedRenderButtonContentResult.find('.someClass__secondary-currency').text(), 'mockFeeInSecondaryCurrency') }) - it('should render a timeEstimate if passed a timeEstimate', () => { + it('should render a timeEstimate if passed a timeEstimate', function () { const renderButtonContentResult = GasPriceButtonGroup.prototype.renderButtonContent({ timeEstimate: 'mockTimeEstimate', }, { @@ -202,7 +202,7 @@ describe('GasPriceButtonGroup Component', function () { assert.equal(wrappedRenderButtonContentResult.find('.someClass__time-estimate').text(), 'mockTimeEstimate') }) - it('should render a check if showCheck is true', () => { + it('should render a check if showCheck is true', function () { const renderButtonContentResult = GasPriceButtonGroup.prototype.renderButtonContent({}, { className: 'someClass', showCheck: true, @@ -211,7 +211,7 @@ describe('GasPriceButtonGroup Component', function () { assert.equal(wrappedRenderButtonContentResult.find('.fa-check').length, 1) }) - it('should render all elements if all args passed', () => { + it('should render all elements if all args passed', function () { const renderButtonContentResult = wrapper.instance().renderButtonContent({ gasEstimateType: 'SLOW', feeInPrimaryCurrency: 'mockFeeInPrimaryCurrency', @@ -226,7 +226,7 @@ describe('GasPriceButtonGroup Component', function () { }) - it('should render no elements if all args passed', () => { + it('should render no elements if all args passed', function () { const renderButtonContentResult = GasPriceButtonGroup.prototype.renderButtonContent({}, {}) const wrappedRenderButtonContentResult = shallow(renderButtonContentResult) assert.equal(wrappedRenderButtonContentResult.children().length, 0) diff --git a/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js b/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js index 2204262b9..a088f746b 100644 --- a/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js +++ b/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js @@ -77,37 +77,37 @@ sinon.spy(GasPriceChart.prototype, 'renderChart') describe('GasPriceChart Component', function () { let wrapper - beforeEach(() => { + beforeEach(function () { wrapper = shallow() }) - describe('render()', () => { - it('should render', () => { + describe('render()', function () { + it('should render', function () { assert(wrapper.hasClass('gas-price-chart')) }) - it('should render the chart div', () => { + it('should render the chart div', function () { assert(wrapper.childAt(0).hasClass('gas-price-chart__root')) assert.equal(wrapper.childAt(0).props().id, 'chart') }) }) - describe('componentDidMount', () => { - it('should call this.renderChart', () => { + describe('componentDidMount', function () { + it('should call this.renderChart', function () { assert(GasPriceChart.prototype.renderChart.callCount, 1) wrapper.instance().componentDidMount() assert(GasPriceChart.prototype.renderChart.callCount, 2) }) }) - describe('componentDidUpdate', () => { - it('should call handleChartUpdate if props.currentPrice has changed', () => { + describe('componentDidUpdate', function () { + it('should call handleChartUpdate if props.currentPrice has changed', function () { gasPriceChartUtilsSpies.handleChartUpdate.resetHistory() wrapper.instance().componentDidUpdate({ currentPrice: 7 }) assert.equal(gasPriceChartUtilsSpies.handleChartUpdate.callCount, 1) }) - it('should call handleChartUpdate with the correct props', () => { + it('should call handleChartUpdate with the correct props', function () { gasPriceChartUtilsSpies.handleChartUpdate.resetHistory() wrapper.instance().componentDidUpdate({ currentPrice: 7 }) assert.deepEqual(gasPriceChartUtilsSpies.handleChartUpdate.getCall(0).args, [{ @@ -118,15 +118,15 @@ describe('GasPriceChart Component', function () { }]) }) - it('should not call handleChartUpdate if props.currentPrice has not changed', () => { + it('should not call handleChartUpdate if props.currentPrice has not changed', function () { gasPriceChartUtilsSpies.handleChartUpdate.resetHistory() wrapper.instance().componentDidUpdate({ currentPrice: 6 }) assert.equal(gasPriceChartUtilsSpies.handleChartUpdate.callCount, 0) }) }) - describe('renderChart', () => { - it('should call setTickPosition 4 times, with the expected props', async () => { + describe('renderChart', function () { + it('should call setTickPosition 4 times, with the expected props', async function () { await timeout(0) gasPriceChartUtilsSpies.setTickPosition.resetHistory() assert.equal(gasPriceChartUtilsSpies.setTickPosition.callCount, 0) @@ -139,7 +139,7 @@ describe('GasPriceChart Component', function () { assert.deepEqual(gasPriceChartUtilsSpies.setTickPosition.getCall(3).args, ['x', 1, 3, -8]) }) - it('should call handleChartUpdate with the correct props', async () => { + it('should call handleChartUpdate with the correct props', async function () { await timeout(0) gasPriceChartUtilsSpies.handleChartUpdate.resetHistory() wrapper.instance().renderChart(testProps) @@ -152,7 +152,7 @@ describe('GasPriceChart Component', function () { }]) }) - it('should add three events to the chart', async () => { + it('should add three events to the chart', async function () { await timeout(0) selectReturnSpies.on.resetHistory() assert.equal(selectReturnSpies.on.callCount, 0) @@ -168,7 +168,7 @@ describe('GasPriceChart Component', function () { assert.equal(thirdOnEventArgs[0], 'mousemove') }) - it('should hide the data UI on mouseout', async () => { + it('should hide the data UI on mouseout', async function () { await timeout(0) selectReturnSpies.on.resetHistory() wrapper.instance().renderChart(testProps) @@ -181,7 +181,7 @@ describe('GasPriceChart Component', function () { assert.deepEqual(gasPriceChartUtilsSpies.hideDataUI.getCall(0).args, [{ mockChart: true }, '#overlayed-circle']) }) - it('should updateCustomGasPrice on click', async () => { + it('should updateCustomGasPrice on click', async function () { await timeout(0) selectReturnSpies.on.resetHistory() wrapper.instance().renderChart(testProps) @@ -194,7 +194,7 @@ describe('GasPriceChart Component', function () { assert.equal(propsMethodSpies.updateCustomGasPrice.getCall(0).args[0], 'mockX') }) - it('should handle mousemove', async () => { + it('should handle mousemove', async function () { await timeout(0) selectReturnSpies.on.resetHistory() wrapper.instance().renderChart(testProps) diff --git a/ui/app/components/app/info-box/tests/info-box.test.js b/ui/app/components/app/info-box/tests/info-box.test.js index 904e868ba..e04d4ca67 100644 --- a/ui/app/components/app/info-box/tests/info-box.test.js +++ b/ui/app/components/app/info-box/tests/info-box.test.js @@ -5,7 +5,7 @@ import { shallow } from 'enzyme' import InfoBox from '../index' -describe('InfoBox', () => { +describe('InfoBox', function () { let wrapper @@ -15,21 +15,21 @@ describe('InfoBox', () => { onClose: sinon.spy(), } - beforeEach(() => { + beforeEach(function () { wrapper = shallow() }) - it('renders title from props', () => { + it('renders title from props', function () { const title = wrapper.find('.info-box__title') assert.equal(title.text(), props.title) }) - it('renders description from props', () => { + it('renders description from props', function () { const description = wrapper.find('.info-box__description') assert.equal(description.text(), props.description) }) - it('closes info box', () => { + it('closes info box', function () { const close = wrapper.find('.info-box__close') close.simulate('click') assert(props.onClose.calledOnce) diff --git a/ui/app/components/app/menu-bar/tests/menu-bar.test.js b/ui/app/components/app/menu-bar/tests/menu-bar.test.js index a43b994ba..46daccb38 100644 --- a/ui/app/components/app/menu-bar/tests/menu-bar.test.js +++ b/ui/app/components/app/menu-bar/tests/menu-bar.test.js @@ -6,7 +6,7 @@ import { mountWithRouter } from '../../../../../../test/lib/render-helpers' import MenuBar from '../index' import { Provider } from 'react-redux' -describe('MenuBar', () => { +describe('MenuBar', function () { let wrapper const mockStore = { @@ -38,11 +38,11 @@ describe('MenuBar', () => { const store = configureStore()(mockStore) - afterEach(() => { + afterEach(function () { sinon.restore() }) - it('shows side bar when sidbarOpen is set to false', () => { + it('shows side bar when sidbarOpen is set to false', function () { const props = { showSidebar: sinon.spy(), } @@ -58,7 +58,7 @@ describe('MenuBar', () => { assert(props.showSidebar.calledOnce) }) - it('hides side when sidebarOpen is set to true', () => { + it('hides side when sidebarOpen is set to true', function () { const props = { showSidebar: sinon.spy(), hideSidebar: sinon.spy(), @@ -76,13 +76,13 @@ describe('MenuBar', () => { assert(props.hideSidebar.calledOnce) }) - it('opens account detail menu when account options is clicked', () => { + it('opens account detail menu when account options is clicked', function () { const accountOptions = wrapper.find('.menu-bar__open-in-browser') accountOptions.simulate('click') assert.equal(wrapper.find('MenuBar').instance().state.accountDetailsMenuOpen, true) }) - it('sets accountDetailsMenuOpen to false when closed', () => { + it('sets accountDetailsMenuOpen to false when closed', function () { wrapper.find('MenuBar').instance().setState({ accountDetailsMenuOpen: true }) wrapper.update() diff --git a/ui/app/components/app/modal/modal-content/tests/modal-content.component.test.js b/ui/app/components/app/modal/modal-content/tests/modal-content.component.test.js index 17af09f45..3238ef3c0 100644 --- a/ui/app/components/app/modal/modal-content/tests/modal-content.component.test.js +++ b/ui/app/components/app/modal/modal-content/tests/modal-content.component.test.js @@ -3,8 +3,8 @@ import assert from 'assert' import { shallow } from 'enzyme' import ModalContent from '../modal-content.component' -describe('ModalContent Component', () => { - it('should render a title', () => { +describe('ModalContent Component', function () { + it('should render a title', function () { const wrapper = shallow( { assert.equal(wrapper.find('.modal-content__description').length, 0) }) - it('should render a description', () => { + it('should render a description', function () { const wrapper = shallow( { assert.equal(wrapper.find('.modal-content__description').text(), 'Modal Description') }) - it('should render both a title and a description', () => { + it('should render both a title and a description', function () { const wrapper = shallow( { - it('should render a modal with a submit button', () => { +describe('Modal Component', function () { + it('should render a modal with a submit button', function () { const wrapper = shallow() assert.equal(wrapper.find('.modal-container').length, 1) @@ -15,7 +15,7 @@ describe('Modal Component', () => { assert.equal(buttons.at(0).props().type, 'secondary') }) - it('should render a modal with a cancel and a submit button', () => { + it('should render a modal with a cancel and a submit button', function () { const handleCancel = sinon.spy() const handleSubmit = sinon.spy() const wrapper = shallow( @@ -45,7 +45,7 @@ describe('Modal Component', () => { assert.equal(handleSubmit.callCount, 1) }) - it('should render a modal with different button types', () => { + it('should render a modal with different button types', function () { const wrapper = shallow( {}} @@ -63,7 +63,7 @@ describe('Modal Component', () => { assert.equal(buttons.at(1).props().type, 'confirm') }) - it('should render a modal with children', () => { + it('should render a modal with children', function () { const wrapper = shallow( {}} @@ -78,7 +78,7 @@ describe('Modal Component', () => { assert.ok(wrapper.find('.test-class')) }) - it('should render a modal with a header', () => { + it('should render a modal with a header', function () { const handleCancel = sinon.spy() const handleSubmit = sinon.spy() const wrapper = shallow( @@ -101,7 +101,7 @@ describe('Modal Component', () => { assert.equal(handleSubmit.callCount, 0) }) - it('should disable the submit button if submitDisabled is true', () => { + it('should disable the submit button if submitDisabled is true', function () { const handleCancel = sinon.spy() const handleSubmit = sinon.spy() const wrapper = mount( diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/tests/cancel-transaction-gas-fee.component.test.js b/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/tests/cancel-transaction-gas-fee.component.test.js index 014815503..3f63d6540 100644 --- a/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/tests/cancel-transaction-gas-fee.component.test.js +++ b/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/tests/cancel-transaction-gas-fee.component.test.js @@ -4,8 +4,8 @@ import { shallow } from 'enzyme' import CancelTransactionGasFee from '../cancel-transaction-gas-fee.component' import UserPreferencedCurrencyDisplay from '../../../../user-preferenced-currency-display' -describe('CancelTransactionGasFee Component', () => { - it('should render', () => { +describe('CancelTransactionGasFee Component', function () { + it('should render', function () { const wrapper = shallow( { +describe('CancelTransaction Component', function () { const t = key => key - it('should render a CancelTransaction modal', () => { + it('should render a CancelTransaction modal', function () { const wrapper = shallow( { assert.equal(wrapper.find('.cancel-transaction__description').text(), 'attemptToCancelDescription') }) - it('should pass the correct props to the Modal component', async () => { + it('should pass the correct props to the Modal component', async function () { const createCancelTransactionSpy = sinon.stub().callsFake(() => Promise.resolve()) const hideModalSpy = sinon.spy() diff --git a/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js b/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js index ce0d49013..390d5bb53 100644 --- a/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js +++ b/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js @@ -4,7 +4,7 @@ import sinon from 'sinon' import { mount } from 'enzyme' import ConfirmDeleteNetwork from '../index' -describe('Confirm Delete Network', () => { +describe('Confirm Delete Network', function () { let wrapper const props = { @@ -14,7 +14,7 @@ describe('Confirm Delete Network', () => { target: '', } - beforeEach(() => { + beforeEach(function () { wrapper = mount( , { context: { @@ -24,18 +24,18 @@ describe('Confirm Delete Network', () => { ) }) - afterEach(() => { + afterEach(function () { props.hideModal.resetHistory() props.delRpcTarget.resetHistory() props.onConfirm.resetHistory() }) - it('renders delete network modal title', () => { + it('renders delete network modal title', function () { const modalTitle = wrapper.find('.modal-content__title') assert.equal(modalTitle.text(), 'deleteNetwork') }) - it('clicks cancel to hide modal', () => { + it('clicks cancel to hide modal', function () { const cancelButton = wrapper.find('.button.btn-default.modal-container__footer-button') cancelButton.simulate('click') @@ -43,7 +43,7 @@ describe('Confirm Delete Network', () => { }) - it('clicks delete to delete the target and hides modal', () => { + it('clicks delete to delete the target and hides modal', function () { const deleteButton = wrapper.find('.button.btn-danger.modal-container__footer-button') deleteButton.simulate('click') diff --git a/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js b/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js index 0a6eb828d..8be07d0d1 100644 --- a/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js +++ b/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js @@ -7,7 +7,7 @@ import configureStore from 'redux-mock-store' import { mount } from 'enzyme' import ConfirmRemoveAccount from '../index' -describe('Confirm Remove Account', () => { +describe('Confirm Remove Account', function () { let wrapper const state = { @@ -30,7 +30,7 @@ describe('Confirm Remove Account', () => { const mockStore = configureStore() const store = mockStore(state) - beforeEach(() => { + beforeEach(function () { wrapper = mount( @@ -48,18 +48,18 @@ describe('Confirm Remove Account', () => { ) }) - afterEach(() => { + afterEach(function () { props.hideModal.resetHistory() }) - it('nevermind', () => { + it('nevermind', function () { const nevermind = wrapper.find({ type: 'default' }) nevermind.simulate('click') assert(props.hideModal.calledOnce) }) - it('remove', (done) => { + it('remove', function (done) { const remove = wrapper.find({ type: 'secondary' }) remove.simulate('click') @@ -73,7 +73,7 @@ describe('Confirm Remove Account', () => { }) - it('closes', () => { + it('closes', function () { const close = wrapper.find('.modal-container__header-close') close.simulate('click') diff --git a/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js b/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js index 175a38158..46ec14050 100644 --- a/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js +++ b/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js @@ -4,7 +4,7 @@ import sinon from 'sinon' import { mount } from 'enzyme' import ConfirmResetAccount from '../index' -describe('Confirm Reset Account', () => { +describe('Confirm Reset Account', function () { let wrapper const props = { @@ -12,7 +12,7 @@ describe('Confirm Reset Account', () => { resetAccount: sinon.stub().resolves(), } - beforeEach(() => { + beforeEach(function () { wrapper = mount( , { context: { @@ -22,18 +22,18 @@ describe('Confirm Reset Account', () => { ) }) - afterEach(() => { + afterEach(function () { props.hideModal.resetHistory() }) - it('hides modal when nevermind button is clicked', () => { + it('hides modal when nevermind button is clicked', function () { const nevermind = wrapper.find('.btn-default.modal-container__footer-button') nevermind.simulate('click') assert(props.hideModal.calledOnce) }) - it('resets account and hidels modal when reset button is clicked', (done) => { + it('resets account and hidels modal when reset button is clicked', function (done) { const reset = wrapper.find('.btn-danger.modal-container__footer-button') reset.simulate('click') diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js b/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js index 2bae8f9b1..0832daf84 100644 --- a/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js +++ b/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js @@ -4,7 +4,7 @@ import sinon from 'sinon' import { mount } from 'enzyme' import MetaMetricsOptIn from '../index' -describe('MetaMetrics Opt In', () => { +describe('MetaMetrics Opt In', function () { let wrapper const props = { @@ -13,7 +13,7 @@ describe('MetaMetrics Opt In', () => { participateInMetaMetrics: null, } - beforeEach(() => { + beforeEach(function () { wrapper = mount( , { context: { @@ -23,12 +23,12 @@ describe('MetaMetrics Opt In', () => { ) }) - afterEach(() => { + afterEach(function () { props.setParticipateInMetaMetrics.resetHistory() props.hideModal.resetHistory() }) - it('passes false to setParticipateInMetaMetrics and hides modal', (done) => { + it('passes false to setParticipateInMetaMetrics and hides modal', function (done) { const noThanks = wrapper.find('.btn-default.page-container__footer-button') noThanks.simulate('click') @@ -40,7 +40,7 @@ describe('MetaMetrics Opt In', () => { }) }) - it('passes true to setParticipateInMetaMetrics and hides modal', (done) => { + it('passes true to setParticipateInMetaMetrics and hides modal', function (done) { const iAgree = wrapper.find('.btn-primary.page-container__footer-button') iAgree.simulate('click') diff --git a/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js b/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js index 505e9a05e..eac74c474 100644 --- a/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js +++ b/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js @@ -4,7 +4,7 @@ import sinon from 'sinon' import { mount } from 'enzyme' import RejectTransactionsModal from '../index' -describe('Reject Transactions Model', () => { +describe('Reject Transactions Model', function () { let wrapper const props = { @@ -13,7 +13,7 @@ describe('Reject Transactions Model', () => { unapprovedTxCount: 2, } - beforeEach(() => { + beforeEach(function () { wrapper = mount( , { context: { @@ -23,18 +23,18 @@ describe('Reject Transactions Model', () => { ) }) - afterEach(() => { + afterEach(function () { props.hideModal.resetHistory() }) - it('hides modal when cancel button is clicked', () => { + it('hides modal when cancel button is clicked', function () { const cancelButton = wrapper.find('.btn-default.modal-container__footer-button') cancelButton.simulate('click') assert(props.hideModal.calledOnce) }) - it('onSubmit is called and hides modal when reject all clicked', (done) => { + it('onSubmit is called and hides modal when reject all clicked', function (done) { const rejectAllButton = wrapper.find('.btn-secondary.modal-container__footer-button') rejectAllButton.simulate('click') diff --git a/ui/app/components/app/modals/tests/account-details-modal.test.js b/ui/app/components/app/modals/tests/account-details-modal.test.js index 24fe0eee4..b00b1418e 100644 --- a/ui/app/components/app/modals/tests/account-details-modal.test.js +++ b/ui/app/components/app/modals/tests/account-details-modal.test.js @@ -4,7 +4,7 @@ import sinon from 'sinon' import { shallow } from 'enzyme' import AccountDetailsModal from '../account-details-modal' -describe('Account Details Modal', () => { +describe('Account Details Modal', function () { let wrapper global.platform = { openWindow: sinon.spy() } @@ -36,7 +36,7 @@ describe('Account Details Modal', () => { }, } - beforeEach(() => { + beforeEach(function () { wrapper = shallow( , { context: { @@ -46,7 +46,7 @@ describe('Account Details Modal', () => { ) }) - it('sets account label when changing default account label', () => { + it('sets account label when changing default account label', function () { const accountLabel = wrapper.find('.account-modal__name').first() accountLabel.simulate('submit', 'New Label') @@ -54,7 +54,7 @@ describe('Account Details Modal', () => { assert.equal(props.setAccountLabel.getCall(0).args[1], 'New Label') }) - it('opens new window when view block explorer is clicked', () => { + it('opens new window when view block explorer is clicked', function () { const modalButton = wrapper.find('.account-modal__button') const etherscanLink = modalButton.first() @@ -62,7 +62,7 @@ describe('Account Details Modal', () => { assert(global.platform.openWindow.calledOnce) }) - it('shows export private key modal when clicked', () => { + it('shows export private key modal when clicked', function () { const modalButton = wrapper.find('.account-modal__button') const etherscanLink = modalButton.last() @@ -70,7 +70,7 @@ describe('Account Details Modal', () => { assert(props.showExportPrivateKeyModal.calledOnce) }) - it('sets blockexplorerview text when block explorer url in rpcPrefs exists', () => { + it('sets blockexplorerview text when block explorer url in rpcPrefs exists', function () { const blockExplorerUrl = 'https://block.explorer' wrapper.setProps({ rpcPrefs: { blockExplorerUrl } }) diff --git a/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js b/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js index 7d4debfd7..529e0cdbc 100644 --- a/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js +++ b/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js @@ -4,25 +4,19 @@ import sinon from 'sinon' import { mount } from 'enzyme' import TransactionConfirmed from '../index' -describe('Transaction Confirmed', () => { - let wrapper - - const props = { - onSubmit: sinon.spy(), - hideModal: sinon.spy(), - } - - beforeEach(() => { - wrapper = mount( +describe('Transaction Confirmed', function () { + it('clicks ok to submit and hide modal', function () { + const props = { + onSubmit: sinon.spy(), + hideModal: sinon.spy(), + } + const wrapper = mount( , { context: { t: str => str, }, } ) - }) - - it('clicks ok to submit and hide modal', () => { const submit = wrapper.find('.btn-secondary.modal-container__footer-button') submit.simulate('click') diff --git a/ui/app/components/app/selected-account/tests/selected-account-component.test.js b/ui/app/components/app/selected-account/tests/selected-account-component.test.js index 7db5c7202..60d34b178 100644 --- a/ui/app/components/app/selected-account/tests/selected-account-component.test.js +++ b/ui/app/components/app/selected-account/tests/selected-account-component.test.js @@ -3,8 +3,8 @@ import assert from 'assert' import { render } from 'enzyme' import SelectedAccount from '../selected-account.component' -describe('SelectedAccount Component', () => { - it('should render checksummed address', () => { +describe('SelectedAccount Component', function () { + it('should render checksummed address', function () { const wrapper = render(( { + beforeEach(function () { wrapper = shallow(( { + afterEach(function () { propsMethodSpies.hideSidebar.resetHistory() }) - describe('renderOverlay', () => { + describe('renderOverlay', function () { let renderOverlay - beforeEach(() => { + beforeEach(function () { renderOverlay = shallow(wrapper.instance().renderOverlay()) }) - it('should render a overlay element', () => { + it('should render a overlay element', function () { assert(renderOverlay.hasClass('sidebar-overlay')) }) - it('should pass the correct onClick function to the element', () => { + it('should pass the correct onClick function to the element', function () { assert.equal(propsMethodSpies.hideSidebar.callCount, 0) renderOverlay.props().onClick() assert.equal(propsMethodSpies.hideSidebar.callCount, 1) }) }) - describe('renderSidebarContent', () => { + describe('renderSidebarContent', function () { let renderSidebarContent - beforeEach(() => { + beforeEach(function () { wrapper.setProps({ type: 'wallet-view' }) renderSidebarContent = wrapper.instance().renderSidebarContent() }) - it('should render sidebar content with the correct props', () => { + it('should render sidebar content with the type wallet-view', function () { wrapper.setProps({ type: 'wallet-view' }) renderSidebarContent = wrapper.instance().renderSidebarContent() assert.equal(renderSidebarContent.props.responsiveDisplayClassname, 'sidebar-right') }) - it('should render sidebar content with the correct props', () => { + it('should render sidebar content with the type customize-gas', function () { wrapper.setProps({ type: 'customize-gas' }) renderSidebarContent = wrapper.instance().renderSidebarContent() const renderedSidebarContent = shallow(renderSidebarContent) @@ -70,25 +70,25 @@ describe('Sidebar Component', function () { assert(renderedSidebarContent.childAt(0).is(CustomizeGas)) }) - it('should not render with an unrecognized type', () => { + it('should not render with an unrecognized type', function () { wrapper.setProps({ type: 'foobar' }) renderSidebarContent = wrapper.instance().renderSidebarContent() assert.equal(renderSidebarContent, undefined) }) }) - describe('render', () => { - it('should render a div with one child', () => { + describe('render', function () { + it('should render a div with one child', function () { assert(wrapper.is('div')) assert.equal(wrapper.children().length, 1) }) - it('should render the ReactCSSTransitionGroup without any children', () => { + it('should render the ReactCSSTransitionGroup without any children', function () { assert(wrapper.children().at(0).is(ReactCSSTransitionGroup)) assert.equal(wrapper.children().at(0).children().length, 0) }) - it('should render sidebar content and the overlay if sidebarOpen is true', () => { + it('should render sidebar content and the overlay if sidebarOpen is true', function () { wrapper.setProps({ sidebarOpen: true }) assert.equal(wrapper.children().length, 2) assert(wrapper.children().at(1).hasClass('sidebar-overlay')) diff --git a/ui/app/components/app/signature-request/tests/signature-request.test.js b/ui/app/components/app/signature-request/tests/signature-request.test.js index acc2ac904..aed360423 100644 --- a/ui/app/components/app/signature-request/tests/signature-request.test.js +++ b/ui/app/components/app/signature-request/tests/signature-request.test.js @@ -5,26 +5,22 @@ import SignatureRequest from '../signature-request.component' describe('Signature Request Component', function () { - let wrapper + describe('render', function () { + it('should render a div with one child', function () { + const wrapper = shallow(( + {}} + cancel={() => {}} + sign={() => {}} + txData={{ + msgParams: { + data: '{"message": {"from": {"name": "hello"}}}', + from: '0x123456789abcdef', + }, + }} + /> + )) - beforeEach(() => { - wrapper = shallow(( - {}} - cancel={() => {}} - sign={() => {}} - txData={{ - msgParams: { - data: '{"message": {"from": {"name": "hello"}}}', - from: '0x123456789abcdef', - }, - }} - /> - )) - }) - - describe('render', () => { - it('should render a div with one child', () => { assert(wrapper.is('div')) assert.equal(wrapper.length, 1) assert(wrapper.hasClass('signature-request')) diff --git a/ui/app/components/app/tests/signature-request.test.js b/ui/app/components/app/tests/signature-request.test.js index eda054c16..5d10fe23e 100644 --- a/ui/app/components/app/tests/signature-request.test.js +++ b/ui/app/components/app/tests/signature-request.test.js @@ -6,7 +6,7 @@ import configureMockStore from 'redux-mock-store' import { mountWithRouter } from '../../../../../test/lib/render-helpers' import SignatureRequest from '../signature-request' -describe('Signature Request', () => { +describe('Signature Request', function () { let wrapper const mockStore = { @@ -40,7 +40,7 @@ describe('Signature Request', () => { }, } - beforeEach(() => { + beforeEach(function () { wrapper = mountWithRouter( @@ -48,18 +48,18 @@ describe('Signature Request', () => { ) }) - afterEach(() => { + afterEach(function () { props.clearConfirmTransaction.resetHistory() }) - it('cancel', () => { + it('cancel', function () { const cancelButton = wrapper.find('button.btn-default') cancelButton.simulate('click') assert(props.cancel.calledOnce) }) - it('sign', () => { + it('sign', function () { const signButton = wrapper.find('button.btn-primary') signButton.simulate('click') diff --git a/ui/app/components/app/tests/token-cell.spec.js b/ui/app/components/app/tests/token-cell.spec.js index 877713e4c..73ac6bb29 100644 --- a/ui/app/components/app/tests/token-cell.spec.js +++ b/ui/app/components/app/tests/token-cell.spec.js @@ -8,7 +8,7 @@ import { mount } from 'enzyme' import TokenCell from '../token-cell' import Identicon from '../../ui/identicon' -describe('Token Cell', () => { +describe('Token Cell', function () { let wrapper const state = { @@ -33,7 +33,7 @@ describe('Token Cell', () => { const mockStore = configureMockStore(middlewares) const store = mockStore(state) - beforeEach(() => { + beforeEach(function () { wrapper = mount( { ) }) - it('renders Identicon with props from token cell', () => { + it('renders Identicon with props from token cell', function () { assert.equal(wrapper.find(Identicon).prop('address'), '0xAnotherToken') assert.equal(wrapper.find(Identicon).prop('network'), 'test') assert.equal(wrapper.find(Identicon).prop('image'), './test-image') }) - it('renders token balance', () => { + it('renders token balance', function () { assert.equal(wrapper.find('.token-list-item__token-balance').text(), '5.000') }) - it('renders token symbol', () => { + it('renders token symbol', function () { assert.equal(wrapper.find('.token-list-item__token-symbol').text(), 'TEST') }) - it('renders converted fiat amount', () => { + it('renders converted fiat amount', function () { assert.equal(wrapper.find('.token-list-item__fiat-amount').text(), '0.52 USD') }) diff --git a/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js b/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js index 636fcfdcd..2168fe1f7 100644 --- a/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js +++ b/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js @@ -4,12 +4,12 @@ import { shallow } from 'enzyme' import sinon from 'sinon' import TransactionAction from '../transaction-action.component' -describe('TransactionAction Component', () => { +describe('TransactionAction Component', function () { const t = key => key - describe('Outgoing transaction', () => { - beforeEach(() => { + describe('Outgoing transaction', function () { + beforeEach(function () { global.eth = { getCode: sinon.stub().callsFake(address => { const code = address === 'approveAddress' ? 'contract' : '0x' @@ -18,7 +18,7 @@ describe('TransactionAction Component', () => { } }) - it('should render Sent Ether', () => { + it('should render Sent Ether', function () { const methodData = { data: {}, done: true, error: null } const transaction = { id: 1, @@ -48,7 +48,7 @@ describe('TransactionAction Component', () => { assert.equal(wrapper.text(), 'sentEther') }) - it('should render Approved', async () => { + it('should render Approved', async function () { const methodData = { name: 'Approve', } @@ -83,7 +83,7 @@ describe('TransactionAction Component', () => { assert.equal(wrapper.find('.transaction-action').text().trim(), 'Approve') }) - it('should render contractInteraction', async () => { + it('should render contractInteraction', async function () { const methodData = {} const transaction = { id: 1, diff --git a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js index b497a4f1b..233aca9ad 100644 --- a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js +++ b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js @@ -3,8 +3,8 @@ import assert from 'assert' import { shallow } from 'enzyme' import TransactionActivityLog from '../transaction-activity-log.component' -describe('TransactionActivityLog Component', () => { - it('should render properly', () => { +describe('TransactionActivityLog Component', function () { + it('should render properly', function () { const activities = [ { eventKey: 'transactionCreated', @@ -51,7 +51,7 @@ describe('TransactionActivityLog Component', () => { assert.ok(wrapper.hasClass('test-class')) }) - it('should render inline retry and cancel buttons for earliest pending transaction', () => { + it('should render inline retry and cancel buttons for earliest pending transaction', function () { const activities = [ { eventKey: 'transactionCreated', @@ -100,7 +100,7 @@ describe('TransactionActivityLog Component', () => { assert.equal(wrapper.find('.transaction-activity-log__action-link').length, 2) }) - it('should not render inline retry and cancel buttons for newer pending transactions', () => { + it('should not render inline retry and cancel buttons for newer pending transactions', function () { const activities = [ { eventKey: 'transactionCreated', diff --git a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.container.test.js b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.container.test.js index a7c35f51e..f071ea96a 100644 --- a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.container.test.js +++ b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.container.test.js @@ -12,9 +12,9 @@ proxyquire('../transaction-activity-log.container.js', { }, }) -describe('TransactionActivityLog container', () => { - describe('mapStateToProps()', () => { - it('should return the correct props', () => { +describe('TransactionActivityLog container', function () { + describe('mapStateToProps()', function () { + it('should return the correct props', function () { const mockState = { metamask: { conversionRate: 280.45, diff --git a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.util.test.js b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.util.test.js index d014b8886..a5912fbe8 100644 --- a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.util.test.js +++ b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.util.test.js @@ -1,335 +1,337 @@ import assert from 'assert' import { combineTransactionHistories, getActivities } from '../transaction-activity-log.util' -describe('combineTransactionHistories', () => { - it('should return no activites for an empty list of transactions', () => { - assert.deepEqual(combineTransactionHistories([]), []) - }) +describe('TransactionActivityLog utils', function () { + describe('combineTransactionHistories', function () { + it('should return no activites for an empty list of transactions', function () { + assert.deepEqual(combineTransactionHistories([]), []) + }) - it('should return activities for an array of transactions', () => { - const transactions = [ - { - estimatedGas: '0x5208', - hash: '0xa14f13d36b3901e352ce3a7acb9b47b001e5a3370f06232a0953c6fc6fad91b3', - history: [ - { - 'id': 6400627574331058, - 'time': 1543958845581, - 'status': 'unapproved', - 'metamaskNetworkId': '3', - 'loadingDefaults': true, - 'txParams': { - 'from': '0x50a9d56c2b8ba9a5c7f2c08c3d26e0499f23a706', - 'to': '0xc5ae6383e126f901dcb06131d97a88745bfa88d6', - 'value': '0x2386f26fc10000', - 'gas': '0x5208', - 'gasPrice': '0x3b9aca00', + it('should return activities for an array of transactions', function () { + const transactions = [ + { + estimatedGas: '0x5208', + hash: '0xa14f13d36b3901e352ce3a7acb9b47b001e5a3370f06232a0953c6fc6fad91b3', + history: [ + { + 'id': 6400627574331058, + 'time': 1543958845581, + 'status': 'unapproved', + 'metamaskNetworkId': '3', + 'loadingDefaults': true, + 'txParams': { + 'from': '0x50a9d56c2b8ba9a5c7f2c08c3d26e0499f23a706', + 'to': '0xc5ae6383e126f901dcb06131d97a88745bfa88d6', + 'value': '0x2386f26fc10000', + 'gas': '0x5208', + 'gasPrice': '0x3b9aca00', + }, + 'type': 'standard', }, - 'type': 'standard', + [{ 'op': 'replace', 'path': '/status', 'value': 'approved', 'note': 'txStateManager: setting status to approved', 'timestamp': 1543958847813 }], + [{ 'op': 'replace', 'path': '/status', 'value': 'submitted', 'note': 'txStateManager: setting status to submitted', 'timestamp': 1543958848147 }], + [{ 'op': 'replace', 'path': '/status', 'value': 'dropped', 'note': 'txStateManager: setting status to dropped', 'timestamp': 1543958897181 }, { 'op': 'add', 'path': '/replacedBy', 'value': '0xecbe181ee67c4291d04a7cb9ffbf1d5d831e4fbaa89994fd06bab5dd4cc79b33' }], + ], + id: 6400627574331058, + loadingDefaults: false, + metamaskNetworkId: '3', + status: 'dropped', + submittedTime: 1543958848135, + time: 1543958845581, + txParams: { + from: '0x50a9d56c2b8ba9a5c7f2c08c3d26e0499f23a706', + gas: '0x5208', + gasPrice: '0x3b9aca00', + nonce: '0x32', + to: '0xc5ae6383e126f901dcb06131d97a88745bfa88d6', + value: '0x2386f26fc10000', }, - [{ 'op': 'replace', 'path': '/status', 'value': 'approved', 'note': 'txStateManager: setting status to approved', 'timestamp': 1543958847813 }], - [{ 'op': 'replace', 'path': '/status', 'value': 'submitted', 'note': 'txStateManager: setting status to submitted', 'timestamp': 1543958848147 }], - [{ 'op': 'replace', 'path': '/status', 'value': 'dropped', 'note': 'txStateManager: setting status to dropped', 'timestamp': 1543958897181 }, { 'op': 'add', 'path': '/replacedBy', 'value': '0xecbe181ee67c4291d04a7cb9ffbf1d5d831e4fbaa89994fd06bab5dd4cc79b33' }], - ], - id: 6400627574331058, - loadingDefaults: false, - metamaskNetworkId: '3', - status: 'dropped', - submittedTime: 1543958848135, - time: 1543958845581, + type: 'standard', + }, { + hash: '0xecbe181ee67c4291d04a7cb9ffbf1d5d831e4fbaa89994fd06bab5dd4cc79b33', + history: [ + { + 'id': 6400627574331060, + 'time': 1543958857697, + 'status': 'unapproved', + 'metamaskNetworkId': '3', + 'loadingDefaults': false, + 'txParams': { + 'from': '0x50a9d56c2b8ba9a5c7f2c08c3d26e0499f23a706', + 'to': '0xc5ae6383e126f901dcb06131d97a88745bfa88d6', + 'value': '0x2386f26fc10000', + 'gas': '0x5208', + 'gasPrice': '0x3b9aca00', + 'nonce': '0x32', + }, + 'lastGasPrice': '0x4190ab00', + 'type': 'retry', + }, + [{ 'op': 'replace', 'path': '/txParams/gasPrice', 'value': '0x481f2280', 'note': 'confTx: user approved transaction', 'timestamp': 1543958859470 }], + [{ 'op': 'replace', 'path': '/status', 'value': 'approved', 'note': 'txStateManager: setting status to approved', 'timestamp': 1543958859485 }], + [{ 'op': 'replace', 'path': '/status', 'value': 'signed', 'note': 'transactions#publishTransaction', 'timestamp': 1543958859889 }], + [{ 'op': 'replace', 'path': '/status', 'value': 'submitted', 'note': 'txStateManager: setting status to submitted', 'timestamp': 1543958860061 }], [{ 'op': 'add', 'path': '/firstRetryBlockNumber', 'value': '0x45a0fd', 'note': 'transactions/pending-tx-tracker#event: tx:block-update', 'timestamp': 1543958896466 }], + [{ 'op': 'replace', 'path': '/status', 'value': 'confirmed', 'timestamp': 1543958897165 }], + ], + id: 6400627574331060, + lastGasPrice: '0x4190ab00', + loadingDefaults: false, + metamaskNetworkId: '3', + status: 'confirmed', + submittedTime: 1543958860054, + time: 1543958857697, + txParams: { + from: '0x50a9d56c2b8ba9a5c7f2c08c3d26e0499f23a706', + gas: '0x5208', + gasPrice: '0x481f2280', + nonce: '0x32', + to: '0xc5ae6383e126f901dcb06131d97a88745bfa88d6', + value: '0x2386f26fc10000', + }, + txReceipt: { + status: '0x1', + }, + type: 'retry', + }, + ] + + const expected = [ + { + id: 6400627574331058, + hash: '0xa14f13d36b3901e352ce3a7acb9b47b001e5a3370f06232a0953c6fc6fad91b3', + eventKey: 'transactionCreated', + timestamp: 1543958845581, + value: '0x2386f26fc10000', + }, { + id: 6400627574331058, + hash: '0xa14f13d36b3901e352ce3a7acb9b47b001e5a3370f06232a0953c6fc6fad91b3', + eventKey: 'transactionSubmitted', + timestamp: 1543958848147, + value: '0x1319718a5000', + }, { + id: 6400627574331060, + hash: '0xecbe181ee67c4291d04a7cb9ffbf1d5d831e4fbaa89994fd06bab5dd4cc79b33', + eventKey: 'transactionResubmitted', + timestamp: 1543958860061, + value: '0x171c3a061400', + }, { + id: 6400627574331060, + hash: '0xecbe181ee67c4291d04a7cb9ffbf1d5d831e4fbaa89994fd06bab5dd4cc79b33', + eventKey: 'transactionConfirmed', + timestamp: 1543958897165, + value: '0x171c3a061400', + }, + ] + + assert.deepEqual(combineTransactionHistories(transactions), expected) + }) + }) + + describe('getActivities', function () { + it('should return no activities for an empty history', function () { + const transaction = { + history: [], + id: 1, + status: 'confirmed', txParams: { - from: '0x50a9d56c2b8ba9a5c7f2c08c3d26e0499f23a706', + from: '0x1', gas: '0x5208', gasPrice: '0x3b9aca00', - nonce: '0x32', - to: '0xc5ae6383e126f901dcb06131d97a88745bfa88d6', + nonce: '0xa4', + to: '0x2', value: '0x2386f26fc10000', }, - type: 'standard', - }, { - hash: '0xecbe181ee67c4291d04a7cb9ffbf1d5d831e4fbaa89994fd06bab5dd4cc79b33', + } + + assert.deepEqual(getActivities(transaction), []) + }) + + it('should return activities for a transaction\'s history', function () { + const transaction = { history: [ { - 'id': 6400627574331060, - 'time': 1543958857697, - 'status': 'unapproved', - 'metamaskNetworkId': '3', - 'loadingDefaults': false, - 'txParams': { - 'from': '0x50a9d56c2b8ba9a5c7f2c08c3d26e0499f23a706', - 'to': '0xc5ae6383e126f901dcb06131d97a88745bfa88d6', - 'value': '0x2386f26fc10000', - 'gas': '0x5208', - 'gasPrice': '0x3b9aca00', - 'nonce': '0x32', + id: 5559712943815343, + loadingDefaults: true, + metamaskNetworkId: '3', + status: 'unapproved', + time: 1535507561452, + txParams: { + from: '0x1', + gas: '0x5208', + gasPrice: '0x3b9aca00', + nonce: '0xa4', + to: '0x2', + value: '0x2386f26fc10000', }, - 'lastGasPrice': '0x4190ab00', - 'type': 'retry', }, - [{ 'op': 'replace', 'path': '/txParams/gasPrice', 'value': '0x481f2280', 'note': 'confTx: user approved transaction', 'timestamp': 1543958859470 }], - [{ 'op': 'replace', 'path': '/status', 'value': 'approved', 'note': 'txStateManager: setting status to approved', 'timestamp': 1543958859485 }], - [{ 'op': 'replace', 'path': '/status', 'value': 'signed', 'note': 'transactions#publishTransaction', 'timestamp': 1543958859889 }], - [{ 'op': 'replace', 'path': '/status', 'value': 'submitted', 'note': 'txStateManager: setting status to submitted', 'timestamp': 1543958860061 }], [{ 'op': 'add', 'path': '/firstRetryBlockNumber', 'value': '0x45a0fd', 'note': 'transactions/pending-tx-tracker#event: tx:block-update', 'timestamp': 1543958896466 }], - [{ 'op': 'replace', 'path': '/status', 'value': 'confirmed', 'timestamp': 1543958897165 }], + [ + { + op: 'replace', + path: '/loadingDefaults', + timestamp: 1535507561515, + value: false, + }, + { + op: 'add', + path: '/gasPriceSpecified', + value: true, + }, + { + op: 'add', + path: '/gasLimitSpecified', + value: true, + }, + { + op: 'add', + path: '/estimatedGas', + value: '0x5208', + }, + ], + [ + { + note: '#newUnapprovedTransaction - adding the origin', + op: 'add', + path: '/origin', + timestamp: 1535507561516, + value: 'MetaMask', + }, + [], + ], + [ + { + note: 'confTx: user approved transaction', + op: 'replace', + path: '/txParams/gasPrice', + timestamp: 1535664571504, + value: '0x77359400', + }, + ], + [ + { + note: 'txStateManager: setting status to approved', + op: 'replace', + path: '/status', + timestamp: 1535507564302, + value: 'approved', + }, + ], + [ + { + note: 'transactions#approveTransaction', + op: 'add', + path: '/txParams/nonce', + timestamp: 1535507564439, + value: '0xa4', + }, + { + op: 'add', + path: '/nonceDetails', + value: { + local: {}, + network: {}, + params: {}, + }, + }, + ], + [ + { + note: 'transactions#publishTransaction', + op: 'replace', + path: '/status', + timestamp: 1535507564518, + value: 'signed', + }, + { + op: 'add', + path: '/rawTx', + value: '0xf86b81a4843b9aca008252089450a9d56c2b8ba9a5c7f2c08c3d26e0499f23a706872386f26fc10000802aa007b30119fc4fc5954fad727895b7e3ba80a78d197e95703cc603bcf017879151a01c50beda40ffaee541da9c05b9616247074f25f392800e0ad6c7a835d5366edf', + }, + ], + [], + [ + { + note: 'transactions#setTxHash', + op: 'add', + path: '/hash', + timestamp: 1535507564658, + value: '0x7acc4987b5c0dfa8d423798a8c561138259de1f98a62e3d52e7e83c0e0dd9fb7', + }, + ], + [ + { + note: 'txStateManager - add submitted time stamp', + op: 'add', + path: '/submittedTime', + timestamp: 1535507564660, + value: 1535507564660, + }, + ], + [ + { + note: 'txStateManager: setting status to submitted', + op: 'replace', + path: '/status', + timestamp: 1535507564665, + value: 'submitted', + }, + ], + [ + { + note: 'transactions/pending-tx-tracker#event: tx:block-update', + op: 'add', + path: '/firstRetryBlockNumber', + timestamp: 1535507575476, + value: '0x3bf624', + }, + ], + [ + { + note: 'txStateManager: setting status to confirmed', + op: 'replace', + path: '/status', + timestamp: 1535507615993, + value: 'confirmed', + }, + ], ], - id: 6400627574331060, - lastGasPrice: '0x4190ab00', - loadingDefaults: false, - metamaskNetworkId: '3', + id: 1, status: 'confirmed', - submittedTime: 1543958860054, - time: 1543958857697, txParams: { - from: '0x50a9d56c2b8ba9a5c7f2c08c3d26e0499f23a706', + from: '0x1', gas: '0x5208', - gasPrice: '0x481f2280', - nonce: '0x32', - to: '0xc5ae6383e126f901dcb06131d97a88745bfa88d6', + gasPrice: '0x3b9aca00', + nonce: '0xa4', + to: '0x2', value: '0x2386f26fc10000', }, - txReceipt: { - status: '0x1', - }, - type: 'retry', - }, - ] - - const expected = [ - { - id: 6400627574331058, - hash: '0xa14f13d36b3901e352ce3a7acb9b47b001e5a3370f06232a0953c6fc6fad91b3', - eventKey: 'transactionCreated', - timestamp: 1543958845581, - value: '0x2386f26fc10000', - }, { - id: 6400627574331058, - hash: '0xa14f13d36b3901e352ce3a7acb9b47b001e5a3370f06232a0953c6fc6fad91b3', - eventKey: 'transactionSubmitted', - timestamp: 1543958848147, - value: '0x1319718a5000', - }, { - id: 6400627574331060, - hash: '0xecbe181ee67c4291d04a7cb9ffbf1d5d831e4fbaa89994fd06bab5dd4cc79b33', - eventKey: 'transactionResubmitted', - timestamp: 1543958860061, - value: '0x171c3a061400', - }, { - id: 6400627574331060, - hash: '0xecbe181ee67c4291d04a7cb9ffbf1d5d831e4fbaa89994fd06bab5dd4cc79b33', - eventKey: 'transactionConfirmed', - timestamp: 1543958897165, - value: '0x171c3a061400', - }, - ] + hash: '0xabc', + } - assert.deepEqual(combineTransactionHistories(transactions), expected) - }) -}) - -describe('getActivities', () => { - it('should return no activities for an empty history', () => { - const transaction = { - history: [], - id: 1, - status: 'confirmed', - txParams: { - from: '0x1', - gas: '0x5208', - gasPrice: '0x3b9aca00', - nonce: '0xa4', - to: '0x2', - value: '0x2386f26fc10000', - }, - } - - assert.deepEqual(getActivities(transaction), []) - }) - - it('should return activities for a transaction\'s history', () => { - const transaction = { - history: [ + const expectedResult = [ { - id: 5559712943815343, - loadingDefaults: true, - metamaskNetworkId: '3', - status: 'unapproved', - time: 1535507561452, - txParams: { - from: '0x1', - gas: '0x5208', - gasPrice: '0x3b9aca00', - nonce: '0xa4', - to: '0x2', - value: '0x2386f26fc10000', - }, + 'eventKey': 'transactionCreated', + 'timestamp': 1535507561452, + 'value': '0x2386f26fc10000', + 'id': 1, + 'hash': '0xabc', }, - [ - { - op: 'replace', - path: '/loadingDefaults', - timestamp: 1535507561515, - value: false, - }, - { - op: 'add', - path: '/gasPriceSpecified', - value: true, - }, - { - op: 'add', - path: '/gasLimitSpecified', - value: true, - }, - { - op: 'add', - path: '/estimatedGas', - value: '0x5208', - }, - ], - [ - { - note: '#newUnapprovedTransaction - adding the origin', - op: 'add', - path: '/origin', - timestamp: 1535507561516, - value: 'MetaMask', - }, - [], - ], - [ - { - note: 'confTx: user approved transaction', - op: 'replace', - path: '/txParams/gasPrice', - timestamp: 1535664571504, - value: '0x77359400', - }, - ], - [ - { - note: 'txStateManager: setting status to approved', - op: 'replace', - path: '/status', - timestamp: 1535507564302, - value: 'approved', - }, - ], - [ - { - note: 'transactions#approveTransaction', - op: 'add', - path: '/txParams/nonce', - timestamp: 1535507564439, - value: '0xa4', - }, - { - op: 'add', - path: '/nonceDetails', - value: { - local: {}, - network: {}, - params: {}, - }, - }, - ], - [ - { - note: 'transactions#publishTransaction', - op: 'replace', - path: '/status', - timestamp: 1535507564518, - value: 'signed', - }, - { - op: 'add', - path: '/rawTx', - value: '0xf86b81a4843b9aca008252089450a9d56c2b8ba9a5c7f2c08c3d26e0499f23a706872386f26fc10000802aa007b30119fc4fc5954fad727895b7e3ba80a78d197e95703cc603bcf017879151a01c50beda40ffaee541da9c05b9616247074f25f392800e0ad6c7a835d5366edf', - }, - ], - [], - [ - { - note: 'transactions#setTxHash', - op: 'add', - path: '/hash', - timestamp: 1535507564658, - value: '0x7acc4987b5c0dfa8d423798a8c561138259de1f98a62e3d52e7e83c0e0dd9fb7', - }, - ], - [ - { - note: 'txStateManager - add submitted time stamp', - op: 'add', - path: '/submittedTime', - timestamp: 1535507564660, - value: 1535507564660, - }, - ], - [ - { - note: 'txStateManager: setting status to submitted', - op: 'replace', - path: '/status', - timestamp: 1535507564665, - value: 'submitted', - }, - ], - [ - { - note: 'transactions/pending-tx-tracker#event: tx:block-update', - op: 'add', - path: '/firstRetryBlockNumber', - timestamp: 1535507575476, - value: '0x3bf624', - }, - ], - [ - { - note: 'txStateManager: setting status to confirmed', - op: 'replace', - path: '/status', - timestamp: 1535507615993, - value: 'confirmed', - }, - ], - ], - id: 1, - status: 'confirmed', - txParams: { - from: '0x1', - gas: '0x5208', - gasPrice: '0x3b9aca00', - nonce: '0xa4', - to: '0x2', - value: '0x2386f26fc10000', - }, - hash: '0xabc', - } - - const expectedResult = [ - { - 'eventKey': 'transactionCreated', - 'timestamp': 1535507561452, - 'value': '0x2386f26fc10000', - 'id': 1, - 'hash': '0xabc', - }, - { - 'eventKey': 'transactionSubmitted', - 'timestamp': 1535507564665, - 'value': '0x2632e314a000', - 'id': 1, - 'hash': '0xabc', - }, - { - 'eventKey': 'transactionConfirmed', - 'timestamp': 1535507615993, - 'value': '0x2632e314a000', - 'id': 1, - 'hash': '0xabc', - }, - ] + { + 'eventKey': 'transactionSubmitted', + 'timestamp': 1535507564665, + 'value': '0x2632e314a000', + 'id': 1, + 'hash': '0xabc', + }, + { + 'eventKey': 'transactionConfirmed', + 'timestamp': 1535507615993, + 'value': '0x2632e314a000', + 'id': 1, + 'hash': '0xabc', + }, + ] - assert.deepEqual(getActivities(transaction, true), expectedResult) + assert.deepEqual(getActivities(transaction, true), expectedResult) + }) }) }) diff --git a/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js b/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js index b34a4e9ce..3f3645364 100644 --- a/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js +++ b/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js @@ -3,8 +3,8 @@ import assert from 'assert' import { shallow } from 'enzyme' import TransactionBreakdown from '../transaction-breakdown.component' -describe('TransactionBreakdown Component', () => { - it('should render properly', () => { +describe('TransactionBreakdown Component', function () { + it('should render properly', function () { const transaction = { history: [], id: 1, diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js index c17fcc940..da5294094 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js @@ -4,8 +4,8 @@ import { shallow } from 'enzyme' import TransactionBreakdownRow from '../transaction-breakdown-row.component' import Button from '../../../../ui/button' -describe('TransactionBreakdownRow Component', () => { - it('should render text properly', () => { +describe('TransactionBreakdownRow Component', function () { + it('should render text properly', function () { const wrapper = shallow( { assert.equal(wrapper.find('.transaction-breakdown-row__value').text(), 'Test') }) - it('should render components properly', () => { + it('should render components properly', function () { const wrapper = shallow( { - it('should render properly', () => { +describe('TransactionListItemDetails Component', function () { + it('should render properly', function () { const transaction = { history: [], id: 1, @@ -48,7 +48,7 @@ describe('TransactionListItemDetails Component', () => { assert.equal(wrapper.find(TransactionActivityLog).length, 1) }) - it('should render a retry button', () => { + it('should render a retry button', function () { const transaction = { history: [], id: 1, @@ -89,7 +89,7 @@ describe('TransactionListItemDetails Component', () => { assert.equal(wrapper.find(Button).length, 3) }) - it('should disable the Copy Tx ID and View In Etherscan buttons when tx hash is missing', () => { + it('should disable the Copy Tx ID and View In Etherscan buttons when tx hash is missing', function () { const transaction = { history: [], id: 1, @@ -128,7 +128,7 @@ describe('TransactionListItemDetails Component', () => { assert.strictEqual(buttons.at(1).prop('disabled'), true) }) - it('should render functional Copy Tx ID and View In Etherscan buttons when tx hash exists', () => { + it('should render functional Copy Tx ID and View In Etherscan buttons when tx hash exists', function () { const transaction = { history: [], id: 1, diff --git a/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js b/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js index ec1d580bd..f37bebb6f 100644 --- a/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js +++ b/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js @@ -4,8 +4,8 @@ import { mount } from 'enzyme' import TransactionStatus from '../transaction-status.component' import Tooltip from '../../../ui/tooltip-v2' -describe('TransactionStatus Component', () => { - it('should render APPROVED properly', () => { +describe('TransactionStatus Component', function () { + it('should render APPROVED properly', function () { const wrapper = mount( { assert.equal(wrapper.find(Tooltip).props().title, 'test-title') }) - it('should render SUBMITTED properly', () => { + it('should render SUBMITTED properly', function () { const wrapper = mount( (str2 ? str1 + str2 : str1) const metricsEvent = () => ({}) -describe('TransactionViewBalance Component', () => { - afterEach(() => { +describe('TransactionViewBalance Component', function () { + afterEach(function () { propsMethodSpies.showDepositModal.resetHistory() historySpies.push.resetHistory() }) - it('should render ETH balance properly', () => { + it('should render ETH balance properly', function () { const wrapper = shallow(( { assert.equal(historySpies.push.getCall(0).args[0], SEND_ROUTE) }) - it('should render token balance properly', () => { + it('should render token balance properly', function () { const token = { address: '0x35865238f0bec9d5ce6abff0fdaebe7b853dfcc5', decimals: '2', diff --git a/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js b/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js index 122115477..c8678e82b 100644 --- a/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js +++ b/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js @@ -4,9 +4,9 @@ import { shallow } from 'enzyme' import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display.component' import CurrencyDisplay from '../../../ui/currency-display' -describe('UserPreferencedCurrencyDisplay Component', () => { - describe('rendering', () => { - it('should render properly', () => { +describe('UserPreferencedCurrencyDisplay Component', function () { + describe('rendering', function () { + it('should render properly', function () { const wrapper = shallow( ) @@ -15,7 +15,7 @@ describe('UserPreferencedCurrencyDisplay Component', () => { assert.equal(wrapper.find(CurrencyDisplay).length, 1) }) - it('should pass all props to the CurrencyDisplay child component', () => { + it('should pass all props to the CurrencyDisplay child component', function () { const wrapper = shallow( { - describe('mapStateToProps()', () => { - it('should return the correct props', () => { +describe('UserPreferencedCurrencyDisplay container', function () { + describe('mapStateToProps()', function () { + it('should return the correct props', function () { const mockState = { metamask: { nativeCurrency: 'ETH', @@ -37,7 +37,7 @@ describe('UserPreferencedCurrencyDisplay container', () => { }) }) - it('should return the correct props when not in mainnet and showFiatInTestnets is true', () => { + it('should return the correct props when not in mainnet and showFiatInTestnets is true', function () { const mockState = { metamask: { nativeCurrency: 'ETH', @@ -60,8 +60,8 @@ describe('UserPreferencedCurrencyDisplay container', () => { }) }) - describe('mergeProps()', () => { - it('should return the correct props', () => { + describe('mergeProps()', function () { + it('should return the correct props', function () { const mockDispatchProps = {} const tests = [ diff --git a/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js b/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js index 3802e16f3..1ccd37776 100644 --- a/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js +++ b/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js @@ -4,9 +4,9 @@ import { shallow } from 'enzyme' import UserPreferencedCurrencyInput from '../user-preferenced-currency-input.component' import CurrencyInput from '../../../ui/currency-input' -describe('UserPreferencedCurrencyInput Component', () => { - describe('rendering', () => { - it('should render properly', () => { +describe('UserPreferencedCurrencyInput Component', function () { + describe('rendering', function () { + it('should render properly', function () { const wrapper = shallow( ) @@ -15,7 +15,7 @@ describe('UserPreferencedCurrencyInput Component', () => { assert.equal(wrapper.find(CurrencyInput).length, 1) }) - it('should render useFiat for CurrencyInput based on preferences.useNativeCurrencyAsPrimaryCurrency', () => { + it('should render useFiat for CurrencyInput based on preferences.useNativeCurrencyAsPrimaryCurrency', function () { const wrapper = shallow( { - describe('mapStateToProps()', () => { - it('should return the correct props', () => { +describe('UserPreferencedCurrencyInput container', function () { + describe('mapStateToProps()', function () { + it('should return the correct props', function () { const mockState = { metamask: { preferences: { diff --git a/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js b/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js index 41cfd51f9..6fa8ce08d 100644 --- a/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js +++ b/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js @@ -4,9 +4,9 @@ import { shallow } from 'enzyme' import UserPreferencedTokenInput from '../user-preferenced-token-input.component' import TokenInput from '../../../ui/token-input' -describe('UserPreferencedCurrencyInput Component', () => { - describe('rendering', () => { - it('should render properly', () => { +describe('UserPreferencedCurrencyInput Component', function () { + describe('rendering', function () { + it('should render properly', function () { const wrapper = shallow( ) @@ -15,7 +15,7 @@ describe('UserPreferencedCurrencyInput Component', () => { assert.equal(wrapper.find(TokenInput).length, 1) }) - it('should render showFiat for TokenInput based on preferences.useNativeCurrencyAsPrimaryCurrency', () => { + it('should render showFiat for TokenInput based on preferences.useNativeCurrencyAsPrimaryCurrency', function () { const wrapper = shallow( { - describe('mapStateToProps()', () => { - it('should return the correct props', () => { +describe('UserPreferencedTokenInput container', function () { + describe('mapStateToProps()', function () { + it('should return the correct props', function () { const mockState = { metamask: { preferences: { diff --git a/ui/app/components/ui/alert/tests/alert.test.js b/ui/app/components/ui/alert/tests/alert.test.js index d3de51bfb..7c3f32024 100644 --- a/ui/app/components/ui/alert/tests/alert.test.js +++ b/ui/app/components/ui/alert/tests/alert.test.js @@ -4,21 +4,21 @@ import sinon from 'sinon' import { shallow } from 'enzyme' import Alert from '../index' -describe('Alert', () => { +describe('Alert', function () { let wrapper - beforeEach(() => { + beforeEach(function () { wrapper = shallow( ) }) - it('renders nothing with no visible boolean in state', () => { + it('renders nothing with no visible boolean in state', function () { const alert = wrapper.find('.global-alert') assert.equal(alert.length, 0) }) - it('renders when visible in state is true, and message', () => { + it('renders when visible in state is true, and message', function () { const errorMessage = 'Error Message' wrapper.setState({ visible: true, msg: errorMessage }) @@ -30,7 +30,7 @@ describe('Alert', () => { assert.equal(errorText.text(), errorMessage) }) - it('calls component method when componentWillReceiveProps is called', () => { + it('calls component method when componentWillReceiveProps is called', function () { const animateInSpy = sinon.stub(wrapper.instance(), 'animateIn') const animateOutSpy = sinon.stub(wrapper.instance(), 'animateOut') diff --git a/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js b/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js index 5013c5b60..0b6e097f5 100644 --- a/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js +++ b/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js @@ -3,8 +3,8 @@ import assert from 'assert' import { shallow } from 'enzyme' import Breadcrumbs from '../breadcrumbs.component' -describe('Breadcrumbs Component', () => { - it('should render with the correct colors', () => { +describe('Breadcrumbs Component', function () { + it('should render with the correct colors', function () { const wrapper = shallow( { + beforeEach(function () { wrapper = shallow(( { + afterEach(function () { childButtonSpies.onClick.resetHistory() ButtonGroup.prototype.handleButtonClick.resetHistory() ButtonGroup.prototype.renderButtons.resetHistory() }) - describe('componentDidUpdate', () => { - it('should set the activeButtonIndex to the updated newActiveButtonIndex', () => { + describe('componentDidUpdate', function () { + it('should set the activeButtonIndex to the updated newActiveButtonIndex', function () { assert.equal(wrapper.state('activeButtonIndex'), 1) wrapper.setProps({ newActiveButtonIndex: 2 }) assert.equal(wrapper.state('activeButtonIndex'), 2) }) - it('should not set the activeButtonIndex to an updated newActiveButtonIndex that is not a number', () => { + it('should not set the activeButtonIndex to an updated newActiveButtonIndex that is not a number', function () { assert.equal(wrapper.state('activeButtonIndex'), 1) wrapper.setProps({ newActiveButtonIndex: null }) assert.equal(wrapper.state('activeButtonIndex'), 1) }) }) - describe('handleButtonClick', () => { - it('should set the activeButtonIndex', () => { + describe('handleButtonClick', function () { + it('should set the activeButtonIndex', function () { assert.equal(wrapper.state('activeButtonIndex'), 1) wrapper.instance().handleButtonClick(2) assert.equal(wrapper.state('activeButtonIndex'), 2) }) }) - describe('renderButtons', () => { - it('should render a button for each child', () => { + describe('renderButtons', function () { + it('should render a button for each child', function () { const childButtons = wrapper.find('.button-group__button') assert.equal(childButtons.length, 3) }) - it('should render the correct button with an active state', () => { + it('should render the correct button with an active state', function () { const childButtons = wrapper.find('.button-group__button') const activeChildButton = wrapper.find('.button-group__button--active') assert.deepEqual(childButtons.get(1), activeChildButton.get(0)) }) - it('should call handleButtonClick and the respective button\'s onClick method when a button is clicked', () => { + it('should call handleButtonClick and the respective button\'s onClick method when a button is clicked', function () { assert.equal(ButtonGroup.prototype.handleButtonClick.callCount, 0) assert.equal(childButtonSpies.onClick.callCount, 0) const childButtons = wrapper.find('.button-group__button') @@ -84,7 +84,7 @@ describe('ButtonGroup Component', function () { assert.equal(childButtonSpies.onClick.callCount, 3) }) - it('should render all child buttons as disabled if props.disabled is true', () => { + it('should render all child buttons as disabled if props.disabled is true', function () { const childButtons = wrapper.find('.button-group__button') childButtons.forEach(button => { assert.equal(button.props().disabled, undefined) @@ -94,19 +94,19 @@ describe('ButtonGroup Component', function () { assert.equal(disabledChildButtons.length, 3) }) - it('should render the children of the button', () => { + it('should render the children of the button', function () { const mockClass = wrapper.find('.mockClass') assert.equal(mockClass.length, 1) }) }) - describe('render', () => { - it('should render a div with the expected class and style', () => { + describe('render', function () { + it('should render a div with the expected class and style', function () { assert.equal(wrapper.find('div').at(0).props().className, 'someClassName') assert.deepEqual(wrapper.find('div').at(0).props().style, { color: 'red' }) }) - it('should call renderButtons when rendering', () => { + it('should call renderButtons when rendering', function () { assert.equal(ButtonGroup.prototype.renderButtons.callCount, 1) wrapper.instance().render() assert.equal(ButtonGroup.prototype.renderButtons.callCount, 2) diff --git a/ui/app/components/ui/card/tests/card.component.test.js b/ui/app/components/ui/card/tests/card.component.test.js index cea05033f..50cf3938b 100644 --- a/ui/app/components/ui/card/tests/card.component.test.js +++ b/ui/app/components/ui/card/tests/card.component.test.js @@ -3,8 +3,8 @@ import assert from 'assert' import { shallow } from 'enzyme' import Card from '../card.component' -describe('Card Component', () => { - it('should render a card with a title and child element', () => { +describe('Card Component', function () { + it('should render a card with a title and child element', function () { const wrapper = shallow( { - it('should render text with a className', () => { +describe('CurrencyDisplay Component', function () { + it('should render text with a className', function () { const wrapper = shallow(( { assert.equal(wrapper.text(), '$123.45') }) - it('should render text with a prefix', () => { + it('should render text with a prefix', function () { const wrapper = shallow(( { - describe('mapStateToProps()', () => { - it('should return the correct props', () => { +describe('CurrencyDisplay container', function () { + describe('mapStateToProps()', function () { + it('should return the correct props', function () { const mockState = { metamask: { conversionRate: 280.45, @@ -32,8 +32,8 @@ describe('CurrencyDisplay container', () => { }) }) - describe('mergeProps()', () => { - it('should return the correct props', () => { + describe('mergeProps()', function () { + it('should return the correct props', function () { const mockStateProps = { conversionRate: 280.45, currentCurrency: 'usd', diff --git a/ui/app/components/ui/currency-input/tests/currency-input.component.test.js b/ui/app/components/ui/currency-input/tests/currency-input.component.test.js index 5c132c08c..471cb9f6b 100644 --- a/ui/app/components/ui/currency-input/tests/currency-input.component.test.js +++ b/ui/app/components/ui/currency-input/tests/currency-input.component.test.js @@ -9,9 +9,9 @@ import CurrencyInput from '../currency-input.component' import UnitInput from '../../unit-input' import CurrencyDisplay from '../../currency-display' -describe('CurrencyInput Component', () => { - describe('rendering', () => { - it('should render properly without a suffix', () => { +describe('CurrencyInput Component', function () { + describe('rendering', function () { + it('should render properly without a suffix', function () { const wrapper = shallow( ) @@ -20,7 +20,7 @@ describe('CurrencyInput Component', () => { assert.equal(wrapper.find(UnitInput).length, 1) }) - it('should render properly with a suffix', () => { + it('should render properly with a suffix', function () { const mockStore = { metamask: { nativeCurrency: 'ETH', @@ -46,7 +46,7 @@ describe('CurrencyInput Component', () => { assert.equal(wrapper.find(CurrencyDisplay).length, 1) }) - it('should render properly with an ETH value', () => { + it('should render properly with an ETH value', function () { const mockStore = { metamask: { nativeCurrency: 'ETH', @@ -79,7 +79,7 @@ describe('CurrencyInput Component', () => { assert.equal(wrapper.find('.currency-display-component').text(), '$231.06USD') }) - it('should render properly with a fiat value', () => { + it('should render properly with a fiat value', function () { const mockStore = { metamask: { nativeCurrency: 'ETH', @@ -113,7 +113,7 @@ describe('CurrencyInput Component', () => { assert.equal(wrapper.find('.currency-display-component').text(), '0.004328ETH') }) - it('should render properly with a native value when hideFiat is true', () => { + it('should render properly with a native value when hideFiat is true', function () { const mockStore = { metamask: { nativeCurrency: 'ETH', @@ -153,16 +153,16 @@ describe('CurrencyInput Component', () => { }) }) - describe('handling actions', () => { + describe('handling actions', function () { const handleChangeSpy = sinon.spy() const handleBlurSpy = sinon.spy() - afterEach(() => { + afterEach(function () { handleChangeSpy.resetHistory() handleBlurSpy.resetHistory() }) - it('should call onChange on input changes with the hex value for ETH', () => { + it('should call onChange on input changes with the hex value for ETH', function () { const mockStore = { metamask: { nativeCurrency: 'ETH', @@ -202,7 +202,7 @@ describe('CurrencyInput Component', () => { assert.equal(currencyInputInstance.state.hexValue, 'de0b6b3a7640000') }) - it('should call onChange on input changes with the hex value for fiat', () => { + it('should call onChange on input changes with the hex value for fiat', function () { const mockStore = { metamask: { nativeCurrency: 'ETH', @@ -243,7 +243,7 @@ describe('CurrencyInput Component', () => { assert.equal(currencyInputInstance.state.hexValue, 'f602f2234d0ea') }) - it('should change the state and pass in a new decimalValue when props.value changes', () => { + it('should change the state and pass in a new decimalValue when props.value changes', function () { const mockStore = { metamask: { nativeCurrency: 'ETH', @@ -278,7 +278,7 @@ describe('CurrencyInput Component', () => { assert.equal(currencyInputInstance.find(UnitInput).props().value, 2) }) - it('should swap selected currency when swap icon is clicked', () => { + it('should swap selected currency when swap icon is clicked', function () { const mockStore = { metamask: { nativeCurrency: 'ETH', diff --git a/ui/app/components/ui/currency-input/tests/currency-input.container.test.js b/ui/app/components/ui/currency-input/tests/currency-input.container.test.js index f10abe09a..1806d6425 100644 --- a/ui/app/components/ui/currency-input/tests/currency-input.container.test.js +++ b/ui/app/components/ui/currency-input/tests/currency-input.container.test.js @@ -13,8 +13,8 @@ proxyquire('../currency-input.container.js', { }, }) -describe('CurrencyInput container', () => { - describe('mapStateToProps()', () => { +describe('CurrencyInput container', function () { + describe('mapStateToProps()', function () { const tests = [ // Test # 1 { @@ -127,11 +127,13 @@ describe('CurrencyInput container', () => { ] tests.forEach(({ mockState, expected, comment }) => { - it(comment, () => assert.deepEqual(mapStateToProps(mockState), expected)) + it(comment, function () { + return assert.deepEqual(mapStateToProps(mockState), expected) + }) }) }) - describe('mergeProps()', () => { + describe('mergeProps()', function () { const tests = [ // Test # 1 { @@ -178,7 +180,7 @@ describe('CurrencyInput container', () => { ] tests.forEach(({ mock: { stateProps, dispatchProps, ownProps }, expected, comment }) => { - it(comment, () => { + it(comment, function () { assert.deepEqual(mergeProps(stateProps, dispatchProps, ownProps), expected) }) }) diff --git a/ui/app/components/ui/error-message/tests/error-message.component.test.js b/ui/app/components/ui/error-message/tests/error-message.component.test.js index b4dcbde32..40e77161b 100644 --- a/ui/app/components/ui/error-message/tests/error-message.component.test.js +++ b/ui/app/components/ui/error-message/tests/error-message.component.test.js @@ -3,10 +3,10 @@ import assert from 'assert' import { shallow } from 'enzyme' import ErrorMessage from '../error-message.component' -describe('ErrorMessage Component', () => { +describe('ErrorMessage Component', function () { const t = key => `translate ${key}` - it('should render a message from props.errorMessage', () => { + it('should render a message from props.errorMessage', function () { const wrapper = shallow( { assert.equal(wrapper.find('.error-message__text').text(), 'ALERT: This is an error.') }) - it('should render a message translated from props.errorKey', () => { + it('should render a message translated from props.errorKey', function () { const wrapper = shallow( { - it('should render a prefixed hex as a decimal with a className', () => { +describe('HexToDecimal Component', function () { + it('should render a prefixed hex as a decimal with a className', function () { const wrapper = shallow(( { assert.equal(wrapper.text(), '12345') }) - it('should render an unprefixed hex as a decimal with a className', () => { + it('should render an unprefixed hex as a decimal with a className', function () { const wrapper = shallow(( { +describe('Identicon', function () { const state = { metamask: { useBlockie: false, @@ -16,7 +16,7 @@ describe('Identicon', () => { const mockStore = configureMockStore(middlewares) const store = mockStore(state) - it('renders default eth_logo identicon with no props', () => { + it('renders default eth_logo identicon with no props', function () { const wrapper = mount( ) @@ -24,7 +24,7 @@ describe('Identicon', () => { assert.equal(wrapper.find('img.balance-icon').prop('src'), './images/eth_logo.svg') }) - it('renders custom image and add className props', () => { + it('renders custom image and add className props', function () { const wrapper = mount( { assert.equal(wrapper.find('img.test-image').prop('src'), 'test-image') }) - it('renders div with address prop', () => { + it('renders div with address prop', function () { const wrapper = mount( { +describe('MetaFoxLogo', function () { - it('sets icon height and width to 42 by default', () => { + it('sets icon height and width to 42 by default', function () { const wrapper = mount( ) @@ -14,7 +14,7 @@ describe('MetaFoxLogo', () => { assert.equal(wrapper.find('img.app-header__metafox-logo--icon').prop('height'), 42) }) - it('does not set icon height and width when unsetIconHeight is true', () => { + it('does not set icon height and width when unsetIconHeight is true', function () { const wrapper = mount( ) diff --git a/ui/app/components/ui/page-container/page-container-footer/tests/page-container-footer.component.test.js b/ui/app/components/ui/page-container/page-container-footer/tests/page-container-footer.component.test.js index 86d06522f..f4f821f4c 100644 --- a/ui/app/components/ui/page-container/page-container-footer/tests/page-container-footer.component.test.js +++ b/ui/app/components/ui/page-container/page-container-footer/tests/page-container-footer.component.test.js @@ -5,12 +5,12 @@ import sinon from 'sinon' import Button from '../../../button' import PageFooter from '../page-container-footer.component' -describe('Page Footer', () => { +describe('Page Footer', function () { let wrapper const onCancel = sinon.spy() const onSubmit = sinon.spy() - beforeEach(() => { + beforeEach(function () { wrapper = shallow(( { )) }) - it('renders page container footer', () => { + it('renders page container footer', function () { assert.equal(wrapper.find('.page-container__footer').length, 1) }) - it('should render a footer inside page-container__footer when given children', () => { + it('should render a footer inside page-container__footer when given children', function () { const wrapper = shallow(
    Works
    @@ -38,42 +38,42 @@ describe('Page Footer', () => { assert.equal(wrapper.find('.page-container__footer footer').length, 1) }) - it('renders two button components', () => { + it('renders two button components', function () { assert.equal(wrapper.find(Button).length, 2) }) - describe('Cancel Button', () => { + describe('Cancel Button', function () { - it('has button type of default', () => { + it('has button type of default', function () { assert.equal(wrapper.find('.page-container__footer-button').first().prop('type'), 'default') }) - it('has children text of Cancel', () => { + it('has children text of Cancel', function () { assert.equal(wrapper.find('.page-container__footer-button').first().prop('children'), 'Cancel') }) - it('should call cancel when click is simulated', () => { + it('should call cancel when click is simulated', function () { wrapper.find('.page-container__footer-button').first().prop('onClick')() assert.equal(onCancel.callCount, 1) }) }) - describe('Submit Button', () => { + describe('Submit Button', function () { - it('assigns button type based on props', () => { + it('assigns button type based on props', function () { assert.equal(wrapper.find('.page-container__footer-button').last().prop('type'), 'Test Type') }) - it('has disabled prop', () => { + it('has disabled prop', function () { assert.equal(wrapper.find('.page-container__footer-button').last().prop('disabled'), false) }) - it('has children text when submitText prop exists', () => { + it('has children text when submitText prop exists', function () { assert.equal(wrapper.find('.page-container__footer-button').last().prop('children'), 'Submit') }) - it('should call submit when click is simulated', () => { + it('should call submit when click is simulated', function () { wrapper.find('.page-container__footer-button').last().prop('onClick')() assert.equal(onSubmit.callCount, 1) }) diff --git a/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js b/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js index 625dcb890..69f5e346b 100644 --- a/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js +++ b/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js @@ -4,10 +4,10 @@ import { shallow } from 'enzyme' import sinon from 'sinon' import PageContainerHeader from '../page-container-header.component' -describe('Page Container Header', () => { +describe('Page Container Header', function () { let wrapper, style, onBackButtonClick, onClose - beforeEach(() => { + beforeEach(function () { style = { test: 'style' } onBackButtonClick = sinon.spy() onClose = sinon.spy() @@ -25,27 +25,27 @@ describe('Page Container Header', () => { )) }) - describe('Render Header Row', () => { + describe('Render Header Row', function () { - it('renders back button', () => { + it('renders back button', function () { assert.equal(wrapper.find('.page-container__back-button').length, 1) assert.equal(wrapper.find('.page-container__back-button').text(), 'Back') }) - it('ensures style prop', () => { + it('ensures style prop', function () { assert.equal(wrapper.find('.page-container__back-button').props().style, style) }) - it('should call back button when click is simulated', () => { + it('should call back button when click is simulated', function () { wrapper.find('.page-container__back-button').prop('onClick')() assert.equal(onBackButtonClick.callCount, 1) }) }) - describe('Render', () => { + describe('Render', function () { let header, headerRow, pageTitle, pageSubtitle, pageClose, pageTab - beforeEach(() => { + beforeEach(function () { header = wrapper.find('.page-container__header--no-padding-bottom') headerRow = wrapper.find('.page-container__header-row') pageTitle = wrapper.find('.page-container__title') @@ -54,7 +54,7 @@ describe('Page Container Header', () => { pageTab = wrapper.find('.page-container__tabs') }) - it('renders page container', () => { + it('renders page container', function () { assert.equal(header.length, 1) assert.equal(headerRow.length, 1) assert.equal(pageTitle.length, 1) @@ -63,19 +63,19 @@ describe('Page Container Header', () => { assert.equal(pageTab.length, 1) }) - it('renders title', () => { + it('renders title', function () { assert.equal(pageTitle.text(), 'Test Title') }) - it('renders subtitle', () => { + it('renders subtitle', function () { assert.equal(pageSubtitle.text(), 'Test Subtitle') }) - it('renders tabs', () => { + it('renders tabs', function () { assert.equal(pageTab.text(), 'Test Tab') }) - it('should call close when click is simulated', () => { + it('should call close when click is simulated', function () { pageClose.prop('onClick')() assert.equal(onClose.callCount, 1) }) diff --git a/ui/app/components/ui/token-input/tests/token-input.component.test.js b/ui/app/components/ui/token-input/tests/token-input.component.test.js index 37fcf3e68..75f400c90 100644 --- a/ui/app/components/ui/token-input/tests/token-input.component.test.js +++ b/ui/app/components/ui/token-input/tests/token-input.component.test.js @@ -9,11 +9,11 @@ import TokenInput from '../token-input.component' import UnitInput from '../../unit-input' import CurrencyDisplay from '../../currency-display' -describe('TokenInput Component', () => { +describe('TokenInput Component', function () { const t = key => `translate ${key}` - describe('rendering', () => { - it('should render properly without a token', () => { + describe('rendering', function () { + it('should render properly without a token', function () { const wrapper = shallow( , { context: { t } } @@ -23,7 +23,7 @@ describe('TokenInput Component', () => { assert.equal(wrapper.find(UnitInput).length, 1) }) - it('should render properly with a token', () => { + it('should render properly with a token', function () { const mockStore = { metamask: { currentCurrency: 'usd', @@ -57,7 +57,7 @@ describe('TokenInput Component', () => { assert.equal(wrapper.find('.currency-input__conversion-component').text(), 'translate noConversionRateAvailable') }) - it('should render properly with a token and selectedTokenExchangeRate', () => { + it('should render properly with a token and selectedTokenExchangeRate', function () { const mockStore = { metamask: { currentCurrency: 'usd', @@ -91,7 +91,7 @@ describe('TokenInput Component', () => { assert.equal(wrapper.find(CurrencyDisplay).length, 1) }) - it('should render properly with a token value for ETH', () => { + it('should render properly with a token value for ETH', function () { const mockStore = { metamask: { currentCurrency: 'usd', @@ -125,7 +125,7 @@ describe('TokenInput Component', () => { assert.equal(wrapper.find('.currency-display-component').text(), '2ETH') }) - it('should render properly with a token value for fiat', () => { + it('should render properly with a token value for fiat', function () { const mockStore = { metamask: { currentCurrency: 'usd', @@ -160,7 +160,7 @@ describe('TokenInput Component', () => { assert.equal(wrapper.find('.currency-display-component').text(), '$462.12USD') }) - it('should render properly with a token value for fiat, but hideConversion is true', () => { + it('should render properly with a token value for fiat, but hideConversion is true', function () { const mockStore = { metamask: { currentCurrency: 'usd', @@ -203,16 +203,16 @@ describe('TokenInput Component', () => { }) }) - describe('handling actions', () => { + describe('handling actions', function () { const handleChangeSpy = sinon.spy() const handleBlurSpy = sinon.spy() - afterEach(() => { + afterEach(function () { handleChangeSpy.resetHistory() handleBlurSpy.resetHistory() }) - it('should call onChange on input changes with the hex value for ETH', () => { + it('should call onChange on input changes with the hex value for ETH', function () { const mockStore = { metamask: { currentCurrency: 'usd', @@ -254,7 +254,7 @@ describe('TokenInput Component', () => { assert.equal(tokenInputInstance.state.hexValue, '2710') }) - it('should call onChange on input changes with the hex value for fiat', () => { + it('should call onChange on input changes with the hex value for fiat', function () { const mockStore = { metamask: { currentCurrency: 'usd', @@ -297,7 +297,7 @@ describe('TokenInput Component', () => { assert.equal(tokenInputInstance.state.hexValue, '2710') }) - it('should change the state and pass in a new decimalValue when props.value changes', () => { + it('should change the state and pass in a new decimalValue when props.value changes', function () { const mockStore = { metamask: { currentCurrency: 'usd', diff --git a/ui/app/components/ui/token-input/tests/token-input.container.test.js b/ui/app/components/ui/token-input/tests/token-input.container.test.js index 6f87e64a5..a45cd2f1f 100644 --- a/ui/app/components/ui/token-input/tests/token-input.container.test.js +++ b/ui/app/components/ui/token-input/tests/token-input.container.test.js @@ -13,9 +13,9 @@ proxyquire('../token-input.container.js', { }, }) -describe('TokenInput container', () => { - describe('mapStateToProps()', () => { - it('should return the correct props when send is empty', () => { +describe('TokenInput container', function () { + describe('mapStateToProps()', function () { + it('should return the correct props when send is empty', function () { const mockState = { metamask: { currentCurrency: 'usd', @@ -50,7 +50,7 @@ describe('TokenInput container', () => { }) }) - it('should return the correct props when selectedTokenAddress is not found and send is populated', () => { + it('should return the correct props when selectedTokenAddress is not found and send is populated', function () { const mockState = { metamask: { currentCurrency: 'usd', @@ -85,7 +85,7 @@ describe('TokenInput container', () => { }) }) - it('should return the correct props when contractExchangeRates is populated', () => { + it('should return the correct props when contractExchangeRates is populated', function () { const mockState = { metamask: { currentCurrency: 'usd', @@ -122,7 +122,7 @@ describe('TokenInput container', () => { }) }) - it('should return the correct props when not in mainnet and showFiatInTestnets is false', () => { + it('should return the correct props when not in mainnet and showFiatInTestnets is false', function () { const mockState = { metamask: { currentCurrency: 'usd', @@ -157,7 +157,7 @@ describe('TokenInput container', () => { }) }) - it('should return the correct props when not in mainnet and showFiatInTestnets is true', () => { + it('should return the correct props when not in mainnet and showFiatInTestnets is true', function () { const mockState = { metamask: { currentCurrency: 'usd', @@ -192,7 +192,7 @@ describe('TokenInput container', () => { }) }) - it('should return the correct props when in mainnet and showFiatInTestnets is true', () => { + it('should return the correct props when in mainnet and showFiatInTestnets is true', function () { const mockState = { metamask: { currentCurrency: 'usd', @@ -228,8 +228,8 @@ describe('TokenInput container', () => { }) }) - describe('mergeProps()', () => { - it('should return the correct props', () => { + describe('mergeProps()', function () { + it('should return the correct props', function () { const mockStateProps = { currentCurrency: 'usd', selectedToken: { diff --git a/ui/app/components/ui/unit-input/tests/unit-input.component.test.js b/ui/app/components/ui/unit-input/tests/unit-input.component.test.js index 6b8dec7c8..a8a14cfac 100644 --- a/ui/app/components/ui/unit-input/tests/unit-input.component.test.js +++ b/ui/app/components/ui/unit-input/tests/unit-input.component.test.js @@ -4,9 +4,9 @@ import { shallow, mount } from 'enzyme' import sinon from 'sinon' import UnitInput from '../unit-input.component' -describe('UnitInput Component', () => { - describe('rendering', () => { - it('should render properly without a suffix', () => { +describe('UnitInput Component', function () { + describe('rendering', function () { + it('should render properly without a suffix', function () { const wrapper = shallow( ) @@ -15,7 +15,7 @@ describe('UnitInput Component', () => { assert.equal(wrapper.find('.unit-input__suffix').length, 0) }) - it('should render properly with a suffix', () => { + it('should render properly with a suffix', function () { const wrapper = shallow( { assert.equal(wrapper.find('.unit-input__suffix').text(), 'ETH') }) - it('should render properly with a child omponent', () => { + it('should render properly with a child omponent', function () { const wrapper = shallow(
    @@ -41,7 +41,7 @@ describe('UnitInput Component', () => { assert.equal(wrapper.find('.testing').text(), 'TESTCOMPONENT') }) - it('should render with an error class when props.error === true', () => { + it('should render with an error class when props.error === true', function () { const wrapper = shallow( { }) }) - describe('handling actions', () => { + describe('handling actions', function () { const handleChangeSpy = sinon.spy() const handleBlurSpy = sinon.spy() - afterEach(() => { + afterEach(function () { handleChangeSpy.resetHistory() handleBlurSpy.resetHistory() }) - it('should focus the input on component click', () => { + it('should focus the input on component click', function () { const wrapper = mount( ) @@ -76,7 +76,7 @@ describe('UnitInput Component', () => { assert.equal(handleFocusSpy.callCount, 1) }) - it('should call onChange on input changes with the value', () => { + it('should call onChange on input changes with the value', function () { const wrapper = mount( { assert.equal(wrapper.state('value'), 123) }) - it('should set the component state value with props.value', () => { + it('should set the component state value with props.value', function () { const wrapper = mount( { assert.equal(wrapper.state('value'), 123) }) - it('should update the component state value with props.value', () => { + it('should update the component state value with props.value', function () { const wrapper = mount( { - describe('State changes', () => { +describe('Confirm Transaction Duck', function () { + describe('State changes', function () { const mockState = { txData: { id: 1, @@ -73,11 +73,11 @@ describe('Confirm Transaction Duck', () => { fetchingData: false, } - it('should initialize state', () => { + it('should initialize state', function () { assert.deepEqual(ConfirmTransactionReducer(undefined, {}), initialState) }) - it('should return state unchanged if it does not match a dispatched actions type', () => { + it('should return state unchanged if it does not match a dispatched actions type', function () { assert.deepEqual( ConfirmTransactionReducer(mockState, { type: 'someOtherAction', @@ -87,7 +87,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should set txData when receiving a UPDATE_TX_DATA action', () => { + it('should set txData when receiving a UPDATE_TX_DATA action', function () { assert.deepEqual( ConfirmTransactionReducer(mockState, { type: UPDATE_TX_DATA, @@ -105,7 +105,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should clear txData when receiving a CLEAR_TX_DATA action', () => { + it('should clear txData when receiving a CLEAR_TX_DATA action', function () { assert.deepEqual( ConfirmTransactionReducer(mockState, { type: CLEAR_TX_DATA, @@ -117,7 +117,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should set tokenData when receiving a UPDATE_TOKEN_DATA action', () => { + it('should set tokenData when receiving a UPDATE_TOKEN_DATA action', function () { assert.deepEqual( ConfirmTransactionReducer(mockState, { type: UPDATE_TOKEN_DATA, @@ -135,7 +135,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should clear tokenData when receiving a CLEAR_TOKEN_DATA action', () => { + it('should clear tokenData when receiving a CLEAR_TOKEN_DATA action', function () { assert.deepEqual( ConfirmTransactionReducer(mockState, { type: CLEAR_TOKEN_DATA, @@ -147,7 +147,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should set methodData when receiving a UPDATE_METHOD_DATA action', () => { + it('should set methodData when receiving a UPDATE_METHOD_DATA action', function () { assert.deepEqual( ConfirmTransactionReducer(mockState, { type: UPDATE_METHOD_DATA, @@ -165,7 +165,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should clear methodData when receiving a CLEAR_METHOD_DATA action', () => { + it('should clear methodData when receiving a CLEAR_METHOD_DATA action', function () { assert.deepEqual( ConfirmTransactionReducer(mockState, { type: CLEAR_METHOD_DATA, @@ -177,7 +177,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should update transaction amounts when receiving an UPDATE_TRANSACTION_AMOUNTS action', () => { + it('should update transaction amounts when receiving an UPDATE_TRANSACTION_AMOUNTS action', function () { assert.deepEqual( ConfirmTransactionReducer(mockState, { type: UPDATE_TRANSACTION_AMOUNTS, @@ -196,7 +196,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should update transaction fees when receiving an UPDATE_TRANSACTION_FEES action', () => { + it('should update transaction fees when receiving an UPDATE_TRANSACTION_FEES action', function () { assert.deepEqual( ConfirmTransactionReducer(mockState, { type: UPDATE_TRANSACTION_FEES, @@ -215,7 +215,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should update transaction totals when receiving an UPDATE_TRANSACTION_TOTALS action', () => { + it('should update transaction totals when receiving an UPDATE_TRANSACTION_TOTALS action', function () { assert.deepEqual( ConfirmTransactionReducer(mockState, { type: UPDATE_TRANSACTION_TOTALS, @@ -234,7 +234,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should update tokenProps when receiving an UPDATE_TOKEN_PROPS action', () => { + it('should update tokenProps when receiving an UPDATE_TOKEN_PROPS action', function () { assert.deepEqual( ConfirmTransactionReducer(mockState, { type: UPDATE_TOKEN_PROPS, @@ -253,7 +253,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should update nonce when receiving an UPDATE_NONCE action', () => { + it('should update nonce when receiving an UPDATE_NONCE action', function () { assert.deepEqual( ConfirmTransactionReducer(mockState, { type: UPDATE_NONCE, @@ -266,7 +266,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should update nonce when receiving an UPDATE_TO_SMART_CONTRACT action', () => { + it('should update nonce when receiving an UPDATE_TO_SMART_CONTRACT action', function () { assert.deepEqual( ConfirmTransactionReducer(mockState, { type: UPDATE_TO_SMART_CONTRACT, @@ -279,7 +279,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should set fetchingData to true when receiving a FETCH_DATA_START action', () => { + it('should set fetchingData to true when receiving a FETCH_DATA_START action', function () { assert.deepEqual( ConfirmTransactionReducer(mockState, { type: FETCH_DATA_START, @@ -291,20 +291,20 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should set fetchingData to false when receiving a FETCH_DATA_END action', () => { + it('should set fetchingData to false when receiving a FETCH_DATA_END action', function () { assert.deepEqual( ConfirmTransactionReducer({ fetchingData: true }, { type: FETCH_DATA_END }), { fetchingData: false }, ) }) - it('should clear confirmTransaction when receiving a FETCH_DATA_END action', () => { + it('should clear confirmTransaction when receiving a FETCH_DATA_END action', function () { assert.deepEqual(ConfirmTransactionReducer(mockState, { type: CLEAR_CONFIRM_TRANSACTION }), initialState) }) }) - describe('Single actions', () => { - it('should create an action to update txData', () => { + describe('Single actions', function () { + it('should create an action to update txData', function () { const txData = { test: 123 } const expectedAction = { type: UPDATE_TX_DATA, @@ -317,7 +317,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should create an action to clear txData', () => { + it('should create an action to clear txData', function () { const expectedAction = { type: CLEAR_TX_DATA, } @@ -328,7 +328,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should create an action to update tokenData', () => { + it('should create an action to update tokenData', function () { const tokenData = { test: 123 } const expectedAction = { type: UPDATE_TOKEN_DATA, @@ -341,7 +341,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should create an action to clear tokenData', () => { + it('should create an action to clear tokenData', function () { const expectedAction = { type: CLEAR_TOKEN_DATA, } @@ -352,7 +352,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should create an action to update methodData', () => { + it('should create an action to update methodData', function () { const methodData = { test: 123 } const expectedAction = { type: UPDATE_METHOD_DATA, @@ -365,7 +365,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should create an action to clear methodData', () => { + it('should create an action to clear methodData', function () { const expectedAction = { type: CLEAR_METHOD_DATA, } @@ -376,7 +376,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should create an action to update transaction amounts', () => { + it('should create an action to update transaction amounts', function () { const transactionAmounts = { test: 123 } const expectedAction = { type: UPDATE_TRANSACTION_AMOUNTS, @@ -389,7 +389,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should create an action to update transaction fees', () => { + it('should create an action to update transaction fees', function () { const transactionFees = { test: 123 } const expectedAction = { type: UPDATE_TRANSACTION_FEES, @@ -402,7 +402,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should create an action to update transaction totals', () => { + it('should create an action to update transaction totals', function () { const transactionTotals = { test: 123 } const expectedAction = { type: UPDATE_TRANSACTION_TOTALS, @@ -415,7 +415,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should create an action to update tokenProps', () => { + it('should create an action to update tokenProps', function () { const tokenProps = { tokenDecimals: '1', tokenSymbol: 'abc', @@ -431,7 +431,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should create an action to update nonce', () => { + it('should create an action to update nonce', function () { const nonce = '0x1' const expectedAction = { type: UPDATE_NONCE, @@ -444,7 +444,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should create an action to set fetchingData to true', () => { + it('should create an action to set fetchingData to true', function () { const expectedAction = { type: FETCH_DATA_START, } @@ -455,7 +455,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should create an action to set fetchingData to false', () => { + it('should create an action to set fetchingData to false', function () { const expectedAction = { type: FETCH_DATA_END, } @@ -466,7 +466,7 @@ describe('Confirm Transaction Duck', () => { ) }) - it('should create an action to clear confirmTransaction', () => { + it('should create an action to clear confirmTransaction', function () { const expectedAction = { type: CLEAR_CONFIRM_TRANSACTION, } @@ -478,8 +478,8 @@ describe('Confirm Transaction Duck', () => { }) }) - describe('Thunk actions', () => { - beforeEach(() => { + describe('Thunk actions', function () { + beforeEach(function () { global.eth = { getCode: sinon.stub().callsFake( address => Promise.resolve(address && address.match(/isContract/) ? 'not-0x' : '0x') @@ -487,11 +487,11 @@ describe('Confirm Transaction Duck', () => { } }) - afterEach(() => { + afterEach(function () { global.eth.getCode.resetHistory() }) - it('updates txData and gas on an existing transaction in confirmTransaction', () => { + it('updates txData and gas on an existing transaction in confirmTransaction', function () { const mockState = { metamask: { conversionRate: 468.58, @@ -546,7 +546,7 @@ describe('Confirm Transaction Duck', () => { storeActions.forEach((action, index) => assert.equal(action.type, expectedActions[index])) }) - it('updates txData and updates gas values in confirmTransaction', () => { + it('updates txData and updates gas values in confirmTransaction', function () { const txData = { estimatedGas: '0x5208', gasLimitSpecified: false, @@ -614,7 +614,7 @@ describe('Confirm Transaction Duck', () => { storeActions.forEach((action, index) => assert.equal(action.type, expectedActions[index])) }) - it('updates confirmTransaction transaction', () => { + it('updates confirmTransaction transaction', function () { const mockState = { metamask: { conversionRate: 468.58, diff --git a/ui/app/ducks/gas/gas-duck.test.js b/ui/app/ducks/gas/gas-duck.test.js index 966d3d7b3..8583d61db 100644 --- a/ui/app/ducks/gas/gas-duck.test.js +++ b/ui/app/ducks/gas/gas-duck.test.js @@ -27,7 +27,7 @@ const { } = GasDuck const GasReducer = GasDuck.default -describe('Gas Duck', () => { +describe('Gas Duck', function () { let tempFetch let tempDateNow const mockEthGasApiResponse = { @@ -75,7 +75,7 @@ describe('Gas Duck', () => { }) }) - beforeEach(() => { + beforeEach(function () { tempFetch = global.fetch tempDateNow = global.Date.now @@ -85,7 +85,7 @@ describe('Gas Duck', () => { global.Date.now = () => 2000000 }) - afterEach(() => { + afterEach(function () { sinon.restore() global.fetch = tempFetch @@ -136,12 +136,12 @@ describe('Gas Duck', () => { const SET_BASIC_API_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_BASIC_API_ESTIMATES_LAST_RETRIEVED' const SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED' - describe('GasReducer()', () => { - it('should initialize state', () => { + describe('GasReducer()', function () { + it('should initialize state', function () { assert.deepEqual(GasReducer(undefined, {}), initState) }) - it('should return state unchanged if it does not match a dispatched actions type', () => { + it('should return state unchanged if it does not match a dispatched actions type', function () { assert.deepEqual( GasReducer(mockState, { type: 'someOtherAction', @@ -151,35 +151,35 @@ describe('Gas Duck', () => { ) }) - it('should set basicEstimateIsLoading to true when receiving a BASIC_GAS_ESTIMATE_LOADING_STARTED action', () => { + it('should set basicEstimateIsLoading to true when receiving a BASIC_GAS_ESTIMATE_LOADING_STARTED action', function () { assert.deepEqual( GasReducer(mockState, { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }), { basicEstimateIsLoading: true, ...mockState }, ) }) - it('should set basicEstimateIsLoading to false when receiving a BASIC_GAS_ESTIMATE_LOADING_FINISHED action', () => { + it('should set basicEstimateIsLoading to false when receiving a BASIC_GAS_ESTIMATE_LOADING_FINISHED action', function () { assert.deepEqual( GasReducer(mockState, { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }), { basicEstimateIsLoading: false, ...mockState }, ) }) - it('should set gasEstimatesLoading to true when receiving a GAS_ESTIMATE_LOADING_STARTED action', () => { + it('should set gasEstimatesLoading to true when receiving a GAS_ESTIMATE_LOADING_STARTED action', function () { assert.deepEqual( GasReducer(mockState, { type: GAS_ESTIMATE_LOADING_STARTED }), { gasEstimatesLoading: true, ...mockState } ) }) - it('should set gasEstimatesLoading to false when receiving a GAS_ESTIMATE_LOADING_FINISHED action', () => { + it('should set gasEstimatesLoading to false when receiving a GAS_ESTIMATE_LOADING_FINISHED action', function () { assert.deepEqual( GasReducer(mockState, { type: GAS_ESTIMATE_LOADING_FINISHED }), { gasEstimatesLoading: false, ...mockState }, ) }) - it('should set basicEstimates when receiving a SET_BASIC_GAS_ESTIMATE_DATA action', () => { + it('should set basicEstimates when receiving a SET_BASIC_GAS_ESTIMATE_DATA action', function () { assert.deepEqual( GasReducer(mockState, { type: SET_BASIC_GAS_ESTIMATE_DATA, @@ -189,7 +189,7 @@ describe('Gas Duck', () => { ) }) - it('should set priceAndTimeEstimates when receiving a SET_PRICE_AND_TIME_ESTIMATES action', () => { + it('should set priceAndTimeEstimates when receiving a SET_PRICE_AND_TIME_ESTIMATES action', function () { assert.deepEqual( GasReducer(mockState, { type: SET_PRICE_AND_TIME_ESTIMATES, @@ -199,7 +199,7 @@ describe('Gas Duck', () => { ) }) - it('should set customData.price when receiving a SET_CUSTOM_GAS_PRICE action', () => { + it('should set customData.price when receiving a SET_CUSTOM_GAS_PRICE action', function () { assert.deepEqual( GasReducer(mockState, { type: SET_CUSTOM_GAS_PRICE, @@ -209,7 +209,7 @@ describe('Gas Duck', () => { ) }) - it('should set customData.limit when receiving a SET_CUSTOM_GAS_LIMIT action', () => { + it('should set customData.limit when receiving a SET_CUSTOM_GAS_LIMIT action', function () { assert.deepEqual( GasReducer(mockState, { type: SET_CUSTOM_GAS_LIMIT, @@ -219,7 +219,7 @@ describe('Gas Duck', () => { ) }) - it('should set customData.total when receiving a SET_CUSTOM_GAS_TOTAL action', () => { + it('should set customData.total when receiving a SET_CUSTOM_GAS_TOTAL action', function () { assert.deepEqual( GasReducer(mockState, { type: SET_CUSTOM_GAS_TOTAL, @@ -229,7 +229,7 @@ describe('Gas Duck', () => { ) }) - it('should set priceAndTimeEstimatesLastRetrieved when receiving a SET_API_ESTIMATES_LAST_RETRIEVED action', () => { + it('should set priceAndTimeEstimatesLastRetrieved when receiving a SET_API_ESTIMATES_LAST_RETRIEVED action', function () { assert.deepEqual( GasReducer(mockState, { type: SET_API_ESTIMATES_LAST_RETRIEVED, @@ -239,7 +239,7 @@ describe('Gas Duck', () => { ) }) - it('should set priceAndTimeEstimatesLastRetrieved when receiving a SET_BASIC_API_ESTIMATES_LAST_RETRIEVED action', () => { + it('should set priceAndTimeEstimatesLastRetrieved when receiving a SET_BASIC_API_ESTIMATES_LAST_RETRIEVED action', function () { assert.deepEqual( GasReducer(mockState, { type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED, @@ -249,7 +249,7 @@ describe('Gas Duck', () => { ) }) - it('should set errors when receiving a SET_CUSTOM_GAS_ERRORS action', () => { + it('should set errors when receiving a SET_CUSTOM_GAS_ERRORS action', function () { assert.deepEqual( GasReducer(mockState, { type: SET_CUSTOM_GAS_ERRORS, @@ -259,7 +259,7 @@ describe('Gas Duck', () => { ) }) - it('should return the initial state in response to a RESET_CUSTOM_GAS_STATE action', () => { + it('should return the initial state in response to a RESET_CUSTOM_GAS_STATE action', function () { assert.deepEqual( GasReducer(mockState, { type: RESET_CUSTOM_GAS_STATE }), initState, @@ -267,20 +267,20 @@ describe('Gas Duck', () => { }) }) - describe('basicGasEstimatesLoadingStarted', () => { - it('should create the correct action', () => { + describe('basicGasEstimatesLoadingStarted', function () { + it('should create the correct action', function () { assert.deepEqual(basicGasEstimatesLoadingStarted(), { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }) }) }) - describe('basicGasEstimatesLoadingFinished', () => { - it('should create the correct action', () => { + describe('basicGasEstimatesLoadingFinished', function () { + it('should create the correct action', function () { assert.deepEqual(basicGasEstimatesLoadingFinished(), { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }) }) }) - describe('fetchBasicGasEstimates', () => { - it('should call fetch with the expected params', async () => { + describe('fetchBasicGasEstimates', function () { + it('should call fetch with the expected params', async function () { const mockDistpatch = sinon.spy() await fetchBasicGasEstimates()(mockDistpatch, () => ({ @@ -328,7 +328,7 @@ describe('Gas Duck', () => { ) }) - it('should fetch recently retrieved estimates from local storage', async () => { + it('should fetch recently retrieved estimates from local storage', async function () { const mockDistpatch = sinon.spy() fakeLocalStorage.loadLocalStorageData .withArgs('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED') @@ -374,7 +374,7 @@ describe('Gas Duck', () => { ) }) - it('should fallback to network if retrieving estimates from local storage fails', async () => { + it('should fallback to network if retrieving estimates from local storage fails', async function () { const mockDistpatch = sinon.spy() fakeLocalStorage.loadLocalStorageData .withArgs('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED') @@ -428,8 +428,8 @@ describe('Gas Duck', () => { }) }) - describe('fetchBasicGasAndTimeEstimates', () => { - it('should call fetch with the expected params', async () => { + describe('fetchBasicGasAndTimeEstimates', function () { + it('should call fetch with the expected params', async function () { const mockDistpatch = sinon.spy() await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ gas: Object.assign( @@ -488,7 +488,7 @@ describe('Gas Duck', () => { ) }) - it('should fetch recently retrieved estimates from local storage', async () => { + it('should fetch recently retrieved estimates from local storage', async function () { const mockDistpatch = sinon.spy() fakeLocalStorage.loadLocalStorageData .withArgs('BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED') @@ -547,7 +547,7 @@ describe('Gas Duck', () => { ) }) - it('should fallback to network if retrieving estimates from local storage fails', async () => { + it('should fallback to network if retrieving estimates from local storage fails', async function () { const mockDistpatch = sinon.spy() fakeLocalStorage.loadLocalStorageData .withArgs('BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED') @@ -610,8 +610,8 @@ describe('Gas Duck', () => { }) }) - describe('fetchGasEstimates', () => { - it('should call fetch with the expected params', async () => { + describe('fetchGasEstimates', function () { + it('should call fetch with the expected params', async function () { const mockDistpatch = sinon.spy() await fetchGasEstimates(5)(mockDistpatch, () => ({ gas: Object.assign( @@ -658,7 +658,7 @@ describe('Gas Duck', () => { ) }) - it('should not call fetch if the estimates were retrieved < 75000 ms ago', async () => { + it('should not call fetch if the estimates were retrieved < 75000 ms ago', async function () { const mockDistpatch = sinon.spy() await fetchGasEstimates(5)(mockDistpatch, () => ({ gas: Object.assign( @@ -702,8 +702,8 @@ describe('Gas Duck', () => { }) }) - describe('gasEstimatesLoadingStarted', () => { - it('should create the correct action', () => { + describe('gasEstimatesLoadingStarted', function () { + it('should create the correct action', function () { assert.deepEqual( gasEstimatesLoadingStarted(), { type: GAS_ESTIMATE_LOADING_STARTED } @@ -711,8 +711,8 @@ describe('Gas Duck', () => { }) }) - describe('gasEstimatesLoadingFinished', () => { - it('should create the correct action', () => { + describe('gasEstimatesLoadingFinished', function () { + it('should create the correct action', function () { assert.deepEqual( gasEstimatesLoadingFinished(), { type: GAS_ESTIMATE_LOADING_FINISHED } @@ -720,8 +720,8 @@ describe('Gas Duck', () => { }) }) - describe('setPricesAndTimeEstimates', () => { - it('should create the correct action', () => { + describe('setPricesAndTimeEstimates', function () { + it('should create the correct action', function () { assert.deepEqual( setPricesAndTimeEstimates('mockPricesAndTimeEstimates'), { type: SET_PRICE_AND_TIME_ESTIMATES, value: 'mockPricesAndTimeEstimates' } @@ -729,8 +729,8 @@ describe('Gas Duck', () => { }) }) - describe('setBasicGasEstimateData', () => { - it('should create the correct action', () => { + describe('setBasicGasEstimateData', function () { + it('should create the correct action', function () { assert.deepEqual( setBasicGasEstimateData('mockBasicEstimatData'), { type: SET_BASIC_GAS_ESTIMATE_DATA, value: 'mockBasicEstimatData' } @@ -738,8 +738,8 @@ describe('Gas Duck', () => { }) }) - describe('setCustomGasPrice', () => { - it('should create the correct action', () => { + describe('setCustomGasPrice', function () { + it('should create the correct action', function () { assert.deepEqual( setCustomGasPrice('mockCustomGasPrice'), { type: SET_CUSTOM_GAS_PRICE, value: 'mockCustomGasPrice' } @@ -747,8 +747,8 @@ describe('Gas Duck', () => { }) }) - describe('setCustomGasLimit', () => { - it('should create the correct action', () => { + describe('setCustomGasLimit', function () { + it('should create the correct action', function () { assert.deepEqual( setCustomGasLimit('mockCustomGasLimit'), { type: SET_CUSTOM_GAS_LIMIT, value: 'mockCustomGasLimit' } @@ -756,8 +756,8 @@ describe('Gas Duck', () => { }) }) - describe('setCustomGasTotal', () => { - it('should create the correct action', () => { + describe('setCustomGasTotal', function () { + it('should create the correct action', function () { assert.deepEqual( setCustomGasTotal('mockCustomGasTotal'), { type: SET_CUSTOM_GAS_TOTAL, value: 'mockCustomGasTotal' } @@ -765,8 +765,8 @@ describe('Gas Duck', () => { }) }) - describe('setCustomGasErrors', () => { - it('should create the correct action', () => { + describe('setCustomGasErrors', function () { + it('should create the correct action', function () { assert.deepEqual( setCustomGasErrors('mockErrorObject'), { type: SET_CUSTOM_GAS_ERRORS, value: 'mockErrorObject' } @@ -774,8 +774,8 @@ describe('Gas Duck', () => { }) }) - describe('setApiEstimatesLastRetrieved', () => { - it('should create the correct action', () => { + describe('setApiEstimatesLastRetrieved', function () { + it('should create the correct action', function () { assert.deepEqual( setApiEstimatesLastRetrieved(1234), { type: SET_API_ESTIMATES_LAST_RETRIEVED, value: 1234 } @@ -783,8 +783,8 @@ describe('Gas Duck', () => { }) }) - describe('resetCustomGasState', () => { - it('should create the correct action', () => { + describe('resetCustomGasState', function () { + it('should create the correct action', function () { assert.deepEqual( resetCustomGasState(), { type: RESET_CUSTOM_GAS_STATE } diff --git a/ui/app/ducks/send/send-duck.test.js b/ui/app/ducks/send/send-duck.test.js index 284cd37ac..3dda8728b 100644 --- a/ui/app/ducks/send/send-duck.test.js +++ b/ui/app/ducks/send/send-duck.test.js @@ -8,7 +8,7 @@ import SendReducer, { hideGasButtonGroup, } from './send.duck.js' -describe('Send Duck', () => { +describe('Send Duck', function () { const mockState = { mockProp: 123, } @@ -24,12 +24,12 @@ describe('Send Duck', () => { const SHOW_GAS_BUTTON_GROUP = 'metamask/send/SHOW_GAS_BUTTON_GROUP' const HIDE_GAS_BUTTON_GROUP = 'metamask/send/HIDE_GAS_BUTTON_GROUP' - describe('SendReducer()', () => { - it('should initialize state', () => { + describe('SendReducer()', function () { + it('should initialize state', function () { assert.deepEqual(SendReducer(undefined, {}), initState) }) - it('should return state unchanged if it does not match a dispatched actions type', () => { + it('should return state unchanged if it does not match a dispatched actions type', function () { assert.deepEqual( SendReducer(mockState, { type: 'someOtherAction', @@ -39,7 +39,7 @@ describe('Send Duck', () => { ) }) - it('should set toDropdownOpen to true when receiving a OPEN_TO_DROPDOWN action', () => { + it('should set toDropdownOpen to true when receiving a OPEN_TO_DROPDOWN action', function () { assert.deepEqual( SendReducer(mockState, { type: OPEN_TO_DROPDOWN, @@ -48,7 +48,7 @@ describe('Send Duck', () => { ) }) - it('should set toDropdownOpen to false when receiving a CLOSE_TO_DROPDOWN action', () => { + it('should set toDropdownOpen to false when receiving a CLOSE_TO_DROPDOWN action', function () { assert.deepEqual( SendReducer(mockState, { type: CLOSE_TO_DROPDOWN, @@ -57,21 +57,21 @@ describe('Send Duck', () => { ) }) - it('should set gasButtonGroupShown to true when receiving a SHOW_GAS_BUTTON_GROUP action', () => { + it('should set gasButtonGroupShown to true when receiving a SHOW_GAS_BUTTON_GROUP action', function () { assert.deepEqual( SendReducer({ ...mockState, gasButtonGroupShown: false }, { type: SHOW_GAS_BUTTON_GROUP }), { gasButtonGroupShown: true, ...mockState }, ) }) - it('should set gasButtonGroupShown to false when receiving a HIDE_GAS_BUTTON_GROUP action', () => { + it('should set gasButtonGroupShown to false when receiving a HIDE_GAS_BUTTON_GROUP action', function () { assert.deepEqual( SendReducer(mockState, { type: HIDE_GAS_BUTTON_GROUP }), { gasButtonGroupShown: false, ...mockState }, ) }) - it('should extend send.errors with the value of a UPDATE_SEND_ERRORS action', () => { + it('should extend send.errors with the value of a UPDATE_SEND_ERRORS action', function () { const modifiedMockState = { ...mockState, errors: { @@ -93,7 +93,7 @@ describe('Send Duck', () => { ) }) - it('should return the initial state in response to a RESET_SEND_STATE action', () => { + it('should return the initial state in response to a RESET_SEND_STATE action', function () { assert.deepEqual( SendReducer(mockState, { type: RESET_SEND_STATE, @@ -103,23 +103,23 @@ describe('Send Duck', () => { }) }) - describe('openToDropdown', () => { + describe('openToDropdown', function () { assert.deepEqual(openToDropdown(), { type: OPEN_TO_DROPDOWN }) }) - describe('closeToDropdown', () => { + describe('closeToDropdown', function () { assert.deepEqual(closeToDropdown(), { type: CLOSE_TO_DROPDOWN }) }) - describe('showGasButtonGroup', () => { + describe('showGasButtonGroup', function () { assert.deepEqual(showGasButtonGroup(), { type: SHOW_GAS_BUTTON_GROUP }) }) - describe('hideGasButtonGroup', () => { + describe('hideGasButtonGroup', function () { assert.deepEqual(hideGasButtonGroup(), { type: HIDE_GAS_BUTTON_GROUP }) }) - describe('updateSendErrors', () => { + describe('updateSendErrors', function () { assert.deepEqual(updateSendErrors('mockErrorObject'), { type: UPDATE_SEND_ERRORS, value: 'mockErrorObject' }) }) }) diff --git a/ui/app/helpers/higher-order-components/with-modal-props/tests/with-modal-props.test.js b/ui/app/helpers/higher-order-components/with-modal-props/tests/with-modal-props.test.js index 81a3512d1..08307c25f 100644 --- a/ui/app/helpers/higher-order-components/with-modal-props/tests/with-modal-props.test.js +++ b/ui/app/helpers/higher-order-components/with-modal-props/tests/with-modal-props.test.js @@ -19,8 +19,8 @@ const mockState = { }, } -describe('withModalProps', () => { - it('should return a component wrapped with modal state props', () => { +describe('withModalProps', function () { + it('should return a component wrapped with modal state props', function () { const TestComponent = () => (
    Testing
    ) diff --git a/ui/app/helpers/higher-order-components/with-token-tracker/tests/with-token-tracker.component.test.js b/ui/app/helpers/higher-order-components/with-token-tracker/tests/with-token-tracker.component.test.js index c7d22242d..92f9436ce 100644 --- a/ui/app/helpers/higher-order-components/with-token-tracker/tests/with-token-tracker.component.test.js +++ b/ui/app/helpers/higher-order-components/with-token-tracker/tests/with-token-tracker.component.test.js @@ -10,10 +10,10 @@ const { createTestProviderTools } = require('../../../../../../test/stub/provide const provider = createTestProviderTools({ scaffold: {} }).provider -describe('WithTokenTracker HOC', () => { +describe('WithTokenTracker HOC', function () { let wrapper - beforeEach(() => { + beforeEach(function () { const TokenTracker = withTokenTracker(TokenBalance) wrapper = shallow( { ) }) - it('#setError', () => { + it('#setError', function () { wrapper.instance().setError('test') assert.equal(wrapper.props().error, 'test') }) - it('#updateBalance', () => { + it('#updateBalance', function () { wrapper.instance().tracker = new TokenTracker({ provider, }) diff --git a/ui/app/helpers/utils/common.util.test.js b/ui/app/helpers/utils/common.util.test.js index 6259f4a89..169b780b6 100644 --- a/ui/app/helpers/utils/common.util.test.js +++ b/ui/app/helpers/utils/common.util.test.js @@ -1,9 +1,9 @@ import * as utils from './common.util' import assert from 'assert' -describe('Common utils', () => { - describe('camelCaseToCapitalize', () => { - it('should return a capitalized string from a camel-cased string', () => { +describe('Common utils', function () { + describe('camelCaseToCapitalize', function () { + it('should return a capitalized string from a camel-cased string', function () { const tests = [ { test: undefined, diff --git a/ui/app/helpers/utils/confirm-tx.util.test.js b/ui/app/helpers/utils/confirm-tx.util.test.js index e818601ca..bc39d984e 100644 --- a/ui/app/helpers/utils/confirm-tx.util.test.js +++ b/ui/app/helpers/utils/confirm-tx.util.test.js @@ -1,42 +1,42 @@ import * as utils from './confirm-tx.util' import assert from 'assert' -describe('Confirm Transaction utils', () => { - describe('increaseLastGasPrice', () => { - it('should increase the gasPrice by 10%', () => { +describe('Confirm Transaction utils', function () { + describe('increaseLastGasPrice', function () { + it('should increase the gasPrice by 10%', function () { const increasedGasPrice = utils.increaseLastGasPrice('0xa') assert.equal(increasedGasPrice, '0xb') }) - it('should prefix the result with 0x', () => { + it('should prefix the result with 0x', function () { const increasedGasPrice = utils.increaseLastGasPrice('a') assert.equal(increasedGasPrice, '0xb') }) }) - describe('hexGreaterThan', () => { - it('should return true if the first value is greater than the second value', () => { + describe('hexGreaterThan', function () { + it('should return true if the first value is greater than the second value', function () { assert.equal( utils.hexGreaterThan('0xb', '0xa'), true ) }) - it('should return false if the first value is less than the second value', () => { + it('should return false if the first value is less than the second value', function () { assert.equal( utils.hexGreaterThan('0xa', '0xb'), false ) }) - it('should return false if the first value is equal to the second value', () => { + it('should return false if the first value is equal to the second value', function () { assert.equal( utils.hexGreaterThan('0xa', '0xa'), false ) }) - it('should correctly compare prefixed and non-prefixed hex values', () => { + it('should correctly compare prefixed and non-prefixed hex values', function () { assert.equal( utils.hexGreaterThan('0xb', 'a'), true @@ -44,15 +44,15 @@ describe('Confirm Transaction utils', () => { }) }) - describe('getHexGasTotal', () => { - it('should multiply the hex gasLimit and hex gasPrice values together', () => { + describe('getHexGasTotal', function () { + it('should multiply the hex gasLimit and hex gasPrice values together', function () { assert.equal( utils.getHexGasTotal({ gasLimit: '0x5208', gasPrice: '0x3b9aca00' }), '0x1319718a5000' ) }) - it('should prefix the result with 0x', () => { + it('should prefix the result with 0x', function () { assert.equal( utils.getHexGasTotal({ gasLimit: '5208', gasPrice: '3b9aca00' }), '0x1319718a5000' @@ -60,15 +60,15 @@ describe('Confirm Transaction utils', () => { }) }) - describe('addEth', () => { - it('should add two values together rounding to 6 decimal places', () => { + describe('addEth', function () { + it('should add two values together rounding to 6 decimal places', function () { assert.equal( utils.addEth('0.12345678', '0'), '0.123457' ) }) - it('should add any number of values together rounding to 6 decimal places', () => { + it('should add any number of values together rounding to 6 decimal places', function () { assert.equal( utils.addEth('0.1', '0.02', '0.003', '0.0004', '0.00005', '0.000006', '0.0000007'), '0.123457' @@ -76,15 +76,15 @@ describe('Confirm Transaction utils', () => { }) }) - describe('addFiat', () => { - it('should add two values together rounding to 2 decimal places', () => { + describe('addFiat', function () { + it('should add two values together rounding to 2 decimal places', function () { assert.equal( utils.addFiat('0.12345678', '0'), '0.12' ) }) - it('should add any number of values together rounding to 2 decimal places', () => { + it('should add any number of values together rounding to 2 decimal places', function () { assert.equal( utils.addFiat('0.1', '0.02', '0.003', '0.0004', '0.00005', '0.000006', '0.0000007'), '0.12' @@ -92,8 +92,8 @@ describe('Confirm Transaction utils', () => { }) }) - describe('getValueFromWeiHex', () => { - it('should get the transaction amount in ETH', () => { + describe('getValueFromWeiHex', function () { + it('should get the transaction amount in ETH', function () { const ethTransactionAmount = utils.getValueFromWeiHex({ value: '0xde0b6b3a7640000', toCurrency: 'ETH', conversionRate: 468.58, numberOfDecimals: 6, }) @@ -101,7 +101,7 @@ describe('Confirm Transaction utils', () => { assert.equal(ethTransactionAmount, '1') }) - it('should get the transaction amount in fiat', () => { + it('should get the transaction amount in fiat', function () { const fiatTransactionAmount = utils.getValueFromWeiHex({ value: '0xde0b6b3a7640000', toCurrency: 'usd', conversionRate: 468.58, numberOfDecimals: 2, }) @@ -110,8 +110,8 @@ describe('Confirm Transaction utils', () => { }) }) - describe('getTransactionFee', () => { - it('should get the transaction fee in ETH', () => { + describe('getTransactionFee', function () { + it('should get the transaction fee in ETH', function () { const ethTransactionFee = utils.getTransactionFee({ value: '0x1319718a5000', toCurrency: 'ETH', conversionRate: 468.58, numberOfDecimals: 6, }) @@ -119,7 +119,7 @@ describe('Confirm Transaction utils', () => { assert.equal(ethTransactionFee, '0.000021') }) - it('should get the transaction fee in fiat', () => { + it('should get the transaction fee in fiat', function () { const fiatTransactionFee = utils.getTransactionFee({ value: '0x1319718a5000', toCurrency: 'usd', conversionRate: 468.58, numberOfDecimals: 2, }) @@ -128,8 +128,8 @@ describe('Confirm Transaction utils', () => { }) }) - describe('formatCurrency', () => { - it('should format USD values', () => { + describe('formatCurrency', function () { + it('should format USD values', function () { const value = utils.formatCurrency('123.45', 'usd') assert.equal(value, '$123.45') }) diff --git a/ui/app/helpers/utils/conversion-util.test.js b/ui/app/helpers/utils/conversion-util.test.js index 4420f9b4d..7b62faf32 100644 --- a/ui/app/helpers/utils/conversion-util.test.js +++ b/ui/app/helpers/utils/conversion-util.test.js @@ -2,19 +2,19 @@ import assert from 'assert' import { addCurrencies } from './conversion-util' -describe('conversion utils', () => { - describe('addCurrencies()', () => { - it('add whole numbers', () => { +describe('conversion utils', function () { + describe('addCurrencies()', function () { + it('add whole numbers', function () { const result = addCurrencies(3, 9) assert.equal(result.toNumber(), 12) }) - it('add decimals', () => { + it('add decimals', function () { const result = addCurrencies(1.3, 1.9) assert.equal(result.toNumber(), 3.2) }) - it('add repeating decimals', () => { + it('add repeating decimals', function () { const result = addCurrencies(1 / 3, 1 / 9) assert.equal(result.toNumber(), 0.4444444444444444) }) diff --git a/ui/app/helpers/utils/fetch-with-cache.test.js b/ui/app/helpers/utils/fetch-with-cache.test.js index 49af2f578..c30d23371 100644 --- a/ui/app/helpers/utils/fetch-with-cache.test.js +++ b/ui/app/helpers/utils/fetch-with-cache.test.js @@ -8,17 +8,17 @@ const fetchWithCache = proxyquire('./fetch-with-cache', { '../../../lib/local-storage-helpers': fakeLocalStorageHelpers, }).default -describe('Fetch with cache', () => { - beforeEach(() => { +describe('Fetch with cache', function () { + beforeEach(function () { fakeLocalStorageHelpers.loadLocalStorageData = sinon.stub() fakeLocalStorageHelpers.saveLocalStorageData = sinon.stub() }) - afterEach(() => { + afterEach(function () { sinon.restore() nock.cleanAll() }) - it('fetches a url', async () => { + it('fetches a url', async function () { nock('https://fetchwithcache.metamask.io') .get('/price') .reply(200, '{"average": 1}') @@ -29,7 +29,7 @@ describe('Fetch with cache', () => { }) }) - it('returns cached response', async () => { + it('returns cached response', async function () { nock('https://fetchwithcache.metamask.io') .get('/price') .reply(200, '{"average": 2}') @@ -47,7 +47,7 @@ describe('Fetch with cache', () => { }) }) - it('fetches URL again after cache refresh time has passed', async () => { + it('fetches URL again after cache refresh time has passed', async function () { nock('https://fetchwithcache.metamask.io') .get('/price') .reply(200, '{"average": 3}') @@ -65,7 +65,7 @@ describe('Fetch with cache', () => { }) }) - it('should abort the request when the custom timeout is hit', async () => { + it('should abort the request when the custom timeout is hit', async function () { nock('https://fetchwithcache.metamask.io') .get('/price') .delay(100) @@ -79,7 +79,7 @@ describe('Fetch with cache', () => { } }) - it('throws when the response is unsuccessful', async () => { + it('throws when the response is unsuccessful', async function () { nock('https://fetchwithcache.metamask.io') .get('/price') .reply(500, '{"average": 6}') @@ -92,7 +92,7 @@ describe('Fetch with cache', () => { } }) - it('throws when a POST request is attempted', async () => { + it('throws when a POST request is attempted', async function () { nock('https://fetchwithcache.metamask.io') .post('/price') .reply(200, '{"average": 7}') @@ -105,7 +105,7 @@ describe('Fetch with cache', () => { } }) - it('throws when the request has a truthy body', async () => { + it('throws when the request has a truthy body', async function () { nock('https://fetchwithcache.metamask.io') .get('/price') .reply(200, '{"average": 8}') @@ -118,7 +118,7 @@ describe('Fetch with cache', () => { } }) - it('throws when the request has an invalid Content-Type header', async () => { + it('throws when the request has an invalid Content-Type header', async function () { nock('https://fetchwithcache.metamask.io') .get('/price') .reply(200, '{"average": 9}') diff --git a/ui/app/helpers/utils/transactions.util.test.js b/ui/app/helpers/utils/transactions.util.test.js index 4a8ca5c9d..c561abb95 100644 --- a/ui/app/helpers/utils/transactions.util.test.js +++ b/ui/app/helpers/utils/transactions.util.test.js @@ -1,9 +1,9 @@ import * as utils from './transactions.util' import assert from 'assert' -describe('Transactions utils', () => { - describe('getTokenData', () => { - it('should return token data', () => { +describe('Transactions utils', function () { + describe('getTokenData', function () { + it('should return token data', function () { const tokenData = utils.getTokenData('0xa9059cbb00000000000000000000000050a9d56c2b8ba9a5c7f2c08c3d26e0499f23a7060000000000000000000000000000000000000000000000000000000000004e20') assert.ok(tokenData) const { name, params } = tokenData @@ -15,13 +15,13 @@ describe('Transactions utils', () => { assert.equal(value.type, 'uint256') }) - it('should not throw errors when called without arguments', () => { + it('should not throw errors when called without arguments', function () { assert.doesNotThrow(() => utils.getTokenData()) }) }) - describe('getStatusKey', () => { - it('should return the correct status', () => { + describe('getStatusKey', function () { + it('should return the correct status', function () { const tests = [ { transaction: { diff --git a/ui/app/helpers/utils/util.test.js b/ui/app/helpers/utils/util.test.js index 51ec92ee3..7c02cda14 100644 --- a/ui/app/helpers/utils/util.test.js +++ b/ui/app/helpers/utils/util.test.js @@ -121,18 +121,18 @@ describe('util', function () { }) describe('#formatBalance', function () { - it('when given nothing', function () { + it('should return None when given nothing', function () { const result = util.formatBalance() assert.equal(result, 'None', 'should return "None"') }) - it('should return eth as string followed by ETH', function () { + it('should return 1.0000 ETH', function () { const input = new ethUtil.BN(ethInWei, 10).toJSON() const result = util.formatBalance(input, 4) assert.equal(result, '1.0000 ETH') }) - it('should return eth as string followed by ETH', function () { + it('should return 0.500 ETH', function () { const input = new ethUtil.BN(ethInWei, 10).div(new ethUtil.BN('2', 10)).toJSON() const result = util.formatBalance(input, 3) assert.equal(result, '0.500 ETH') diff --git a/ui/app/pages/add-token/tests/add-token.test.js b/ui/app/pages/add-token/tests/add-token.test.js index 67465752b..761c7c5e8 100644 --- a/ui/app/pages/add-token/tests/add-token.test.js +++ b/ui/app/pages/add-token/tests/add-token.test.js @@ -6,7 +6,7 @@ import configureMockStore from 'redux-mock-store' import { mountWithRouter } from '../../../../../test/lib/render-helpers' import AddToken from '../index' -describe('Add Token', () => { +describe('Add Token', function () { let wrapper const state = { @@ -15,8 +15,7 @@ describe('Add Token', () => { }, } - const mockStore = configureMockStore() - const store = mockStore(state) + const store = configureMockStore()(state) const props = { history: { @@ -28,29 +27,28 @@ describe('Add Token', () => { identities: {}, } - before(() => { - wrapper = mountWithRouter( - - - , store - ) + describe('Add Token', function () { + before(function () { + wrapper = mountWithRouter( + + + , store + ) - wrapper.find({ name: 'customToken' }).simulate('click') - }) - - afterEach(() => { - props.history.push.reset() - }) + wrapper.find({ name: 'customToken' }).simulate('click') + }) - describe('Add Token', () => { + afterEach(function () { + props.history.push.reset() + }) - it('next button is disabled when no fields are populated', () => { + it('next button is disabled when no fields are populated', function () { const nextButton = wrapper.find('.button.btn-secondary.page-container__footer-button') assert.equal(nextButton.props().disabled, true) }) - it('edits token address', () => { + it('edits token address', function () { const tokenAddress = '0x617b3f8050a0BD94b6b1da02B4384eE5B4DF13F4' const event = { target: { value: tokenAddress } } const customAddress = wrapper.find('input#custom-address') @@ -60,7 +58,7 @@ describe('Add Token', () => { }) - it('edits token symbol', () => { + it('edits token symbol', function () { const tokenSymbol = 'META' const event = { target: { value: tokenSymbol } } const customAddress = wrapper.find('#custom-symbol') @@ -69,17 +67,16 @@ describe('Add Token', () => { assert.equal(wrapper.find('AddToken').instance().state.customSymbol, tokenSymbol) }) - it('edits token decimal precision', () => { + it('edits token decimal precision', function () { const tokenPrecision = '2' const event = { target: { value: tokenPrecision } } const customAddress = wrapper.find('#custom-decimals') customAddress.last().simulate('change', event) assert.equal(wrapper.find('AddToken').instance().state.customDecimals, tokenPrecision) - }) - it('next', () => { + it('next', function () { const nextButton = wrapper.find('.button.btn-secondary.page-container__footer-button') nextButton.simulate('click') @@ -88,7 +85,7 @@ describe('Add Token', () => { assert.equal(props.history.push.getCall(0).args[0], '/confirm-add-token') }) - it('cancels', () => { + it('cancels', function () { const cancelButton = wrapper.find('button.btn-default.page-container__footer-button') cancelButton.simulate('click') @@ -96,5 +93,4 @@ describe('Add Token', () => { assert.equal(props.history.push.getCall(0).args[0], '/') }) }) - }) diff --git a/ui/app/pages/confirm-transaction-base/tests/confirm-transaction-base.component.test.js b/ui/app/pages/confirm-transaction-base/tests/confirm-transaction-base.component.test.js index 8ca7ca4e7..92ac0c66b 100644 --- a/ui/app/pages/confirm-transaction-base/tests/confirm-transaction-base.component.test.js +++ b/ui/app/pages/confirm-transaction-base/tests/confirm-transaction-base.component.test.js @@ -1,9 +1,9 @@ import assert from 'assert' import { getMethodName } from '../confirm-transaction-base.component' -describe('ConfirmTransactionBase Component', () => { - describe('getMethodName', () => { - it('should get correct method names', () => { +describe('ConfirmTransactionBase Component', function () { + describe('getMethodName', function () { + it('should get correct method names', function () { assert.equal(getMethodName(undefined), '') assert.equal(getMethodName({}), '') assert.equal(getMethodName('confirm'), 'confirm') diff --git a/ui/app/pages/create-account/tests/create-account.test.js b/ui/app/pages/create-account/tests/create-account.test.js index b68a2241e..280f68d09 100644 --- a/ui/app/pages/create-account/tests/create-account.test.js +++ b/ui/app/pages/create-account/tests/create-account.test.js @@ -4,7 +4,7 @@ import sinon from 'sinon' import { mountWithRouter } from '../../../../../test/lib/render-helpers' import CreateAccountPage from '../index' -describe('Create Account Page', () => { +describe('Create Account Page', function () { let wrapper const props = { @@ -16,29 +16,29 @@ describe('Create Account Page', () => { }, } - before(() => { + before(function () { wrapper = mountWithRouter( ) }) - afterEach(() => { + afterEach(function () { props.history.push.resetHistory() }) - it('clicks create account and routes to new-account path', () => { + it('clicks create account and routes to new-account path', function () { const createAccount = wrapper.find('.new-account__tabs__tab').at(0) createAccount.simulate('click') assert.equal(props.history.push.getCall(0).args[0], '/new-account') }) - it('clicks import account and routes to import new account path', () => { + it('clicks import account and routes to import new account path', function () { const importAccount = wrapper.find('.new-account__tabs__tab').at(1) importAccount.simulate('click') assert.equal(props.history.push.getCall(0).args[0], '/new-account/import') }) - it('clicks connect HD Wallet and routes to connect new account path', () => { + it('clicks connect HD Wallet and routes to connect new account path', function () { const connectHdWallet = wrapper.find('.new-account__tabs__tab').at(2) connectHdWallet.simulate('click') assert.equal(props.history.push.getCall(0).args[0], '/new-account/connect') diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js index f6a2ad8ca..d7669384e 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js @@ -14,8 +14,8 @@ function shallowRender (props = {}, context = {}) { }) } -describe('ImportWithSeedPhrase Component', () => { - it('should render without error', () => { +describe('ImportWithSeedPhrase Component', function () { + it('should render without error', function () { const root = shallowRender({ onSubmit: sinon.spy(), }) @@ -23,8 +23,8 @@ describe('ImportWithSeedPhrase Component', () => { assert.equal(textareaCount, 1, 'should render 12 seed phrases') }) - describe('parseSeedPhrase', () => { - it('should handle a regular seed phrase', () => { + describe('parseSeedPhrase', function () { + it('should handle a regular seed phrase', function () { const root = shallowRender({ onSubmit: sinon.spy(), }) @@ -34,7 +34,7 @@ describe('ImportWithSeedPhrase Component', () => { assert.deepEqual(parseSeedPhrase('foo bar baz'), 'foo bar baz') }) - it('should trim extraneous whitespace from the given seed phrase', () => { + it('should trim extraneous whitespace from the given seed phrase', function () { const root = shallowRender({ onSubmit: sinon.spy(), }) @@ -44,7 +44,7 @@ describe('ImportWithSeedPhrase Component', () => { assert.deepEqual(parseSeedPhrase(' foo bar baz '), 'foo bar baz') }) - it('should return an empty string when given a whitespace-only string', () => { + it('should return an empty string when given a whitespace-only string', function () { const root = shallowRender({ onSubmit: sinon.spy(), }) @@ -54,7 +54,7 @@ describe('ImportWithSeedPhrase Component', () => { assert.deepEqual(parseSeedPhrase(' '), '') }) - it('should return an empty string when given a string with only symbols', () => { + it('should return an empty string when given a string with only symbols', function () { const root = shallowRender({ onSubmit: sinon.spy(), }) @@ -64,7 +64,7 @@ describe('ImportWithSeedPhrase Component', () => { assert.deepEqual(parseSeedPhrase('$'), '') }) - it('should return an empty string for both null and undefined', () => { + it('should return an empty string for both null and undefined', function () { const root = shallowRender({ onSubmit: sinon.spy(), }) diff --git a/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js b/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js index 23cebc68c..9be1db528 100644 --- a/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js +++ b/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js @@ -5,7 +5,7 @@ import { mountWithRouter } from '../../../../../../test/lib/render-helpers' import { DEFAULT_ROUTE } from '../../../../helpers/constants/routes' import EndOfFlowScreen from '../index' -describe('End of Flow Screen', () => { +describe('End of Flow Screen', function () { let wrapper const props = { @@ -15,24 +15,23 @@ describe('End of Flow Screen', () => { completeOnboarding: sinon.spy(), } - beforeEach(() => { + beforeEach(function () { wrapper = mountWithRouter( ) }) - it('renders', () => { + it('renders', function () { assert.equal(wrapper.length, 1) }) - it('', (done) => { + it('should navigate to the default route on click', function (done) { const endOfFlowButton = wrapper.find('.btn-primary.first-time-flow__button') endOfFlowButton.simulate('click') setImmediate(() => { assert(props.completeOnboarding.calledOnce) - assert(props.history.push.calledOnce) - assert.equal(props.history.push.getCall(0).args[0], DEFAULT_ROUTE) + assert(props.history.push.calledOnceWithExactly(DEFAULT_ROUTE)) done() }) }) diff --git a/ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js b/ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js index 4c2b60727..2e18f68f5 100644 --- a/ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js +++ b/ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js @@ -9,16 +9,16 @@ import { } from '../../../../helpers/constants/routes' import FirstTimeFlowSwitch from '../index' -describe('FirstTimeFlowSwitch', () => { +describe('FirstTimeFlowSwitch', function () { - it('redirects to /welcome route with no props', () => { + it('redirects to /welcome route with no props', function () { const wrapper = mountWithRouter( ) assert.equal(wrapper.find('Lifecycle').find({ to: { pathname: INITIALIZE_WELCOME_ROUTE } }).length, 1) }) - it('redirects to / route when completedOnboarding is true', () => { + it('redirects to / route when completedOnboarding is true', function () { const props = { completedOnboarding: true, } @@ -29,7 +29,7 @@ describe('FirstTimeFlowSwitch', () => { assert.equal(wrapper.find('Lifecycle').find({ to: { pathname: DEFAULT_ROUTE } }).length, 1) }) - it('redirects to /lock route when isUnlocked is true ', () => { + it('redirects to /lock route when isUnlocked is true ', function () { const props = { completedOnboarding: false, isUnlocked: true, @@ -42,7 +42,7 @@ describe('FirstTimeFlowSwitch', () => { assert.equal(wrapper.find('Lifecycle').find({ to: { pathname: LOCK_ROUTE } }).length, 1) }) - it('redirects to /welcome route when isInitialized is false', () => { + it('redirects to /welcome route when isInitialized is false', function () { const props = { completedOnboarding: false, isUnlocked: false, @@ -56,7 +56,7 @@ describe('FirstTimeFlowSwitch', () => { assert.equal(wrapper.find('Lifecycle').find({ to: { pathname: INITIALIZE_WELCOME_ROUTE } }).length, 1) }) - it('redirects to /unlock route when isInitialized is true', () => { + it('redirects to /unlock route when isInitialized is true', function () { const props = { completedOnboarding: false, isUnlocked: false, diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js b/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js index 3d70debda..9f1195d5d 100644 --- a/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js +++ b/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js @@ -5,39 +5,25 @@ import configureMockStore from 'redux-mock-store' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' import MetaMetricsOptIn from '../index' -describe('MetaMetricsOptIn', () => { - let wrapper - - const props = { - history: { - push: sinon.spy(), - }, - setParticipateInMetaMetrics: sinon.stub().resolves(), - participateInMetaMetrics: false, - } - - const mockStore = { - metamask: {}, - } - - const store = configureMockStore()(mockStore) - - beforeEach(() => { - wrapper = mountWithRouter( +describe('MetaMetricsOptIn', function () { + it('opt out of MetaMetrics', function () { + const props = { + history: { + push: sinon.spy(), + }, + setParticipateInMetaMetrics: sinon.stub().resolves(), + participateInMetaMetrics: false, + } + const store = configureMockStore()({ + metamask: {}, + }) + const wrapper = mountWithRouter( , store ) - }) - - afterEach(() => { - props.setParticipateInMetaMetrics.resetHistory() - }) - - it('opt out of metametrics', () => { const noThanksButton = wrapper.find('.btn-default.page-container__footer-button') noThanksButton.simulate('click') - assert(props.setParticipateInMetaMetrics.calledOnce) - assert.equal(props.setParticipateInMetaMetrics.getCall(0).args[0], false) + assert.ok(props.setParticipateInMetaMetrics.calledOnceWithExactly(false)) + props.setParticipateInMetaMetrics.resetHistory() }) - }) diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js index 41d170b5d..5e88da102 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js +++ b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js @@ -4,7 +4,7 @@ import sinon from 'sinon' import { mount } from 'enzyme' import RevealSeedPhrase from '../index' -describe('Reveal Seed Phrase', () => { +describe('Reveal Seed Phrase', function () { let wrapper const TEST_SEED = 'debris dizzy just program just float decrease vacant alarm reduce speak stadium' @@ -18,7 +18,7 @@ describe('Reveal Seed Phrase', () => { setCompletedOnboarding: sinon.spy(), } - beforeEach(() => { + beforeEach(function () { wrapper = mount( , { context: { @@ -29,13 +29,13 @@ describe('Reveal Seed Phrase', () => { ) }) - it('seed phrase', () => { + it('seed phrase', function () { const seedPhrase = wrapper.find('.reveal-seed-phrase__secret-words--hidden') assert.equal(seedPhrase.length, 1) assert.equal(seedPhrase.text(), TEST_SEED) }) - it('clicks to reveal', () => { + it('clicks to reveal', function () { const reveal = wrapper.find('.reveal-seed-phrase__secret-blocker') assert.equal(wrapper.state().isShowingSeedPhrase, false) diff --git a/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js b/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js index b61adfb7a..639407b38 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js +++ b/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js @@ -16,8 +16,8 @@ function shallowRender (props = {}, context = {}) { ) } -describe('ConfirmSeedPhrase Component', () => { - it('should render correctly', () => { +describe('ConfirmSeedPhrase Component', function () { + it('should render correctly', function () { const root = shallowRender({ seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬', }) @@ -29,7 +29,7 @@ describe('ConfirmSeedPhrase Component', () => { ) }) - it('should add/remove selected on click', () => { + it('should add/remove selected on click', function () { const metricsEventSpy = sinon.spy() const pushSpy = sinon.spy() const root = shallowRender( @@ -67,7 +67,7 @@ describe('ConfirmSeedPhrase Component', () => { ) }) - it('should render correctly on hover', () => { + it('should render correctly on hover', function () { const metricsEventSpy = sinon.spy() const pushSpy = sinon.spy() const root = shallowRender( @@ -100,7 +100,7 @@ describe('ConfirmSeedPhrase Component', () => { assert.equal(pendingSeeds.at(2).props().seedIndex, 1) }) - it('should insert seed in place on drop', () => { + it('should insert seed in place on drop', function () { const metricsEventSpy = sinon.spy() const pushSpy = sinon.spy() const root = shallowRender( @@ -131,7 +131,7 @@ describe('ConfirmSeedPhrase Component', () => { assert.deepEqual(root.state().pendingSeedIndices, [2, 0, 1]) }) - it('should submit correctly', async () => { + it('should submit correctly', async function () { const originalSeed = ['鼠', '牛', '虎', '兔', '龍', '蛇', '馬', '羊', '猴', '雞', '狗', '豬'] const metricsEventSpy = sinon.spy() const pushSpy = sinon.spy() diff --git a/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js b/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js index fe88c9a0b..05d394dfe 100644 --- a/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js +++ b/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js @@ -4,7 +4,7 @@ import sinon from 'sinon' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' import SelectAction from '../index' -describe('Selection Action', () => { +describe('Selection Action', function () { let wrapper const props = { @@ -15,18 +15,18 @@ describe('Selection Action', () => { }, } - beforeEach(() => { + beforeEach(function () { wrapper = mountWithRouter( ) }) - afterEach(() => { + afterEach(function () { props.setFirstTimeFlowType.resetHistory() props.history.push.resetHistory() }) - it('clicks import wallet to route to import FTF', () => { + it('clicks import wallet to route to import FTF', function () { const importWalletButton = wrapper.find('.btn-primary.first-time-flow__button').at(0) importWalletButton.simulate('click') @@ -35,7 +35,7 @@ describe('Selection Action', () => { assert(props.history.push.calledOnce) }) - it('clicks create wallet to route to create FTF ', () => { + it('clicks create wallet to route to create FTF ', function () { const createWalletButton = wrapper.find('.btn-primary.first-time-flow__button').at(1) createWalletButton.simulate('click') diff --git a/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js b/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js index 3649cef11..60996ff65 100644 --- a/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js +++ b/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js @@ -5,18 +5,18 @@ import configureMockStore from 'redux-mock-store' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' import Welcome from '../index' -describe('Welcome', () => { +describe('Welcome', function () { const mockStore = { metamask: {}, } const store = configureMockStore()(mockStore) - after(() => { + after(function () { sinon.restore() }) - it('routes to select action when participateInMetaMetrics is not initialized', () => { + it('routes to select action when participateInMetaMetrics is not initialized', function () { const props = { history: { @@ -34,7 +34,7 @@ describe('Welcome', () => { }) - it('routes to correct password when participateInMetaMetrics is initialized', () => { + it('routes to correct password when participateInMetaMetrics is initialized', function () { const props = { welcomeScreenSeen: true, diff --git a/ui/app/pages/keychains/tests/reveal-seed.test.js b/ui/app/pages/keychains/tests/reveal-seed.test.js index f63c5ae03..1a9dda8c3 100644 --- a/ui/app/pages/keychains/tests/reveal-seed.test.js +++ b/ui/app/pages/keychains/tests/reveal-seed.test.js @@ -4,27 +4,22 @@ import sinon from 'sinon' import { mount } from 'enzyme' import RevealSeedPage from '../reveal-seed' -describe('Reveal Seed Page', () => { - let wrapper - - const props = { - history: { - push: sinon.spy(), - }, - requestRevealSeedWords: sinon.stub().resolves(), - } - - beforeEach(() => { - wrapper = mount( +describe('Reveal Seed Page', function () { + it('form submit', function () { + const props = { + history: { + push: sinon.spy(), + }, + requestRevealSeedWords: sinon.stub().resolves(), + } + const wrapper = mount( , { context: { t: str => str, }, } ) - }) - it('form submit', () => { wrapper.find('form').simulate('submit') assert(props.requestRevealSeedWords.calledOnce) }) diff --git a/ui/app/pages/lock/tests/lock.test.js b/ui/app/pages/lock/tests/lock.test.js index ba412ebf8..78e1275f2 100644 --- a/ui/app/pages/lock/tests/lock.test.js +++ b/ui/app/pages/lock/tests/lock.test.js @@ -4,9 +4,9 @@ import sinon from 'sinon' import { mountWithRouter } from '../../../../../test/lib/render-helpers' import Lock from '../index' -describe('Lock', () => { +describe('Lock', function () { - it('replaces history with default route when isUnlocked false', () => { + it('replaces history with default route when isUnlocked false', function () { const props = { isUnlocked: false, @@ -23,7 +23,7 @@ describe('Lock', () => { }) - it('locks and pushes history with default route when isUnlocked true', (done) => { + it('locks and pushes history with default route when isUnlocked true', function (done) { const props = { isUnlocked: true, diff --git a/ui/app/pages/send/account-list-item/tests/account-list-item-component.test.js b/ui/app/pages/send/account-list-item/tests/account-list-item-component.test.js index e54a8c493..d4687c8dc 100644 --- a/ui/app/pages/send/account-list-item/tests/account-list-item-component.test.js +++ b/ui/app/pages/send/account-list-item/tests/account-list-item-component.test.js @@ -22,34 +22,34 @@ const propsMethodSpies = { describe('AccountListItem Component', function () { let wrapper - beforeEach(() => { - wrapper = shallow(( - } - /> - ), { context: { t: str => str + '_t' } }) - }) + describe('render', function () { + beforeEach(function () { + wrapper = shallow(( + } + /> + ), { context: { t: str => str + '_t' } }) + }) - afterEach(() => { - propsMethodSpies.handleClick.resetHistory() - }) + afterEach(function () { + propsMethodSpies.handleClick.resetHistory() + }) - describe('render', () => { - it('should render a div with the passed className', () => { + it('should render a div with the passed className', function () { assert.equal(wrapper.find('.mockClassName').length, 1) assert(wrapper.find('.mockClassName').is('div')) assert(wrapper.find('.mockClassName').hasClass('account-list-item')) }) - it('should call handleClick with the expected props when the root div is clicked', () => { + it('should call handleClick with the expected props when the root div is clicked', function () { const { onClick } = wrapper.find('.mockClassName').props() assert.equal(propsMethodSpies.handleClick.callCount, 0) onClick() @@ -60,42 +60,42 @@ describe('AccountListItem Component', function () { ) }) - it('should have a top row div', () => { + it('should have a top row div', function () { assert.equal(wrapper.find('.mockClassName > .account-list-item__top-row').length, 1) assert(wrapper.find('.mockClassName > .account-list-item__top-row').is('div')) }) - it('should have an identicon, name and icon in the top row', () => { + it('should have an identicon, name and icon in the top row', function () { const topRow = wrapper.find('.mockClassName > .account-list-item__top-row') assert.equal(topRow.find(Identicon).length, 1) assert.equal(topRow.find('.account-list-item__account-name').length, 1) assert.equal(topRow.find('.account-list-item__icon').length, 1) }) - it('should show the account name if it exists', () => { + it('should show the account name if it exists', function () { const topRow = wrapper.find('.mockClassName > .account-list-item__top-row') assert.equal(topRow.find('.account-list-item__account-name').text(), 'mockName') }) - it('should show the account address if there is no name', () => { + it('should show the account address if there is no name', function () { wrapper.setProps({ account: { address: 'addressButNoName' } }) const topRow = wrapper.find('.mockClassName > .account-list-item__top-row') assert.equal(topRow.find('.account-list-item__account-name').text(), 'addressButNoName') }) - it('should render the passed icon', () => { + it('should render the passed icon', function () { const topRow = wrapper.find('.mockClassName > .account-list-item__top-row') assert(topRow.find('.account-list-item__icon').childAt(0).is('i')) assert(topRow.find('.account-list-item__icon').childAt(0).hasClass('mockIcon')) }) - it('should not render an icon if none is passed', () => { + it('should not render an icon if none is passed', function () { wrapper.setProps({ icon: null }) const topRow = wrapper.find('.mockClassName > .account-list-item__top-row') assert.equal(topRow.find('.account-list-item__icon').length, 0) }) - it('should render the account address as a checksumAddress if displayAddress is true and name is provided', () => { + it('should render the account address as a checksumAddress if displayAddress is true and name is provided', function () { wrapper.setProps({ displayAddress: true }) assert.equal(wrapper.find('.account-list-item__account-address').length, 1) assert.equal(wrapper.find('.account-list-item__account-address').text(), 'mockCheckSumAddress') @@ -105,17 +105,17 @@ describe('AccountListItem Component', function () { ) }) - it('should not render the account address as a checksumAddress if displayAddress is false', () => { + it('should not render the account address as a checksumAddress if displayAddress is false', function () { wrapper.setProps({ displayAddress: false }) assert.equal(wrapper.find('.account-list-item__account-address').length, 0) }) - it('should not render the account address as a checksumAddress if name is not provided', () => { + it('should not render the account address as a checksumAddress if name is not provided', function () { wrapper.setProps({ account: { address: 'someAddressButNoName' } }) assert.equal(wrapper.find('.account-list-item__account-address').length, 0) }) - it('should render a CurrencyDisplay with the correct props if displayBalance is true', () => { + it('should render a CurrencyDisplay with the correct props if displayBalance is true', function () { wrapper.setProps({ displayBalance: true }) assert.equal(wrapper.find(UserPreferencedCurrencyDisplay).length, 2) assert.deepEqual( @@ -128,7 +128,7 @@ describe('AccountListItem Component', function () { ) }) - it('should only render one CurrencyDisplay if showFiat is false', () => { + it('should only render one CurrencyDisplay if showFiat is false', function () { wrapper.setProps({ showFiat: false, displayBalance: true }) assert.equal(wrapper.find(UserPreferencedCurrencyDisplay).length, 1) assert.deepEqual( @@ -141,10 +141,9 @@ describe('AccountListItem Component', function () { ) }) - it('should not render a CurrencyDisplay if displayBalance is false', () => { + it('should not render a CurrencyDisplay if displayBalance is false', function () { wrapper.setProps({ displayBalance: false }) assert.equal(wrapper.find(UserPreferencedCurrencyDisplay).length, 0) }) - }) }) diff --git a/ui/app/pages/send/account-list-item/tests/account-list-item-container.test.js b/ui/app/pages/send/account-list-item/tests/account-list-item-container.test.js index 0c0fd83aa..a1c2434e3 100644 --- a/ui/app/pages/send/account-list-item/tests/account-list-item-container.test.js +++ b/ui/app/pages/send/account-list-item/tests/account-list-item-container.test.js @@ -24,11 +24,11 @@ proxyquire('../account-list-item.container.js', { }, }) -describe('account-list-item container', () => { +describe('account-list-item container', function () { - describe('mapStateToProps()', () => { + describe('mapStateToProps()', function () { - it('should map the correct properties to props', () => { + it('should map the correct properties to props', function () { assert.deepEqual(mapStateToProps({ isMainnet: true, showFiatInTestnets: false }), { nativeCurrency: 'mockNativeCurrency', balanceIsCached: 'mockBalanceIsCached', @@ -36,7 +36,7 @@ describe('account-list-item container', () => { }) }) - it('should map the correct properties to props when in mainnet and showFiatInTestnet is true', () => { + it('should map the correct properties to props when in mainnet and showFiatInTestnet is true', function () { assert.deepEqual(mapStateToProps({ isMainnet: true, showFiatInTestnets: true }), { nativeCurrency: 'mockNativeCurrency', balanceIsCached: 'mockBalanceIsCached', @@ -44,7 +44,7 @@ describe('account-list-item container', () => { }) }) - it('should map the correct properties to props when not in mainnet and showFiatInTestnet is true', () => { + it('should map the correct properties to props when not in mainnet and showFiatInTestnet is true', function () { assert.deepEqual(mapStateToProps({ isMainnet: false, showFiatInTestnets: true }), { nativeCurrency: 'mockNativeCurrency', balanceIsCached: 'mockBalanceIsCached', @@ -52,7 +52,7 @@ describe('account-list-item container', () => { }) }) - it('should map the correct properties to props when not in mainnet and showFiatInTestnet is false', () => { + it('should map the correct properties to props when not in mainnet and showFiatInTestnet is false', function () { assert.deepEqual(mapStateToProps({ isMainnet: false, showFiatInTestnets: false }), { nativeCurrency: 'mockNativeCurrency', balanceIsCached: 'mockBalanceIsCached', diff --git a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js index 115ad5b62..7b345409e 100644 --- a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js +++ b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js @@ -18,7 +18,7 @@ describe('AddRecipient Component', function () { let wrapper let instance - beforeEach(() => { + beforeEach(function () { wrapper = shallow(( { + afterEach(function () { propsMethodSpies.closeToDropdown.resetHistory() propsMethodSpies.openToDropdown.resetHistory() propsMethodSpies.updateSendTo.resetHistory() @@ -50,9 +50,9 @@ describe('AddRecipient Component', function () { propsMethodSpies.updateGas.resetHistory() }) - describe('selectRecipient', () => { + describe('selectRecipient', function () { - it('should call updateSendTo', () => { + it('should call updateSendTo', function () { assert.equal(propsMethodSpies.updateSendTo.callCount, 0) instance.selectRecipient('mockTo2', 'mockNickname') assert.equal(propsMethodSpies.updateSendTo.callCount, 1) @@ -62,19 +62,19 @@ describe('AddRecipient Component', function () { ) }) - it('should call updateGas if there is no to error', () => { + it('should call updateGas if there is no to error', function () { assert.equal(propsMethodSpies.updateGas.callCount, 0) instance.selectRecipient(false) assert.equal(propsMethodSpies.updateGas.callCount, 1) }) }) - describe('render', () => { - it('should render a component', () => { + describe('render', function () { + it('should render a component', function () { assert.equal(wrapper.find('.send__select-recipient-wrapper').length, 1) }) - it('should render no content if there are no recents, transfers, and contacts', () => { + it('should render no content if there are no recents, transfers, and contacts', function () { wrapper.setProps({ ownedAccounts: [], addressBook: [], @@ -84,7 +84,7 @@ describe('AddRecipient Component', function () { assert.equal(wrapper.find('.send__select-recipient-wrapper__group').length, 0) }) - it('should render transfer', () => { + it('should render transfer', function () { wrapper.setProps({ ownedAccounts: [{ address: '0x123', name: '123' }, { address: '0x124', name: '124' }], addressBook: [{ address: '0x456', name: 'test-name' }], @@ -99,7 +99,7 @@ describe('AddRecipient Component', function () { assert.equal(groups.shallow().find('.send__select-recipient-wrapper__group').length, 1) }) - it('should render ContactList', () => { + it('should render ContactList', function () { wrapper.setProps({ ownedAccounts: [{ address: '0x123', name: '123' }, { address: '0x124', name: '124' }], addressBook: [{ address: '0x125' }], @@ -110,7 +110,7 @@ describe('AddRecipient Component', function () { assert.equal(contactList.length, 1) }) - it('should render contacts', () => { + it('should render contacts', function () { wrapper.setProps({ addressBook: [ { address: '0x125', name: 'alice' }, @@ -129,7 +129,7 @@ describe('AddRecipient Component', function () { assert.equal(groups.find('.send__select-recipient-wrapper__group-item').length, 0) }) - it('should render error when query has no results', () => { + it('should render error when query has no results', function () { wrapper.setProps({ addressBook: [], toError: 'bad', @@ -144,7 +144,7 @@ describe('AddRecipient Component', function () { assert.equal(dialog.length, 1) }) - it('should render error when query has ens does not resolve', () => { + it('should render error when query has ens does not resolve', function () { wrapper.setProps({ addressBook: [], toError: 'bad', @@ -160,7 +160,7 @@ describe('AddRecipient Component', function () { assert.equal(dialog.length, 1) }) - it('should render warning', () => { + it('should render warning', function () { wrapper.setProps({ addressBook: [], query: 'yo', @@ -174,7 +174,7 @@ describe('AddRecipient Component', function () { assert.equal(dialog.length, 1) }) - it('should not render error when ens resolved', () => { + it('should not render error when ens resolved', function () { wrapper.setProps({ addressBook: [], toError: 'bad', @@ -186,7 +186,7 @@ describe('AddRecipient Component', function () { assert.equal(dialog.length, 0) }) - it('should not render error when query has results', () => { + it('should not render error when query has results', function () { wrapper.setProps({ addressBook: [ { address: '0x125', name: 'alice' }, diff --git a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-container.test.js b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-container.test.js index 5ca0b2c23..a95b90293 100644 --- a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-container.test.js +++ b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-container.test.js @@ -29,11 +29,9 @@ proxyquire('../add-recipient.container.js', { '../../../../store/actions': actionSpies, }) -describe('add-recipient container', () => { - - describe('mapStateToProps()', () => { - - it('should map the correct properties to props', () => { +describe('add-recipient container', function () { + describe('mapStateToProps()', function () { + it('should map the correct properties to props', function () { assert.deepEqual(mapStateToProps('mockState'), { addressBook: [{ name: 'mockAddressBook:mockState' }], contacts: [{ name: 'mockAddressBook:mockState' }], @@ -44,20 +42,14 @@ describe('add-recipient container', () => { nonContacts: [], }) }) - }) - describe('mapDispatchToProps()', () => { - let dispatchSpy - let mapDispatchToPropsObject + describe('mapDispatchToProps()', function () { + describe('updateSendTo()', function () { + const dispatchSpy = sinon.spy() + const mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) - beforeEach(() => { - dispatchSpy = sinon.spy() - mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) - }) - - describe('updateSendTo()', () => { - it('should dispatch an action', () => { + it('should dispatch an action', function () { mapDispatchToPropsObject.updateSendTo('mockTo', 'mockNickname') assert(dispatchSpy.calledOnce) assert(actionSpies.updateSendTo.calledOnce) @@ -68,5 +60,4 @@ describe('add-recipient container', () => { }) }) }) - }) diff --git a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-selectors.test.js b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-selectors.test.js index 82f481187..19ef6f860 100644 --- a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-selectors.test.js +++ b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-selectors.test.js @@ -5,10 +5,10 @@ import { sendToIsInError, } from '../add-recipient.selectors.js' -describe('add-recipient selectors', () => { +describe('add-recipient selectors', function () { - describe('getToDropdownOpen()', () => { - it('should return send.getToDropdownOpen', () => { + describe('getToDropdownOpen()', function () { + it('should return send.getToDropdownOpen', function () { const state = { send: { toDropdownOpen: false, @@ -19,8 +19,8 @@ describe('add-recipient selectors', () => { }) }) - describe('sendToIsInError()', () => { - it('should return true if send.errors.to is truthy', () => { + describe('sendToIsInError()', function () { + it('should return true if send.errors.to is truthy', function () { const state = { send: { errors: { @@ -32,7 +32,7 @@ describe('add-recipient selectors', () => { assert.equal(sendToIsInError(state), true) }) - it('should return false if send.errors.to is falsy', () => { + it('should return false if send.errors.to is falsy', function () { const state = { send: { errors: { @@ -45,8 +45,8 @@ describe('add-recipient selectors', () => { }) }) - describe('getTokens()', () => { - it('should return empty array if no tokens in state', () => { + describe('getTokens()', function () { + it('should return empty array if no tokens in state', function () { const state = { metamask: { tokens: [], diff --git a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js index 5549c2503..0b1e317cd 100644 --- a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js +++ b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js @@ -22,82 +22,82 @@ const { getToWarningObject, } = toRowUtils -describe('add-recipient utils', () => { +describe('add-recipient utils', function () { - describe('getToErrorObject()', () => { - it('should return a required error if to is falsy', () => { + describe('getToErrorObject()', function () { + it('should return a required error if to is falsy', function () { assert.deepEqual(getToErrorObject(null), { to: REQUIRED_ERROR, }) }) - it('should return null if to is falsy and hexData is truthy', () => { + it('should return null if to is falsy and hexData is truthy', function () { assert.deepEqual(getToErrorObject(null, undefined, true), { to: null, }) }) - it('should return an invalid recipient error if to is truthy but invalid', () => { + it('should return an invalid recipient error if to is truthy but invalid', function () { assert.deepEqual(getToErrorObject('mockInvalidTo'), { to: INVALID_RECIPIENT_ADDRESS_ERROR, }) }) - it('should return null if to is truthy and valid', () => { + it('should return null if to is truthy and valid', function () { assert.deepEqual(getToErrorObject('0xabc123'), { to: null, }) }) - it('should return the passed error if to is truthy but invalid if to is truthy and valid', () => { + it('should return the passed error if to is truthy but invalid if to is truthy and valid', function () { assert.deepEqual(getToErrorObject('invalid #$ 345878', 'someExplicitError'), { to: 'someExplicitError', }) }) - it('should return null if to is truthy but part of state tokens', () => { + it('should return null if to is truthy but part of state tokens', function () { assert.deepEqual(getToErrorObject('0xabc123', undefined, false, [{ 'address': '0xabc123' }], { 'address': '0xabc123' }), { to: null, }) }) - it('should null if to is truthy part of tokens but selectedToken falsy', () => { + it('should null if to is truthy part of tokens but selectedToken falsy', function () { assert.deepEqual(getToErrorObject('0xabc123', undefined, false, [{ 'address': '0xabc123' }]), { to: null, }) }) - it('should return null if to is truthy but part of contract metadata', () => { + it('should return null if to is truthy but part of contract metadata', function () { assert.deepEqual(getToErrorObject('0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', undefined, false, [{ 'address': '0xabc123' }], { 'address': '0xabc123' }), { to: null, }) }) - it('should null if to is truthy part of contract metadata but selectedToken falsy', () => { + it('should null if to is truthy part of contract metadata but selectedToken falsy', function () { assert.deepEqual(getToErrorObject('0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', undefined, false, [{ 'address': '0xabc123' }], { 'address': '0xabc123' }), { to: null, }) }) }) - describe('getToWarningObject()', () => { - it('should return a known address recipient if to is truthy but part of state tokens', () => { + describe('getToWarningObject()', function () { + it('should return a known address recipient if to is truthy but part of state tokens', function () { assert.deepEqual(getToWarningObject('0xabc123', undefined, [{ 'address': '0xabc123' }], { 'address': '0xabc123' }), { to: KNOWN_RECIPIENT_ADDRESS_ERROR, }) }) - it('should null if to is truthy part of tokens but selectedToken falsy', () => { + it('should null if to is truthy part of tokens but selectedToken falsy', function () { assert.deepEqual(getToWarningObject('0xabc123', undefined, [{ 'address': '0xabc123' }]), { to: null, }) }) - it('should return a known address recipient if to is truthy but part of contract metadata', () => { + it('should return a known address recipient if to is truthy but part of contract metadata', function () { assert.deepEqual(getToWarningObject('0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', undefined, [{ 'address': '0xabc123' }], { 'address': '0xabc123' }), { to: KNOWN_RECIPIENT_ADDRESS_ERROR, }) }) - it('should null if to is truthy part of contract metadata but selectedToken falsy', () => { + it('should null if to is truthy part of contract metadata but selectedToken falsy', function () { assert.deepEqual(getToWarningObject('0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', undefined, [{ 'address': '0xabc123' }], { 'address': '0xabc123' }), { to: KNOWN_RECIPIENT_ADDRESS_ERROR, }) diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js index 48bc32d3a..02b67621f 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js @@ -17,7 +17,7 @@ describe('AmountMaxButton Component', function () { let wrapper let instance - beforeEach(() => { + beforeEach(function () { wrapper = shallow(( { + afterEach(function () { propsMethodSpies.setAmountToMax.resetHistory() propsMethodSpies.setMaxModeTo.resetHistory() AmountMaxButton.prototype.setMaxAmount.resetHistory() }) - describe('setMaxAmount', () => { + describe('setMaxAmount', function () { - it('should call setAmountToMax with the correct params', () => { + it('should call setAmountToMax with the correct params', function () { assert.equal(propsMethodSpies.setAmountToMax.callCount, 0) instance.setMaxAmount() assert.equal(propsMethodSpies.setAmountToMax.callCount, 1) @@ -62,12 +62,12 @@ describe('AmountMaxButton Component', function () { }) - describe('render', () => { - it('should render an element with a send-v2__amount-max class', () => { + describe('render', function () { + it('should render an element with a send-v2__amount-max class', function () { assert(wrapper.exists('.send-v2__amount-max')) }) - it('should call setMaxModeTo and setMaxAmount when the checkbox is checked', () => { + it('should call setMaxModeTo and setMaxAmount when the checkbox is checked', function () { const { onClick, } = wrapper.find('.send-v2__amount-max').props() @@ -83,7 +83,7 @@ describe('AmountMaxButton Component', function () { ) }) - it('should render the expected text when maxModeOn is false', () => { + it('should render the expected text when maxModeOn is false', function () { wrapper.setProps({ maxModeOn: false }) assert.equal(wrapper.find('.send-v2__amount-max').text(), 'max_t') }) diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-container.test.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-container.test.js index 0307388d7..e13eab9a4 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-container.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-container.test.js @@ -34,11 +34,11 @@ proxyquire('../amount-max-button.container.js', { '../../../../../ducks/send/send.duck': duckActionSpies, }) -describe('amount-max-button container', () => { +describe('amount-max-button container', function () { - describe('mapStateToProps()', () => { + describe('mapStateToProps()', function () { - it('should map the correct properties to props', () => { + it('should map the correct properties to props', function () { assert.deepEqual(mapStateToProps('mockState'), { balance: 'mockBalance:mockState', buttonDataLoading: 'mockButtonDataLoading:mockState', @@ -51,17 +51,17 @@ describe('amount-max-button container', () => { }) - describe('mapDispatchToProps()', () => { + describe('mapDispatchToProps()', function () { let dispatchSpy let mapDispatchToPropsObject - beforeEach(() => { + beforeEach(function () { dispatchSpy = sinon.spy() mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) }) - describe('setAmountToMax()', () => { - it('should dispatch an action', () => { + describe('setAmountToMax()', function () { + it('should dispatch an action', function () { mapDispatchToPropsObject.setAmountToMax({ val: 11, foo: 'bar' }) assert(dispatchSpy.calledTwice) assert(duckActionSpies.updateSendErrors.calledOnce) @@ -77,8 +77,8 @@ describe('amount-max-button container', () => { }) }) - describe('setMaxModeTo()', () => { - it('should dispatch an action', () => { + describe('setMaxModeTo()', function () { + it('should dispatch an action', function () { mapDispatchToPropsObject.setMaxModeTo('mockVal') assert(dispatchSpy.calledOnce) assert.equal( diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-selectors.test.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-selectors.test.js index 655fe1969..45221ad3d 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-selectors.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-selectors.test.js @@ -3,10 +3,10 @@ import { getMaxModeOn, } from '../amount-max-button.selectors.js' -describe('amount-max-button selectors', () => { +describe('amount-max-button selectors', function () { - describe('getMaxModeOn()', () => { - it('should', () => { + describe('getMaxModeOn()', function () { + it('should', function () { const state = { metamask: { send: { diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-utils.test.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-utils.test.js index 1ee858f67..cdef90473 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-utils.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-utils.test.js @@ -3,10 +3,10 @@ import { calcMaxAmount, } from '../amount-max-button.utils.js' -describe('amount-max-button utils', () => { +describe('amount-max-button utils', function () { - describe('calcMaxAmount()', () => { - it('should calculate the correct amount when no selectedToken defined', () => { + describe('calcMaxAmount()', function () { + it('should calculate the correct amount when no selectedToken defined', function () { assert.deepEqual(calcMaxAmount({ balance: 'ffffff', gasTotal: 'ff', @@ -14,7 +14,7 @@ describe('amount-max-button utils', () => { }), 'ffff00') }) - it('should calculate the correct amount when a selectedToken is defined', () => { + it('should calculate the correct amount when a selectedToken is defined', function () { assert.deepEqual(calcMaxAmount({ selectedToken: { decimals: 10, diff --git a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js index f1ef75bc9..917002946 100644 --- a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js @@ -9,8 +9,8 @@ import AmountMaxButton from '../amount-max-button/amount-max-button.container' import UserPreferencedTokenInput from '../../../../../components/app/user-preferenced-token-input' describe('SendAmountRow Component', function () { - describe('validateAmount', () => { - it('should call updateSendAmountError with the correct params', () => { + describe('validateAmount', function () { + it('should call updateSendAmountError with the correct params', function () { const { instance, propsMethodSpies: { updateSendAmountError } } = shallowRenderSendAmountRow() assert.equal(updateSendAmountError.callCount, 0) @@ -29,7 +29,7 @@ describe('SendAmountRow Component', function () { })) }) - it('should call updateGasFeeError if selectedToken is truthy', () => { + it('should call updateGasFeeError if selectedToken is truthy', function () { const { instance, propsMethodSpies: { updateGasFeeError } } = shallowRenderSendAmountRow() assert.equal(updateGasFeeError.callCount, 0) @@ -47,7 +47,7 @@ describe('SendAmountRow Component', function () { })) }) - it('should call not updateGasFeeError if selectedToken is falsey', () => { + it('should call not updateGasFeeError if selectedToken is falsey', function () { const { wrapper, instance, propsMethodSpies: { updateGasFeeError } } = shallowRenderSendAmountRow() wrapper.setProps({ selectedToken: null }) @@ -61,9 +61,9 @@ describe('SendAmountRow Component', function () { }) - describe('updateAmount', () => { + describe('updateAmount', function () { - it('should call setMaxModeTo', () => { + it('should call setMaxModeTo', function () { const { instance, propsMethodSpies: { setMaxModeTo } } = shallowRenderSendAmountRow() assert.equal(setMaxModeTo.callCount, 0) @@ -73,7 +73,7 @@ describe('SendAmountRow Component', function () { assert.ok(setMaxModeTo.calledOnceWithExactly(false)) }) - it('should call updateSendAmount', () => { + it('should call updateSendAmount', function () { const { instance, propsMethodSpies: { updateSendAmount } } = shallowRenderSendAmountRow() assert.equal(updateSendAmount.callCount, 0) @@ -85,14 +85,14 @@ describe('SendAmountRow Component', function () { }) - describe('render', () => { - it('should render a SendRowWrapper component', () => { + describe('render', function () { + it('should render a SendRowWrapper component', function () { const { wrapper } = shallowRenderSendAmountRow() assert.equal(wrapper.find(SendRowWrapper).length, 1) }) - it('should pass the correct props to SendRowWrapper', () => { + it('should pass the correct props to SendRowWrapper', function () { const { wrapper } = shallowRenderSendAmountRow() const { errorType, @@ -105,19 +105,19 @@ describe('SendAmountRow Component', function () { assert.equal(showError, false) }) - it('should render an AmountMaxButton as the first child of the SendRowWrapper', () => { + it('should render an AmountMaxButton as the first child of the SendRowWrapper', function () { const { wrapper } = shallowRenderSendAmountRow() assert(wrapper.find(SendRowWrapper).childAt(0).is(AmountMaxButton)) }) - it('should render a UserPreferencedTokenInput as the second child of the SendRowWrapper', () => { + it('should render a UserPreferencedTokenInput as the second child of the SendRowWrapper', function () { const { wrapper } = shallowRenderSendAmountRow() assert(wrapper.find(SendRowWrapper).childAt(1).is(UserPreferencedTokenInput)) }) - it('should render the UserPreferencedTokenInput with the correct props', () => { + it('should render the UserPreferencedTokenInput with the correct props', function () { const { wrapper, instanceSpies: { updateGas, updateAmount, validateAmount } } = shallowRenderSendAmountRow() const { onChange, diff --git a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-container.test.js b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-container.test.js index bceadb914..e8fb7d428 100644 --- a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-container.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-container.test.js @@ -28,20 +28,20 @@ proxyquire('../send-amount-row.container.js', { '../../../../ducks/send/send.duck': duckActionSpies, }) -describe('send-amount-row container', () => { +describe('send-amount-row container', function () { - describe('mapDispatchToProps()', () => { + describe('mapDispatchToProps()', function () { let dispatchSpy let mapDispatchToPropsObject - beforeEach(() => { + beforeEach(function () { dispatchSpy = sinon.spy() mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) duckActionSpies.updateSendErrors.resetHistory() }) - describe('setMaxModeTo()', () => { - it('should dispatch an action', () => { + describe('setMaxModeTo()', function () { + it('should dispatch an action', function () { mapDispatchToPropsObject.setMaxModeTo('mockBool') assert(dispatchSpy.calledOnce) assert(actionSpies.setMaxModeTo.calledOnce) @@ -52,8 +52,8 @@ describe('send-amount-row container', () => { }) }) - describe('updateSendAmount()', () => { - it('should dispatch an action', () => { + describe('updateSendAmount()', function () { + it('should dispatch an action', function () { mapDispatchToPropsObject.updateSendAmount('mockAmount') assert(dispatchSpy.calledOnce) assert(actionSpies.updateSendAmount.calledOnce) @@ -64,8 +64,8 @@ describe('send-amount-row container', () => { }) }) - describe('updateGasFeeError()', () => { - it('should dispatch an action', () => { + describe('updateGasFeeError()', function () { + it('should dispatch an action', function () { mapDispatchToPropsObject.updateGasFeeError({ some: 'data' }) assert(dispatchSpy.calledOnce) assert(duckActionSpies.updateSendErrors.calledOnce) @@ -76,8 +76,8 @@ describe('send-amount-row container', () => { }) }) - describe('updateSendAmountError()', () => { - it('should dispatch an action', () => { + describe('updateSendAmountError()', function () { + it('should dispatch an action', function () { mapDispatchToPropsObject.updateSendAmountError({ some: 'data' }) assert(dispatchSpy.calledOnce) assert(duckActionSpies.updateSendErrors.calledOnce) diff --git a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-selectors.test.js b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-selectors.test.js index 4672cb8a7..b0130a794 100644 --- a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-selectors.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-selectors.test.js @@ -3,10 +3,10 @@ import { sendAmountIsInError, } from '../send-amount-row.selectors.js' -describe('send-amount-row selectors', () => { +describe('send-amount-row selectors', function () { - describe('sendAmountIsInError()', () => { - it('should return true if send.errors.amount is truthy', () => { + describe('sendAmountIsInError()', function () { + it('should return true if send.errors.amount is truthy', function () { const state = { send: { errors: { @@ -18,7 +18,7 @@ describe('send-amount-row selectors', () => { assert.equal(sendAmountIsInError(state), true) }) - it('should return false if send.errors.amount is falsy', () => { + it('should return false if send.errors.amount is falsy', function () { const state = { send: { errors: { diff --git a/ui/app/pages/send/send-content/send-dropdown-list/tests/send-dropdown-list-component.test.js b/ui/app/pages/send/send-content/send-dropdown-list/tests/send-dropdown-list-component.test.js index 77efddfd4..4fdf4d038 100644 --- a/ui/app/pages/send/send-content/send-dropdown-list/tests/send-dropdown-list-component.test.js +++ b/ui/app/pages/send/send-content/send-dropdown-list/tests/send-dropdown-list-component.test.js @@ -16,7 +16,7 @@ sinon.spy(SendDropdownList.prototype, 'getListItemIcon') describe('SendDropdownList Component', function () { let wrapper - beforeEach(() => { + beforeEach(function () { wrapper = shallow(( str + '_t' } }) }) - afterEach(() => { + afterEach(function () { propsMethodSpies.closeDropdown.resetHistory() propsMethodSpies.onSelect.resetHistory() SendDropdownList.prototype.getListItemIcon.resetHistory() }) - describe('getListItemIcon', () => { - it('should return check icon if the passed addresses are the same', () => { + describe('getListItemIcon', function () { + it('should return check icon if the passed addresses are the same', function () { assert.deepEqual( wrapper.instance().getListItemIcon('mockAccount0', 'mockAccount0'), ) }) - it('should return null if the passed addresses are different', () => { + it('should return null if the passed addresses are different', function () { assert.equal( wrapper.instance().getListItemIcon('mockAccount0', 'mockAccount1'), null @@ -53,29 +53,29 @@ describe('SendDropdownList Component', function () { }) }) - describe('render', () => { - it('should render a single div with two children', () => { + describe('render', function () { + it('should render a single div with two children', function () { assert(wrapper.is('div')) assert.equal(wrapper.children().length, 2) }) - it('should render the children with the correct classes', () => { + it('should render the children with the correct classes', function () { assert(wrapper.childAt(0).hasClass('send-v2__from-dropdown__close-area')) assert(wrapper.childAt(1).hasClass('send-v2__from-dropdown__list')) }) - it('should call closeDropdown onClick of the send-v2__from-dropdown__close-area', () => { + it('should call closeDropdown onClick of the send-v2__from-dropdown__close-area', function () { assert.equal(propsMethodSpies.closeDropdown.callCount, 0) wrapper.childAt(0).props().onClick() assert.equal(propsMethodSpies.closeDropdown.callCount, 1) }) - it('should render an AccountListItem for each item in accounts', () => { + it('should render an AccountListItem for each item in accounts', function () { assert.equal(wrapper.childAt(1).children().length, 3) assert(wrapper.childAt(1).children().every(AccountListItem)) }) - it('should pass the correct props to the AccountListItem', () => { + it('should pass the correct props to the AccountListItem', function () { wrapper.childAt(1).children().forEach((accountListItem, index) => { const { account, @@ -98,7 +98,7 @@ describe('SendDropdownList Component', function () { }) }) - it('should call this.getListItemIcon for each AccountListItem', () => { + it('should call this.getListItemIcon for each AccountListItem', function () { assert.equal(SendDropdownList.prototype.getListItemIcon.callCount, 3) const getListItemIconCalls = SendDropdownList.prototype.getListItemIcon.getCalls() assert(getListItemIconCalls.every(({ args }, index) => args[0] === 'mockAccount' + index)) diff --git a/ui/app/pages/send/send-content/send-from-row/tests/send-from-row-component.test.js b/ui/app/pages/send/send-content/send-from-row/tests/send-from-row-component.test.js index 18811c57e..e38269421 100644 --- a/ui/app/pages/send/send-content/send-from-row/tests/send-from-row-component.test.js +++ b/ui/app/pages/send/send-content/send-from-row/tests/send-from-row-component.test.js @@ -6,7 +6,7 @@ import AccountListItem from '../../../account-list-item' import SendRowWrapper from '../../send-row-wrapper/send-row-wrapper.component' describe('SendFromRow Component', function () { - describe('render', () => { + describe('render', function () { const wrapper = shallow( str + '_t' } } ) - it('should render a SendRowWrapper component', () => { + it('should render a SendRowWrapper component', function () { assert.equal(wrapper.find(SendRowWrapper).length, 1) }) - it('should pass the correct props to SendRowWrapper', () => { + it('should pass the correct props to SendRowWrapper', function () { const { label } = wrapper.find(SendRowWrapper).props() assert.equal(label, 'from_t:') }) - it('should render the FromDropdown with the correct props', () => { + it('should render the FromDropdown with the correct props', function () { const { account } = wrapper.find(AccountListItem).props() assert.deepEqual(account, { address: 'mockAddress' }) }) diff --git a/ui/app/pages/send/send-content/send-from-row/tests/send-from-row-container.test.js b/ui/app/pages/send/send-content/send-from-row/tests/send-from-row-container.test.js index fd771ea77..91db73cf5 100644 --- a/ui/app/pages/send/send-content/send-from-row/tests/send-from-row-container.test.js +++ b/ui/app/pages/send/send-content/send-from-row/tests/send-from-row-container.test.js @@ -15,9 +15,9 @@ proxyquire('../send-from-row.container.js', { }, }) -describe('send-from-row container', () => { - describe('mapStateToProps()', () => { - it('should map the correct properties to props', () => { +describe('send-from-row container', function () { + describe('mapStateToProps()', function () { + it('should map the correct properties to props', function () { assert.deepEqual(mapStateToProps('mockState'), { from: 'mockFrom:mockState', }) diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js index 3ff2ddec2..badf345d3 100644 --- a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js +++ b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js @@ -5,7 +5,6 @@ import GasFeeDisplay from '../gas-fee-display.component' import UserPreferencedCurrencyDisplay from '../../../../../../components/app/user-preferenced-currency-display' import sinon from 'sinon' - const propsMethodSpies = { showCustomizeGasModal: sinon.spy(), onReset: sinon.spy(), @@ -14,29 +13,29 @@ const propsMethodSpies = { describe('GasFeeDisplay Component', function () { let wrapper - beforeEach(() => { - wrapper = shallow(( - - ), { context: { t: str => str + '_t' } }) - }) + describe('render', function () { + beforeEach(function () { + wrapper = shallow(( + + ), { context: { t: str => str + '_t' } }) + }) - afterEach(() => { - propsMethodSpies.showCustomizeGasModal.resetHistory() - }) + afterEach(function () { + propsMethodSpies.showCustomizeGasModal.resetHistory() + }) - describe('render', () => { - it('should render a CurrencyDisplay component', () => { + it('should render a CurrencyDisplay component', function () { assert.equal(wrapper.find(UserPreferencedCurrencyDisplay).length, 2) }) - it('should render the CurrencyDisplay with the correct props', () => { + it('should render the CurrencyDisplay with the correct props', function () { const { type, value, @@ -45,7 +44,7 @@ describe('GasFeeDisplay Component', function () { assert.equal(value, 'mockGasTotal') }) - it('should render the reset button with the correct props', () => { + it('should render the reset button with the correct props', function () { const { onClick, className, @@ -56,7 +55,7 @@ describe('GasFeeDisplay Component', function () { assert.equal(propsMethodSpies.onReset.callCount, 1) }) - it('should render the reset button with the correct text', () => { + it('should render the reset button with the correct text', function () { assert.equal(wrapper.find('button').text(), 'reset_t') }) }) diff --git a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js index ad2056498..1151289fe 100644 --- a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js +++ b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js @@ -16,35 +16,35 @@ const propsMethodSpies = { describe('SendGasRow Component', function () { let wrapper - beforeEach(() => { - wrapper = shallow(( - - ), { context: { t: str => str + '_t', metricsEvent: () => ({}) } }) - }) + describe('render', function () { + beforeEach(function () { + wrapper = shallow(( + + ), { context: { t: str => str + '_t', metricsEvent: () => ({}) } }) + }) - afterEach(() => { - propsMethodSpies.resetGasButtons.resetHistory() - }) + afterEach(function () { + propsMethodSpies.resetGasButtons.resetHistory() + }) - describe('render', () => { - it('should render a SendRowWrapper component', () => { + it('should render a SendRowWrapper component', function () { assert.equal(wrapper.find(SendRowWrapper).length, 1) }) - it('should pass the correct props to SendRowWrapper', () => { + it('should pass the correct props to SendRowWrapper', function () { const { label, showError, @@ -56,11 +56,11 @@ describe('SendGasRow Component', function () { assert.equal(errorType, 'gasFee') }) - it('should render a GasFeeDisplay as a child of the SendRowWrapper', () => { + it('should render a GasFeeDisplay as a child of the SendRowWrapper', function () { assert(wrapper.find(SendRowWrapper).childAt(0).is(GasFeeDisplay)) }) - it('should render the GasFeeDisplay', () => { + it('should render the GasFeeDisplay', function () { const { gasLoadingError, gasTotal, @@ -73,7 +73,7 @@ describe('SendGasRow Component', function () { assert.equal(propsMethodSpies.resetGasButtons.callCount, 1) }) - it('should render the GasPriceButtonGroup if gasButtonGroupShown is true', () => { + it('should render the GasPriceButtonGroup if gasButtonGroupShown is true', function () { wrapper.setProps({ gasButtonGroupShown: true }) const rendered = wrapper.find(SendRowWrapper).childAt(0) assert.equal(rendered.children().length, 2) @@ -86,7 +86,7 @@ describe('SendGasRow Component', function () { assert.equal(gasPriceButtonGroup.props().anotherGasPriceButtonGroupProp, 'bar') }) - it('should render an advanced options button if gasButtonGroupShown is true', () => { + it('should render an advanced options button if gasButtonGroupShown is true', function () { wrapper.setProps({ gasButtonGroupShown: true }) const rendered = wrapper.find(SendRowWrapper).childAt(0) assert.equal(rendered.children().length, 2) diff --git a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-container.test.js b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-container.test.js index 128939152..c870a4915 100644 --- a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-container.test.js +++ b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-container.test.js @@ -47,20 +47,20 @@ proxyquire('../send-gas-row.container.js', { '../../../../ducks/gas/gas.duck': gasDuckSpies, }) -describe('send-gas-row container', () => { +describe('send-gas-row container', function () { - describe('mapDispatchToProps()', () => { + describe('mapDispatchToProps()', function () { let dispatchSpy let mapDispatchToPropsObject - beforeEach(() => { + beforeEach(function () { dispatchSpy = sinon.spy() mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) actionSpies.setGasTotal.resetHistory() }) - describe('showCustomizeGasModal()', () => { - it('should dispatch an action', () => { + describe('showCustomizeGasModal()', function () { + it('should dispatch an action', function () { mapDispatchToPropsObject.showCustomizeGasModal() assert(dispatchSpy.calledOnce) assert.deepEqual( @@ -70,8 +70,8 @@ describe('send-gas-row container', () => { }) }) - describe('setGasPrice()', () => { - it('should dispatch an action', () => { + describe('setGasPrice()', function () { + it('should dispatch an action', function () { mapDispatchToPropsObject.setGasPrice('mockNewPrice', 'mockLimit') assert(dispatchSpy.calledThrice) assert(actionSpies.setGasPrice.calledOnce) @@ -82,8 +82,8 @@ describe('send-gas-row container', () => { }) }) - describe('setGasLimit()', () => { - it('should dispatch an action', () => { + describe('setGasLimit()', function () { + it('should dispatch an action', function () { mapDispatchToPropsObject.setGasLimit('mockNewLimit', 'mockPrice') assert(dispatchSpy.calledThrice) assert(actionSpies.setGasLimit.calledOnce) @@ -94,45 +94,37 @@ describe('send-gas-row container', () => { }) }) - describe('showGasButtonGroup()', () => { - it('should dispatch an action', () => { + describe('showGasButtonGroup()', function () { + it('should dispatch an action', function () { mapDispatchToPropsObject.showGasButtonGroup() assert(dispatchSpy.calledOnce) assert(sendDuckSpies.showGasButtonGroup.calledOnce) }) }) - describe('resetCustomData()', () => { - it('should dispatch an action', () => { + describe('resetCustomData()', function () { + it('should dispatch an action', function () { mapDispatchToPropsObject.resetCustomData() assert(dispatchSpy.calledOnce) assert(gasDuckSpies.resetCustomData.calledOnce) }) }) - }) - describe('mergeProps', () => { - let stateProps - let dispatchProps - let ownProps - - beforeEach(() => { - stateProps = { + describe('mergeProps', function () { + it('should return the expected props when isConfirm is true', function () { + const stateProps = { gasPriceButtonGroupProps: { someGasPriceButtonGroupProp: 'foo', anotherGasPriceButtonGroupProp: 'bar', }, someOtherStateProp: 'baz', } - dispatchProps = { + const dispatchProps = { setGasPrice: sinon.spy(), someOtherDispatchProp: sinon.spy(), } - ownProps = { someOwnProp: 123 } - }) - - it('should return the expected props when isConfirm is true', () => { + const ownProps = { someOwnProp: 123 } const result = mergeProps(stateProps, dispatchProps, ownProps) assert.equal(result.someOtherStateProp, 'baz') @@ -149,5 +141,4 @@ describe('send-gas-row container', () => { assert.equal(dispatchProps.someOtherDispatchProp.callCount, 1) }) }) - }) diff --git a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-selectors.test.js b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-selectors.test.js index bd3c9a257..19f88f4c4 100644 --- a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-selectors.test.js +++ b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-selectors.test.js @@ -5,10 +5,10 @@ import { getGasButtonGroupShown, } from '../send-gas-row.selectors.js' -describe('send-gas-row selectors', () => { +describe('send-gas-row selectors', function () { - describe('getGasLoadingError()', () => { - it('should return send.errors.gasLoading', () => { + describe('getGasLoadingError()', function () { + it('should return send.errors.gasLoading', function () { const state = { send: { errors: { @@ -21,8 +21,8 @@ describe('send-gas-row selectors', () => { }) }) - describe('gasFeeIsInError()', () => { - it('should return true if send.errors.gasFee is truthy', () => { + describe('gasFeeIsInError()', function () { + it('should return true if send.errors.gasFee is truthy', function () { const state = { send: { errors: { @@ -34,7 +34,7 @@ describe('send-gas-row selectors', () => { assert.equal(gasFeeIsInError(state), true) }) - it('should return false send.errors.gasFee is falsely', () => { + it('should return false send.errors.gasFee is falsely', function () { const state = { send: { errors: { @@ -47,8 +47,8 @@ describe('send-gas-row selectors', () => { }) }) - describe('getGasButtonGroupShown()', () => { - it('should return send.gasButtonGroupShown', () => { + describe('getGasButtonGroupShown()', function () { + it('should return send.gasButtonGroupShown', function () { const state = { send: { gasButtonGroupShown: 'foobar', diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js index 2f20b2f0c..ef4bedc8f 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js @@ -6,22 +6,22 @@ import SendRowErrorMessage from '../send-row-error-message.component.js' describe('SendRowErrorMessage Component', function () { let wrapper - beforeEach(() => { - wrapper = shallow(( - - ), { context: { t: str => str + '_t' } }) - }) + describe('render', function () { + beforeEach(function () { + wrapper = shallow(( + + ), { context: { t: str => str + '_t' } }) + }) - describe('render', () => { - it('should render null if the passed errors do not contain an error of errorType', () => { + it('should render null if the passed errors do not contain an error of errorType', function () { assert.equal(wrapper.find('.send-v2__error').length, 0) assert.equal(wrapper.html(), null) }) - it('should render an error message if the passed errors contain an error of errorType', () => { + it('should render an error message if the passed errors contain an error of errorType', function () { wrapper.setProps({ errors: { error1: 'abc', error2: 'def', error3: 'xyz' } }) assert.equal(wrapper.find('.send-v2__error').length, 1) assert.equal(wrapper.find('.send-v2__error').text(), 'xyz_t') diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-container.test.js b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-container.test.js index 2013e3200..370600f50 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-container.test.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-container.test.js @@ -13,11 +13,11 @@ proxyquire('../send-row-error-message.container.js', { '../../../send.selectors': { getSendErrors: (s) => `mockErrors:${s}` }, }) -describe('send-row-error-message container', () => { +describe('send-row-error-message container', function () { - describe('mapStateToProps()', () => { + describe('mapStateToProps()', function () { - it('should map the correct properties to props', () => { + it('should map the correct properties to props', function () { assert.deepEqual(mapStateToProps('mockState', { errorType: 'someType' }), { errors: 'mockErrors:mockState', errorType: 'someType' }) diff --git a/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js b/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js index c992d97e2..82e64c239 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js @@ -8,41 +8,37 @@ import SendRowErrorMessage from '../send-row-error-message/send-row-error-messag describe('SendContent Component', function () { let wrapper - beforeEach(() => { - wrapper = shallow(( - - Mock Form Field - - )) - }) + describe('render', function () { + beforeEach(function () { + wrapper = shallow(( + + Mock Form Field + + )) + }) - describe('render', () => { - it('should render a div with a send-v2__form-row class', () => { + it('should render a div with a send-v2__form-row class', function () { assert.equal(wrapper.find('div.send-v2__form-row').length, 1) }) - it('should render two children of the root div, with send-v2_form label and field classes', () => { + it('should render two children of the root div, with send-v2_form label and field classes', function () { assert.equal(wrapper.find('.send-v2__form-row > .send-v2__form-label').length, 1) assert.equal(wrapper.find('.send-v2__form-row > .send-v2__form-field').length, 1) }) - it('should render the label as a child of the send-v2__form-label', () => { + it('should render the label as a child of the send-v2__form-label', function () { assert.equal(wrapper.find('.send-v2__form-row > .send-v2__form-label').childAt(0).text(), 'mockLabel') }) - it('should render its first child as a child of the send-v2__form-field', () => { + it('should render its first child as a child of the send-v2__form-field', function () { assert.equal(wrapper.find('.send-v2__form-row > .send-v2__form-field').childAt(0).text(), 'Mock Form Field') }) - it('should not render a SendRowErrorMessage if showError is false', () => { + it('should not render a SendRowErrorMessage if showError is false', function () { assert.equal(wrapper.find(SendRowErrorMessage).length, 0) }) - it('should render a SendRowErrorMessage with and errorType props if showError is true', () => { + it('should render a SendRowErrorMessage with and errorType props if showError is true', function () { wrapper.setProps({ showError: true }) assert.equal(wrapper.find(SendRowErrorMessage).length, 1) @@ -54,7 +50,7 @@ describe('SendContent Component', function () { ) }) - it('should render its second child as a child of the send-v2__form-field, if it has two children', () => { + it('should render its second child as a child of the send-v2__form-field, if it has two children', function () { wrapper = shallow(( .send-v2__form-field').childAt(0).text(), 'Mock Form Field') }) - it('should render its first child as the last child of the send-v2__form-label, if it has two children', () => { + it('should render its first child as the last child of the send-v2__form-label, if it has two children', function () { wrapper = shallow(( { + beforeEach(function () { wrapper = shallow( { - it('should render a PageContainerContent component', () => { + describe('render', function () { + it('should render a PageContainerContent component', function () { assert.equal(wrapper.find(PageContainerContent).length, 1) }) - it('should render a div with a .send-v2__form class as a child of PageContainerContent', () => { + it('should render a div with a .send-v2__form class as a child of PageContainerContent', function () { const PageContainerContentChild = wrapper.find(PageContainerContent).children() PageContainerContentChild.is('div') PageContainerContentChild.is('.send-v2__form') }) - it('should render the correct row components as grandchildren of the PageContainerContent component', () => { + it('should render the correct row components as grandchildren of the PageContainerContent component', function () { const PageContainerContentChild = wrapper.find(PageContainerContent).children() assert(PageContainerContentChild.childAt(0).is(Dialog), 'row[0] should be Dialog') assert(PageContainerContentChild.childAt(1).is(SendAssetRow), 'row[1] should be SendAssetRow') @@ -42,7 +42,7 @@ describe('SendContent Component', function () { assert(PageContainerContentChild.childAt(4).is(SendHexDataRow), 'row[4] should be SendHexDataRow') }) - it('should not render the SendHexDataRow if props.showHexData is false', () => { + it('should not render the SendHexDataRow if props.showHexData is false', function () { wrapper.setProps({ showHexData: false }) const PageContainerContentChild = wrapper.find(PageContainerContent).children() assert(PageContainerContentChild.childAt(0).is(Dialog), 'row[0] should be Dialog') @@ -52,7 +52,7 @@ describe('SendContent Component', function () { assert.equal(PageContainerContentChild.childAt(4).exists(), false) }) - it('should not render the Dialog if contact has a name', () => { + it('should not render the Dialog if contact has a name', function () { wrapper.setProps({ showHexData: false, contact: { name: 'testName' }, @@ -64,7 +64,7 @@ describe('SendContent Component', function () { assert.equal(PageContainerContentChild.childAt(3).exists(), false) }) - it('should not render the Dialog if it is an ownedAccount', () => { + it('should not render the Dialog if it is an ownedAccount', function () { wrapper.setProps({ showHexData: false, isOwnedAccount: true, @@ -77,7 +77,7 @@ describe('SendContent Component', function () { }) }) - it('should not render the asset dropdown if token length is 0 ', () => { + it('should not render the asset dropdown if token length is 0 ', function () { wrapper.setProps({ tokens: [] }) const PageContainerContentChild = wrapper.find(PageContainerContent).children() assert(PageContainerContentChild.childAt(1).is(SendAssetRow)) diff --git a/ui/app/pages/send/send-footer/tests/send-footer-component.test.js b/ui/app/pages/send/send-footer/tests/send-footer-component.test.js index bda82711c..b319f9cf4 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-component.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-component.test.js @@ -24,7 +24,7 @@ sinon.spy(SendFooter.prototype, 'onSubmit') describe('SendFooter Component', function () { let wrapper - beforeEach(() => { + beforeEach(function () { wrapper = shallow(( str, metricsEvent: () => ({}) } }) }) - afterEach(() => { + afterEach(function () { propsMethodSpies.clearSend.resetHistory() propsMethodSpies.addToAddressBookIfNew.resetHistory() propsMethodSpies.clearSend.resetHistory() @@ -62,14 +62,14 @@ describe('SendFooter Component', function () { SendFooter.prototype.onSubmit.resetHistory() }) - describe('onCancel', () => { - it('should call clearSend', () => { + describe('onCancel', function () { + it('should call clearSend', function () { assert.equal(propsMethodSpies.clearSend.callCount, 0) wrapper.instance().onCancel() assert.equal(propsMethodSpies.clearSend.callCount, 1) }) - it('should call history.push', () => { + it('should call history.push', function () { assert.equal(historySpies.push.callCount, 0) wrapper.instance().onCancel() assert.equal(historySpies.push.callCount, 1) @@ -78,7 +78,7 @@ describe('SendFooter Component', function () { }) - describe('formShouldBeDisabled()', () => { + describe('formShouldBeDisabled()', function () { const config = { 'should return true if inError is truthy': { inError: true, @@ -123,15 +123,15 @@ describe('SendFooter Component', function () { } Object.entries(config).map(([description, obj]) => { - it(description, () => { + it(description, function () { wrapper.setProps(obj) assert.equal(wrapper.instance().formShouldBeDisabled(), obj.expectedResult) }) }) }) - describe('onSubmit', () => { - it('should call addToAddressBookIfNew with the correct params', () => { + describe('onSubmit', function () { + it('should call addToAddressBookIfNew with the correct params', function () { wrapper.instance().onSubmit(MOCK_EVENT) assert(propsMethodSpies.addToAddressBookIfNew.calledOnce) assert.deepEqual( @@ -140,7 +140,7 @@ describe('SendFooter Component', function () { ) }) - it('should call props.update if editingTransactionId is truthy', () => { + it('should call props.update if editingTransactionId is truthy', function () { wrapper.instance().onSubmit(MOCK_EVENT) assert(propsMethodSpies.update.calledOnce) assert.deepEqual( @@ -159,11 +159,11 @@ describe('SendFooter Component', function () { ) }) - it('should not call props.sign if editingTransactionId is truthy', () => { + it('should not call props.sign if editingTransactionId is truthy', function () { assert.equal(propsMethodSpies.sign.callCount, 0) }) - it('should call props.sign if editingTransactionId is falsy', () => { + it('should call props.sign if editingTransactionId is falsy', function () { wrapper.setProps({ editingTransactionId: null }) wrapper.instance().onSubmit(MOCK_EVENT) assert(propsMethodSpies.sign.calledOnce) @@ -181,11 +181,11 @@ describe('SendFooter Component', function () { ) }) - it('should not call props.update if editingTransactionId is falsy', () => { + it('should not call props.update if editingTransactionId is falsy', function () { assert.equal(propsMethodSpies.update.callCount, 0) }) - it('should call history.push', done => { + it('should call history.push', function (done) { Promise.resolve(wrapper.instance().onSubmit(MOCK_EVENT)) .then(() => { assert.equal(historySpies.push.callCount, 1) @@ -195,8 +195,8 @@ describe('SendFooter Component', function () { }) }) - describe('render', () => { - beforeEach(() => { + describe('render', function () { + beforeEach(function () { sinon.stub(SendFooter.prototype, 'formShouldBeDisabled').returns(true) wrapper = shallow(( str, metricsEvent: () => ({}) } }) }) - afterEach(() => { + afterEach(function () { SendFooter.prototype.formShouldBeDisabled.restore() }) - it('should render a PageContainerFooter component', () => { + it('should render a PageContainerFooter component', function () { assert.equal(wrapper.find(PageContainerFooter).length, 1) }) - it('should pass the correct props to PageContainerFooter', () => { + it('should pass the correct props to PageContainerFooter', function () { const { onCancel, onSubmit, diff --git a/ui/app/pages/send/send-footer/tests/send-footer-container.test.js b/ui/app/pages/send/send-footer/tests/send-footer-container.test.js index 70bc078c8..0d4655c9d 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-container.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-container.test.js @@ -51,27 +51,27 @@ proxyquire('../send-footer.container.js', { }, }) -describe('send-footer container', () => { +describe('send-footer container', function () { - describe('mapDispatchToProps()', () => { + describe('mapDispatchToProps()', function () { let dispatchSpy let mapDispatchToPropsObject - beforeEach(() => { + beforeEach(function () { dispatchSpy = sinon.spy() mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) }) - describe('clearSend()', () => { - it('should dispatch an action', () => { + describe('clearSend()', function () { + it('should dispatch an action', function () { mapDispatchToPropsObject.clearSend() assert(dispatchSpy.calledOnce) assert(actionSpies.clearSend.calledOnce) }) }) - describe('sign()', () => { - it('should dispatch a signTokenTx action if selectedToken is defined', () => { + describe('sign()', function () { + it('should dispatch a signTokenTx action if selectedToken is defined', function () { mapDispatchToPropsObject.sign({ selectedToken: { address: '0xabc', @@ -103,7 +103,7 @@ describe('send-footer container', () => { ) }) - it('should dispatch a sign action if selectedToken is not defined', () => { + it('should dispatch a sign action if selectedToken is not defined', function () { utilsStubs.constructTxParams.resetHistory() mapDispatchToPropsObject.sign({ to: 'mockTo', @@ -132,8 +132,8 @@ describe('send-footer container', () => { }) }) - describe('update()', () => { - it('should dispatch an updateTransaction action', () => { + describe('update()', function () { + it('should dispatch an updateTransaction action', function () { mapDispatchToPropsObject.update({ to: 'mockTo', amount: 'mockAmount', @@ -163,8 +163,8 @@ describe('send-footer container', () => { }) }) - describe('addToAddressBookIfNew()', () => { - it('should dispatch an action', () => { + describe('addToAddressBookIfNew()', function () { + it('should dispatch an action', function () { mapDispatchToPropsObject.addToAddressBookIfNew('mockNewAddress', 'mockToAccounts', 'mockNickname') assert(dispatchSpy.calledOnce) assert.equal(utilsStubs.addressIsNew.getCall(0).args[0], 'mockToAccounts') diff --git a/ui/app/pages/send/send-footer/tests/send-footer-selectors.test.js b/ui/app/pages/send/send-footer/tests/send-footer-selectors.test.js index 36f3a809f..4671abf3f 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-selectors.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-selectors.test.js @@ -9,14 +9,14 @@ const { }, }) -describe('send-footer selectors', () => { +describe('send-footer selectors', function () { - describe('getTitleKey()', () => { - it('should return true if any of the values of the object returned by getSendErrors are truthy', () => { + describe('getTitleKey()', function () { + it('should return true if any of the values of the object returned by getSendErrors are truthy', function () { assert.equal(isSendFormInError({ errors: { a: 'abc', b: false } }), true) }) - it('should return false if all of the values of the object returned by getSendErrors are falsy', () => { + it('should return false if all of the values of the object returned by getSendErrors are falsy', function () { assert.equal(isSendFormInError({ errors: { a: false, b: null } }), false) }) }) diff --git a/ui/app/pages/send/send-footer/tests/send-footer-utils.test.js b/ui/app/pages/send/send-footer/tests/send-footer-utils.test.js index 7cecbae45..ea1f54126 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-utils.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-utils.test.js @@ -21,10 +21,10 @@ const { addHexPrefixToObjectValues, } = sendUtils -describe('send-footer utils', () => { +describe('send-footer utils', function () { - describe('addHexPrefixToObjectValues()', () => { - it('should return a new object with the same properties with a 0x prefix', () => { + describe('addHexPrefixToObjectValues()', function () { + it('should return a new object with the same properties with a 0x prefix', function () { assert.deepEqual( addHexPrefixToObjectValues({ prop1: '0x123', @@ -40,8 +40,8 @@ describe('send-footer utils', () => { }) }) - describe('addressIsNew()', () => { - it('should return false if the address exists in toAccounts', () => { + describe('addressIsNew()', function () { + it('should return false if the address exists in toAccounts', function () { assert.equal( addressIsNew([ { address: '0xabc' }, @@ -52,7 +52,7 @@ describe('send-footer utils', () => { ) }) - it('should return true if the address does not exists in toAccounts', () => { + it('should return true if the address does not exists in toAccounts', function () { assert.equal( addressIsNew([ { address: '0xabc' }, @@ -64,8 +64,8 @@ describe('send-footer utils', () => { }) }) - describe('constructTxParams()', () => { - it('should return a new txParams object with data if there data is given', () => { + describe('constructTxParams()', function () { + it('should return a new txParams object with data if there data is given', function () { assert.deepEqual( constructTxParams({ data: 'someData', @@ -87,7 +87,7 @@ describe('send-footer utils', () => { ) }) - it('should return a new txParams object with value and to properties if there is no selectedToken', () => { + it('should return a new txParams object with value and to properties if there is no selectedToken', function () { assert.deepEqual( constructTxParams({ selectedToken: false, @@ -108,7 +108,7 @@ describe('send-footer utils', () => { ) }) - it('should return a new txParams object without a to property and a 0 value if there is a selectedToken', () => { + it('should return a new txParams object without a to property and a 0 value if there is a selectedToken', function () { assert.deepEqual( constructTxParams({ selectedToken: true, @@ -129,8 +129,8 @@ describe('send-footer utils', () => { }) }) - describe('constructUpdatedTx()', () => { - it('should return a new object with an updated txParams', () => { + describe('constructUpdatedTx()', function () { + it('should return a new object with an updated txParams', function () { const result = constructUpdatedTx({ amount: 'mockAmount', editingTransactionId: '0x456', @@ -162,7 +162,7 @@ describe('send-footer utils', () => { }) }) - it('should not have data property if there is non in the original tx', () => { + it('should not have data property if there is non in the original tx', function () { const result = constructUpdatedTx({ amount: 'mockAmount', editingTransactionId: '0x456', @@ -196,7 +196,7 @@ describe('send-footer utils', () => { }) }) - it('should have token property values if selectedToken is truthy', () => { + it('should have token property values if selectedToken is truthy', function () { const result = constructUpdatedTx({ amount: 'mockAmount', editingTransactionId: '0x456', diff --git a/ui/app/pages/send/send-header/tests/send-header-component.test.js b/ui/app/pages/send/send-header/tests/send-header-component.test.js index 166d12487..c57391e6c 100644 --- a/ui/app/pages/send/send-header/tests/send-header-component.test.js +++ b/ui/app/pages/send/send-header/tests/send-header-component.test.js @@ -19,7 +19,7 @@ sinon.spy(SendHeader.prototype, 'onClose') describe('SendHeader Component', function () { let wrapper - beforeEach(() => { + beforeEach(function () { wrapper = shallow(( (str2 ? str1 + str2 : str1) } }) }) - afterEach(() => { + afterEach(function () { propsMethodSpies.clearSend.resetHistory() historySpies.push.resetHistory() SendHeader.prototype.onClose.resetHistory() }) - describe('onClose', () => { - it('should call clearSend', () => { + describe('onClose', function () { + it('should call clearSend', function () { assert.equal(propsMethodSpies.clearSend.callCount, 0) wrapper.instance().onClose() assert.equal(propsMethodSpies.clearSend.callCount, 1) }) - it('should call history.push', () => { + it('should call history.push', function () { assert.equal(historySpies.push.callCount, 0) wrapper.instance().onClose() assert.equal(historySpies.push.callCount, 1) @@ -50,12 +50,12 @@ describe('SendHeader Component', function () { }) }) - describe('render', () => { - it('should render a PageContainerHeader compenent', () => { + describe('render', function () { + it('should render a PageContainerHeader compenent', function () { assert.equal(wrapper.find(PageContainerHeader).length, 1) }) - it('should pass the correct props to PageContainerHeader', () => { + it('should pass the correct props to PageContainerHeader', function () { const { onClose, title, diff --git a/ui/app/pages/send/send-header/tests/send-header-container.test.js b/ui/app/pages/send/send-header/tests/send-header-container.test.js index 0ff7491f0..26f60bd7b 100644 --- a/ui/app/pages/send/send-header/tests/send-header-container.test.js +++ b/ui/app/pages/send/send-header/tests/send-header-container.test.js @@ -23,35 +23,25 @@ proxyquire('../send-header.container.js', { }, }) -describe('send-header container', () => { - - describe('mapStateToProps()', () => { - - it('should map the correct properties to props', () => { +describe('send-header container', function () { + describe('mapStateToProps()', function () { + it('should map the correct properties to props', function () { assert.deepEqual(mapStateToProps('mockState'), { titleKey: 'mockTitleKey:mockState', }) }) - }) - describe('mapDispatchToProps()', () => { - let dispatchSpy - let mapDispatchToPropsObject + describe('mapDispatchToProps()', function () { + describe('clearSend()', function () { + it('should dispatch an action', function () { + const dispatchSpy = sinon.spy() + const mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) - beforeEach(() => { - dispatchSpy = sinon.spy() - mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) - }) - - describe('clearSend()', () => { - it('should dispatch an action', () => { mapDispatchToPropsObject.clearSend() assert(dispatchSpy.calledOnce) assert(actionSpies.clearSend.calledOnce) }) }) - }) - }) diff --git a/ui/app/pages/send/send-header/tests/send-header-selectors.test.js b/ui/app/pages/send/send-header/tests/send-header-selectors.test.js index ad47d0cfa..21cd2ad48 100644 --- a/ui/app/pages/send/send-header/tests/send-header-selectors.test.js +++ b/ui/app/pages/send/send-header/tests/send-header-selectors.test.js @@ -11,22 +11,22 @@ const { }, }) -describe('send-header selectors', () => { +describe('send-header selectors', function () { - describe('getTitleKey()', () => { - it('should return the correct key when "to" is empty', () => { + describe('getTitleKey()', function () { + it('should return the correct key when "to" is empty', function () { assert.equal(getTitleKey({ e: 1, t: true, to: '' }), 'addRecipient') }) - it('should return the correct key when getSendEditingTransactionId is truthy', () => { + it('should return the correct key when getSendEditingTransactionId is truthy', function () { assert.equal(getTitleKey({ e: 1, t: true, to: '0x123' }), 'edit') }) - it('should return the correct key when getSendEditingTransactionId is falsy and getSelectedToken is truthy', () => { + it('should return the correct key when getSendEditingTransactionId is falsy and getSelectedToken is truthy', function () { assert.equal(getTitleKey({ e: null, t: 'abc', to: '0x123' }), 'sendTokens') }) - it('should return the correct key when getSendEditingTransactionId is falsy and getSelectedToken is falsy', () => { + it('should return the correct key when getSendEditingTransactionId is falsy and getSelectedToken is falsy', function () { assert.equal(getTitleKey({ e: null, to: '0x123' }), 'sendETH') }) }) diff --git a/ui/app/pages/send/tests/send-component.test.js b/ui/app/pages/send/tests/send-component.test.js index 2b7a31d77..14b3b4584 100644 --- a/ui/app/pages/send/tests/send-component.test.js +++ b/ui/app/pages/send/tests/send-component.test.js @@ -39,7 +39,7 @@ sinon.spy(SendTransactionScreen.prototype, 'updateGas') describe('Send Component', function () { let wrapper - beforeEach(() => { + beforeEach(function () { wrapper = shallow(( { + afterEach(function () { SendTransactionScreen.prototype.componentDidMount.resetHistory() SendTransactionScreen.prototype.updateGas.resetHistory() utilsMethodStubs.doesAmountErrorRequireUpdate.resetHistory() @@ -89,19 +89,19 @@ describe('Send Component', function () { propsMethodSpies.updateToNicknameIfNecessary.resetHistory() }) - it('should call componentDidMount', () => { + it('should call componentDidMount', function () { assert(SendTransactionScreen.prototype.componentDidMount.calledOnce) }) - describe('componentDidMount', () => { - it('should call props.fetchBasicGasAndTimeEstimates', () => { + describe('componentDidMount', function () { + it('should call props.fetchBasicGasAndTimeEstimates', function () { propsMethodSpies.fetchBasicGasEstimates.resetHistory() assert.equal(propsMethodSpies.fetchBasicGasEstimates.callCount, 0) wrapper.instance().componentDidMount() assert.equal(propsMethodSpies.fetchBasicGasEstimates.callCount, 1) }) - it('should call this.updateGas', async () => { + it('should call this.updateGas', async function () { SendTransactionScreen.prototype.updateGas.resetHistory() propsMethodSpies.updateSendErrors.resetHistory() assert.equal(SendTransactionScreen.prototype.updateGas.callCount, 0) @@ -111,8 +111,8 @@ describe('Send Component', function () { }) }) - describe('componentWillUnmount', () => { - it('should call this.props.resetSendState', () => { + describe('componentWillUnmount', function () { + it('should call this.props.resetSendState', function () { propsMethodSpies.resetSendState.resetHistory() assert.equal(propsMethodSpies.resetSendState.callCount, 0) wrapper.instance().componentWillUnmount() @@ -120,8 +120,8 @@ describe('Send Component', function () { }) }) - describe('componentDidUpdate', () => { - it('should call doesAmountErrorRequireUpdate with the expected params', () => { + describe('componentDidUpdate', function () { + it('should call doesAmountErrorRequireUpdate with the expected params', function () { utilsMethodStubs.getAmountErrorObject.resetHistory() wrapper.instance().componentDidUpdate({ from: { @@ -143,7 +143,7 @@ describe('Send Component', function () { ) }) - it('should not call getAmountErrorObject if doesAmountErrorRequireUpdate returns false', () => { + it('should not call getAmountErrorObject if doesAmountErrorRequireUpdate returns false', function () { utilsMethodStubs.getAmountErrorObject.resetHistory() wrapper.instance().componentDidUpdate({ from: { @@ -153,7 +153,7 @@ describe('Send Component', function () { assert.equal(utilsMethodStubs.getAmountErrorObject.callCount, 0) }) - it('should call getAmountErrorObject if doesAmountErrorRequireUpdate returns true', () => { + it('should call getAmountErrorObject if doesAmountErrorRequireUpdate returns true', function () { utilsMethodStubs.getAmountErrorObject.resetHistory() wrapper.instance().componentDidUpdate({ from: { @@ -176,7 +176,7 @@ describe('Send Component', function () { ) }) - it('should call getGasFeeErrorObject if doesAmountErrorRequireUpdate returns true and selectedToken is truthy', () => { + it('should call getGasFeeErrorObject if doesAmountErrorRequireUpdate returns true and selectedToken is truthy', function () { utilsMethodStubs.getGasFeeErrorObject.resetHistory() wrapper.instance().componentDidUpdate({ from: { @@ -197,7 +197,7 @@ describe('Send Component', function () { ) }) - it('should not call getGasFeeErrorObject if doesAmountErrorRequireUpdate returns false', () => { + it('should not call getGasFeeErrorObject if doesAmountErrorRequireUpdate returns false', function () { utilsMethodStubs.getGasFeeErrorObject.resetHistory() wrapper.instance().componentDidUpdate({ from: { address: 'mockAddress', balance: 'mockBalance' }, @@ -205,7 +205,7 @@ describe('Send Component', function () { assert.equal(utilsMethodStubs.getGasFeeErrorObject.callCount, 0) }) - it('should not call getGasFeeErrorObject if doesAmountErrorRequireUpdate returns true but selectedToken is falsy', () => { + it('should not call getGasFeeErrorObject if doesAmountErrorRequireUpdate returns true but selectedToken is falsy', function () { utilsMethodStubs.getGasFeeErrorObject.resetHistory() wrapper.setProps({ selectedToken: null }) wrapper.instance().componentDidUpdate({ @@ -216,7 +216,7 @@ describe('Send Component', function () { assert.equal(utilsMethodStubs.getGasFeeErrorObject.callCount, 0) }) - it('should call updateSendErrors with the expected params if selectedToken is falsy', () => { + it('should call updateSendErrors with the expected params if selectedToken is falsy', function () { propsMethodSpies.updateSendErrors.resetHistory() wrapper.setProps({ selectedToken: null }) wrapper.instance().componentDidUpdate({ @@ -231,7 +231,7 @@ describe('Send Component', function () { ) }) - it('should call updateSendErrors with the expected params if selectedToken is truthy', () => { + it('should call updateSendErrors with the expected params if selectedToken is truthy', function () { propsMethodSpies.updateSendErrors.resetHistory() wrapper.setProps({ selectedToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' } }) wrapper.instance().componentDidUpdate({ @@ -246,7 +246,7 @@ describe('Send Component', function () { ) }) - it('should not call updateSendTokenBalance or this.updateGas if network === prevNetwork', () => { + it('should not call updateSendTokenBalance or this.updateGas if network === prevNetwork', function () { SendTransactionScreen.prototype.updateGas.resetHistory() propsMethodSpies.updateSendTokenBalance.resetHistory() wrapper.instance().componentDidUpdate({ @@ -260,7 +260,7 @@ describe('Send Component', function () { assert.equal(SendTransactionScreen.prototype.updateGas.callCount, 0) }) - it('should not call updateSendTokenBalance or this.updateGas if network === loading', () => { + it('should not call updateSendTokenBalance or this.updateGas if network === loading', function () { wrapper.setProps({ network: 'loading' }) SendTransactionScreen.prototype.updateGas.resetHistory() propsMethodSpies.updateSendTokenBalance.resetHistory() @@ -275,7 +275,7 @@ describe('Send Component', function () { assert.equal(SendTransactionScreen.prototype.updateGas.callCount, 0) }) - it('should call updateSendTokenBalance and this.updateGas with the correct params', () => { + it('should call updateSendTokenBalance and this.updateGas with the correct params', function () { SendTransactionScreen.prototype.updateGas.resetHistory() propsMethodSpies.updateSendTokenBalance.resetHistory() wrapper.instance().componentDidUpdate({ @@ -301,7 +301,7 @@ describe('Send Component', function () { ) }) - it('should call updateGas when selectedToken.address is changed', () => { + it('should call updateGas when selectedToken.address is changed', function () { SendTransactionScreen.prototype.updateGas.resetHistory() propsMethodSpies.updateAndSetGasLimit.resetHistory() wrapper.instance().componentDidUpdate({ @@ -316,8 +316,8 @@ describe('Send Component', function () { }) }) - describe('updateGas', () => { - it('should call updateAndSetGasLimit with the correct params if no to prop is passed', () => { + describe('updateGas', function () { + it('should call updateAndSetGasLimit with the correct params if no to prop is passed', function () { propsMethodSpies.updateAndSetGasLimit.resetHistory() wrapper.instance().updateGas() assert.equal(propsMethodSpies.updateAndSetGasLimit.callCount, 1) @@ -338,7 +338,7 @@ describe('Send Component', function () { ) }) - it('should call updateAndSetGasLimit with the correct params if a to prop is passed', () => { + it('should call updateAndSetGasLimit with the correct params if a to prop is passed', function () { propsMethodSpies.updateAndSetGasLimit.resetHistory() wrapper.setProps({ to: 'someAddress' }) wrapper.instance().updateGas() @@ -348,24 +348,24 @@ describe('Send Component', function () { ) }) - it('should call updateAndSetGasLimit with to set to lowercase if passed', () => { + it('should call updateAndSetGasLimit with to set to lowercase if passed', function () { propsMethodSpies.updateAndSetGasLimit.resetHistory() wrapper.instance().updateGas({ to: '0xABC' }) assert.equal(propsMethodSpies.updateAndSetGasLimit.getCall(0).args[0].to, '0xabc') }) }) - describe('render', () => { - it('should render a page-container class', () => { + describe('render', function () { + it('should render a page-container class', function () { assert.equal(wrapper.find('.page-container').length, 1) }) - it('should render SendHeader and AddRecipient', () => { + it('should render SendHeader and AddRecipient', function () { assert.equal(wrapper.find(SendHeader).length, 1) assert.equal(wrapper.find(AddRecipient).length, 1) }) - it('should pass the history prop to SendHeader and SendFooter', () => { + it('should pass the history prop to SendHeader and SendFooter', function () { wrapper.setProps({ to: '0x80F061544cC398520615B5d3e7A3BedD70cd4510', }) @@ -380,7 +380,7 @@ describe('Send Component', function () { ) }) - it('should pass showHexData to SendContent', () => { + it('should pass showHexData to SendContent', function () { wrapper.setProps({ to: '0x80F061544cC398520615B5d3e7A3BedD70cd4510', }) @@ -388,18 +388,18 @@ describe('Send Component', function () { }) }) - describe('validate when input change', () => { + describe('validate when input change', function () { let clock - beforeEach(() => { + beforeEach(function () { clock = sinon.useFakeTimers() }) - afterEach(() => { + afterEach(function () { clock.restore() }) - it('should validate when input changes', () => { + it('should validate when input changes', function () { const instance = wrapper.instance() instance.onRecipientInputChange('0x80F061544cC398520615B5d3e7A3BedD70cd4510') @@ -410,7 +410,7 @@ describe('Send Component', function () { }) }) - it('should validate when input changes and has error', () => { + it('should validate when input changes and has error', function () { const instance = wrapper.instance() instance.onRecipientInputChange('0x80F061544cC398520615B5d3e7a3BedD70cd4510') @@ -422,7 +422,7 @@ describe('Send Component', function () { }) }) - it('should validate when input changes and has error', () => { + it('should validate when input changes and has error on a bad network', function () { wrapper.setProps({ network: 'bad' }) const instance = wrapper.instance() instance.onRecipientInputChange('0x80F061544cC398520615B5d3e7a3BedD70cd4510') @@ -435,7 +435,7 @@ describe('Send Component', function () { }) }) - it('should synchronously validate when input changes to ""', () => { + it('should synchronously validate when input changes to ""', function () { wrapper.setProps({ network: 'bad' }) const instance = wrapper.instance() instance.onRecipientInputChange('0x80F061544cC398520615B5d3e7a3BedD70cd4510') @@ -455,7 +455,7 @@ describe('Send Component', function () { }) }) - it('should warn when send to a known token contract address', () => { + it('should warn when send to a known token contract address', function () { wrapper.setProps({ address: '0x888', decimals: 18, symbol: '888' }) const instance = wrapper.instance() instance.onRecipientInputChange('0x13cb85823f78Cff38f0B0E90D3e975b8CB3AAd64') diff --git a/ui/app/pages/send/tests/send-container.test.js b/ui/app/pages/send/tests/send-container.test.js index 48221493b..403630d61 100644 --- a/ui/app/pages/send/tests/send-container.test.js +++ b/ui/app/pages/send/tests/send-container.test.js @@ -31,18 +31,18 @@ proxyquire('../send.container.js', { }) -describe('send container', () => { +describe('send container', function () { - describe('mapDispatchToProps()', () => { + describe('mapDispatchToProps()', function () { let dispatchSpy let mapDispatchToPropsObject - beforeEach(() => { + beforeEach(function () { dispatchSpy = sinon.spy() mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) }) - describe('updateAndSetGasLimit()', () => { + describe('updateAndSetGasLimit()', function () { const mockProps = { blockGasLimit: 'mockBlockGasLimit', editingTransactionId: '0x2', @@ -56,7 +56,7 @@ describe('send container', () => { data: undefined, } - it('should dispatch a setGasTotal action when editingTransactionId is truthy', () => { + it('should dispatch a setGasTotal action when editingTransactionId is truthy', function () { mapDispatchToPropsObject.updateAndSetGasLimit(mockProps) assert(dispatchSpy.calledOnce) assert.equal( @@ -65,7 +65,7 @@ describe('send container', () => { ) }) - it('should dispatch an updateGasData action when editingTransactionId is falsy', () => { + it('should dispatch an updateGasData action when editingTransactionId is falsy', function () { const { gasPrice, selectedAddress, selectedToken, recentBlocks, blockGasLimit, to, value, data } = mockProps mapDispatchToPropsObject.updateAndSetGasLimit( Object.assign({}, mockProps, { editingTransactionId: false }) @@ -78,14 +78,14 @@ describe('send container', () => { }) }) - describe('updateSendTokenBalance()', () => { + describe('updateSendTokenBalance()', function () { const mockProps = { address: '0x10', tokenContract: '0x00a', selectedToken: { address: '0x1' }, } - it('should dispatch an action', () => { + it('should dispatch an action', function () { mapDispatchToPropsObject.updateSendTokenBalance(Object.assign({}, mockProps)) assert(dispatchSpy.calledOnce) assert.deepEqual( @@ -95,8 +95,8 @@ describe('send container', () => { }) }) - describe('updateSendErrors()', () => { - it('should dispatch an action', () => { + describe('updateSendErrors()', function () { + it('should dispatch an action', function () { mapDispatchToPropsObject.updateSendErrors('mockError') assert(dispatchSpy.calledOnce) assert.equal( @@ -106,8 +106,8 @@ describe('send container', () => { }) }) - describe('resetSendState()', () => { - it('should dispatch an action', () => { + describe('resetSendState()', function () { + it('should dispatch an action', function () { mapDispatchToPropsObject.resetSendState() assert(dispatchSpy.calledOnce) assert.equal( diff --git a/ui/app/pages/send/tests/send-selectors.test.js b/ui/app/pages/send/tests/send-selectors.test.js index ca06f6524..0396311aa 100644 --- a/ui/app/pages/send/tests/send-selectors.test.js +++ b/ui/app/pages/send/tests/send-selectors.test.js @@ -39,9 +39,9 @@ import { } from '../send.selectors.js' import mockState from './send-selectors-test-data' -describe('send selectors', () => { +describe('send selectors', function () { const tempGlobalEth = Object.assign({}, global.eth) - beforeEach(() => { + beforeEach(function () { global.eth = { contract: sinon.stub().returns({ at: address => 'mockAt:' + address, @@ -49,12 +49,12 @@ describe('send selectors', () => { } }) - afterEach(() => { + afterEach(function () { global.eth = tempGlobalEth }) - describe('accountsWithSendEtherInfoSelector()', () => { - it('should return an array of account objects with name info from identities', () => { + describe('accountsWithSendEtherInfoSelector()', function () { + it('should return an array of account objects with name info from identities', function () { assert.deepEqual( accountsWithSendEtherInfoSelector(mockState), [ @@ -100,15 +100,15 @@ describe('send selectors', () => { // }) // }) - describe('getAmountConversionRate()', () => { - it('should return the token conversion rate if a token is selected', () => { + describe('getAmountConversionRate()', function () { + it('should return the token conversion rate if a token is selected', function () { assert.equal( getAmountConversionRate(mockState), 2401.76400654 ) }) - it('should return the eth conversion rate if no token is selected', () => { + it('should return the eth conversion rate if no token is selected', function () { const editedMockState = { metamask: Object.assign({}, mockState.metamask, { selectedTokenAddress: null }), } @@ -119,8 +119,8 @@ describe('send selectors', () => { }) }) - describe('getBlockGasLimit', () => { - it('should return the current block gas limit', () => { + describe('getBlockGasLimit', function () { + it('should return the current block gas limit', function () { assert.deepEqual( getBlockGasLimit(mockState), '0x4c1878' @@ -128,8 +128,8 @@ describe('send selectors', () => { }) }) - describe('getConversionRate()', () => { - it('should return the eth conversion rate', () => { + describe('getConversionRate()', function () { + it('should return the eth conversion rate', function () { assert.deepEqual( getConversionRate(mockState), 1200.88200327 @@ -137,8 +137,8 @@ describe('send selectors', () => { }) }) - describe('getCurrentAccountWithSendEtherInfo()', () => { - it('should return the currently selected account with identity info', () => { + describe('getCurrentAccountWithSendEtherInfo()', function () { + it('should return the currently selected account with identity info', function () { assert.deepEqual( getCurrentAccountWithSendEtherInfo(mockState), { @@ -152,8 +152,8 @@ describe('send selectors', () => { }) }) - describe('getCurrentCurrency()', () => { - it('should return the currently selected currency', () => { + describe('getCurrentCurrency()', function () { + it('should return the currently selected currency', function () { assert.equal( getCurrentCurrency(mockState), 'USD' @@ -161,8 +161,8 @@ describe('send selectors', () => { }) }) - describe('getNativeCurrency()', () => { - it('should return the ticker symbol of the selected network', () => { + describe('getNativeCurrency()', function () { + it('should return the ticker symbol of the selected network', function () { assert.equal( getNativeCurrency(mockState), 'ETH' @@ -170,8 +170,8 @@ describe('send selectors', () => { }) }) - describe('getCurrentNetwork()', () => { - it('should return the id of the currently selected network', () => { + describe('getCurrentNetwork()', function () { + it('should return the id of the currently selected network', function () { assert.equal( getCurrentNetwork(mockState), '3' @@ -179,8 +179,8 @@ describe('send selectors', () => { }) }) - describe('getForceGasMin()', () => { - it('should get the send.forceGasMin property', () => { + describe('getForceGasMin()', function () { + it('should get the send.forceGasMin property', function () { assert.equal( getForceGasMin(mockState), true @@ -188,8 +188,8 @@ describe('send selectors', () => { }) }) - describe('getGasLimit()', () => { - it('should return the send.gasLimit', () => { + describe('getGasLimit()', function () { + it('should return the send.gasLimit', function () { assert.equal( getGasLimit(mockState), '0xFFFF' @@ -197,8 +197,8 @@ describe('send selectors', () => { }) }) - describe('getGasPrice()', () => { - it('should return the send.gasPrice', () => { + describe('getGasPrice()', function () { + it('should return the send.gasPrice', function () { assert.equal( getGasPrice(mockState), '0xaa' @@ -206,8 +206,8 @@ describe('send selectors', () => { }) }) - describe('getGasTotal()', () => { - it('should return the send.gasTotal', () => { + describe('getGasTotal()', function () { + it('should return the send.gasTotal', function () { assert.equal( getGasTotal(mockState), 'a9ff56' @@ -215,8 +215,8 @@ describe('send selectors', () => { }) }) - describe('getPrimaryCurrency()', () => { - it('should return the symbol of the selected token', () => { + describe('getPrimaryCurrency()', function () { + it('should return the symbol of the selected token', function () { assert.equal( getPrimaryCurrency(mockState), 'DEF' @@ -224,8 +224,8 @@ describe('send selectors', () => { }) }) - describe('getRecentBlocks()', () => { - it('should return the recent blocks', () => { + describe('getRecentBlocks()', function () { + it('should return the recent blocks', function () { assert.deepEqual( getRecentBlocks(mockState), ['mockBlock1', 'mockBlock2', 'mockBlock3'] @@ -233,8 +233,8 @@ describe('send selectors', () => { }) }) - describe('getSelectedAccount()', () => { - it('should return the currently selected account', () => { + describe('getSelectedAccount()', function () { + it('should return the currently selected account', function () { assert.deepEqual( getSelectedAccount(mockState), { @@ -248,8 +248,8 @@ describe('send selectors', () => { }) - describe('getSelectedIdentity()', () => { - it('should return the identity object of the currently selected address', () => { + describe('getSelectedIdentity()', function () { + it('should return the identity object of the currently selected address', function () { assert.deepEqual( getSelectedIdentity(mockState), { @@ -260,8 +260,8 @@ describe('send selectors', () => { }) }) - describe('getSelectedToken()', () => { - it('should return the currently selected token if selected', () => { + describe('getSelectedToken()', function () { + it('should return the currently selected token if selected', function () { assert.deepEqual( getSelectedToken(mockState), { @@ -272,7 +272,7 @@ describe('send selectors', () => { ) }) - it('should return the send token if none is currently selected, but a send token exists', () => { + it('should return the send token if none is currently selected, but a send token exists', function () { const mockSendToken = { address: '0x123456708414189a58339873ab429b6c47ab92d3', decimals: 4, @@ -293,15 +293,15 @@ describe('send selectors', () => { }) }) - describe('getSelectedTokenContract()', () => { - it('should return the contract at the selected token address', () => { + describe('getSelectedTokenContract()', function () { + it('should return the contract at the selected token address', function () { assert.equal( getSelectedTokenContract(mockState), 'mockAt:0x8d6b81208414189a58339873ab429b6c47ab92d3' ) }) - it('should return null if no token is selected', () => { + it('should return null if no token is selected', function () { const modifiedMetamaskState = Object.assign({}, mockState.metamask, { selectedTokenAddress: false }) assert.equal( getSelectedTokenContract(Object.assign({}, mockState, { metamask: modifiedMetamaskState })), @@ -310,8 +310,8 @@ describe('send selectors', () => { }) }) - describe('getSelectedTokenExchangeRate()', () => { - it('should return the exchange rate for the selected token', () => { + describe('getSelectedTokenExchangeRate()', function () { + it('should return the exchange rate for the selected token', function () { assert.equal( getSelectedTokenExchangeRate(mockState), 2.0 @@ -319,8 +319,8 @@ describe('send selectors', () => { }) }) - describe('getSelectedTokenToFiatRate()', () => { - it('should return rate for converting the selected token to fiat', () => { + describe('getSelectedTokenToFiatRate()', function () { + it('should return rate for converting the selected token to fiat', function () { assert.equal( getSelectedTokenToFiatRate(mockState), 2401.76400654 @@ -328,8 +328,8 @@ describe('send selectors', () => { }) }) - describe('getSendAmount()', () => { - it('should return the send.amount', () => { + describe('getSendAmount()', function () { + it('should return the send.amount', function () { assert.equal( getSendAmount(mockState), '0x080' @@ -337,8 +337,8 @@ describe('send selectors', () => { }) }) - describe('getSendEditingTransactionId()', () => { - it('should return the send.editingTransactionId', () => { + describe('getSendEditingTransactionId()', function () { + it('should return the send.editingTransactionId', function () { assert.equal( getSendEditingTransactionId(mockState), 97531 @@ -346,8 +346,8 @@ describe('send selectors', () => { }) }) - describe('getSendErrors()', () => { - it('should return the send.errors', () => { + describe('getSendErrors()', function () { + it('should return the send.errors', function () { assert.deepEqual( getSendErrors(mockState), { someError: null } @@ -355,8 +355,8 @@ describe('send selectors', () => { }) }) - describe('getSendHexDataFeatureFlagState()', () => { - it('should return the sendHexData feature flag state', () => { + describe('getSendHexDataFeatureFlagState()', function () { + it('should return the sendHexData feature flag state', function () { assert.deepEqual( getSendHexDataFeatureFlagState(mockState), true @@ -364,8 +364,8 @@ describe('send selectors', () => { }) }) - describe('getSendFrom()', () => { - it('should return the send.from', () => { + describe('getSendFrom()', function () { + it('should return the send.from', function () { assert.deepEqual( getSendFrom(mockState), { @@ -376,15 +376,15 @@ describe('send selectors', () => { }) }) - describe('getSendFromBalance()', () => { - it('should get the send.from balance if it exists', () => { + describe('getSendFromBalance()', function () { + it('should get the send.from balance if it exists', function () { assert.equal( getSendFromBalance(mockState), '0x5f4e3d2c1' ) }) - it('should get the selected account balance if the send.from does not exist', () => { + it('should get the selected account balance if the send.from does not exist', function () { const editedMockState = { metamask: Object.assign({}, mockState.metamask, { send: { @@ -399,8 +399,8 @@ describe('send selectors', () => { }) }) - describe('getSendFromObject()', () => { - it('should return send.from if it exists', () => { + describe('getSendFromObject()', function () { + it('should return send.from if it exists', function () { assert.deepEqual( getSendFromObject(mockState), { @@ -410,7 +410,7 @@ describe('send selectors', () => { ) }) - it('should return the current account with send ether info if send.from does not exist', () => { + it('should return the current account with send ether info if send.from does not exist', function () { const editedMockState = { metamask: Object.assign({}, mockState.metamask, { send: { @@ -431,8 +431,8 @@ describe('send selectors', () => { }) }) - describe('getSendMaxModeState()', () => { - it('should return send.maxModeOn', () => { + describe('getSendMaxModeState()', function () { + it('should return send.maxModeOn', function () { assert.equal( getSendMaxModeState(mockState), false @@ -440,8 +440,8 @@ describe('send selectors', () => { }) }) - describe('getSendTo()', () => { - it('should return send.to', () => { + describe('getSendTo()', function () { + it('should return send.to', function () { assert.equal( getSendTo(mockState), '0x987fedabc' @@ -449,8 +449,8 @@ describe('send selectors', () => { }) }) - describe('getSendToAccounts()', () => { - it('should return an array including all the users accounts and the address book', () => { + describe('getSendToAccounts()', function () { + it('should return an array including all the users accounts and the address book', function () { assert.deepEqual( getSendToAccounts(mockState), [ @@ -492,8 +492,8 @@ describe('send selectors', () => { }) }) - describe('getTokenBalance()', () => { - it('should', () => { + describe('getTokenBalance()', function () { + it('should', function () { assert.equal( getTokenBalance(mockState), 3434 @@ -501,8 +501,8 @@ describe('send selectors', () => { }) }) - describe('getTokenExchangeRate()', () => { - it('should return the passed tokens exchange rates', () => { + describe('getTokenExchangeRate()', function () { + it('should return the passed tokens exchange rates', function () { assert.equal( getTokenExchangeRate(mockState, 'GHI'), 31.01 @@ -510,8 +510,8 @@ describe('send selectors', () => { }) }) - describe('getUnapprovedTxs()', () => { - it('should return the unapproved txs', () => { + describe('getUnapprovedTxs()', function () { + it('should return the unapproved txs', function () { assert.deepEqual( getUnapprovedTxs(mockState), { @@ -541,8 +541,8 @@ describe('send selectors', () => { }) }) - describe('transactionsSelector()', () => { - it('should return the selected addresses selected token transactions', () => { + describe('transactionsSelector()', function () { + it('should return the selected addresses selected token transactions', function () { assert.deepEqual( transactionsSelector(mockState), [ @@ -564,7 +564,7 @@ describe('send selectors', () => { ) }) - it('should return all transactions if no token is selected', () => { + it('should return all transactions if no token is selected', function () { const modifiedMetamaskState = Object.assign({}, mockState.metamask, { selectedTokenAddress: false }) const modifiedState = Object.assign({}, mockState, { metamask: modifiedMetamaskState }) assert.deepEqual( @@ -614,7 +614,7 @@ describe('send selectors', () => { ) }) - it('should return shapeshift transactions if current network is 1', () => { + it('should return shapeshift transactions if current network is 1', function () { const modifiedMetamaskState = Object.assign({}, mockState.metamask, { selectedTokenAddress: false, network: '1' }) const modifiedState = Object.assign({}, mockState, { metamask: modifiedMetamaskState }) assert.deepEqual( diff --git a/ui/app/pages/send/tests/send-utils.test.js b/ui/app/pages/send/tests/send-utils.test.js index b96ed6d52..d66de02de 100644 --- a/ui/app/pages/send/tests/send-utils.test.js +++ b/ui/app/pages/send/tests/send-utils.test.js @@ -59,10 +59,10 @@ const { removeLeadingZeroes, } = sendUtils -describe('send utils', () => { +describe('send utils', function () { - describe('calcGasTotal()', () => { - it('should call multiplyCurrencies with the correct params and return the multiplyCurrencies return', () => { + describe('calcGasTotal()', function () { + it('should call multiplyCurrencies with the correct params and return the multiplyCurrencies return', function () { const result = calcGasTotal(12, 15) assert.equal(result, '12x15') const call_ = stubs.multiplyCurrencies.getCall(0).args @@ -77,7 +77,7 @@ describe('send utils', () => { }) }) - describe('doesAmountErrorRequireUpdate()', () => { + describe('doesAmountErrorRequireUpdate()', function () { const config = { 'should return true if balances are different': { balance: 0, @@ -107,19 +107,19 @@ describe('send utils', () => { }, } Object.entries(config).map(([description, obj]) => { - it(description, () => { + it(description, function () { assert.equal(doesAmountErrorRequireUpdate(obj), obj.expectedResult) }) }) }) - describe('generateTokenTransferData()', () => { - it('should return undefined if not passed a selected token', () => { + describe('generateTokenTransferData()', function () { + it('should return undefined if not passed a selected token', function () { assert.equal(generateTokenTransferData({ toAddress: 'mockAddress', amount: '0xa', selectedToken: false }), undefined) }) - it('should call abi.rawEncode with the correct params', () => { + it('should call abi.rawEncode with the correct params', function () { stubs.rawEncode.resetHistory() generateTokenTransferData({ toAddress: 'mockAddress', amount: 'ab', selectedToken: true }) assert.deepEqual( @@ -128,7 +128,7 @@ describe('send utils', () => { ) }) - it('should return encoded token transfer data', () => { + it('should return encoded token transfer data', function () { assert.equal( generateTokenTransferData({ toAddress: 'mockAddress', amount: '0xa', selectedToken: true }), '0xa9059cbb104c' @@ -136,7 +136,7 @@ describe('send utils', () => { }) }) - describe('getAmountErrorObject()', () => { + describe('getAmountErrorObject()', function () { const config = { 'should return insufficientFunds error if isBalanceSufficient returns false': { amount: 15, @@ -173,13 +173,13 @@ describe('send utils', () => { }, } Object.entries(config).map(([description, obj]) => { - it(description, () => { + it(description, function () { assert.deepEqual(getAmountErrorObject(obj), obj.expectedResult) }) }) }) - describe('getGasFeeErrorObject()', () => { + describe('getGasFeeErrorObject()', function () { const config = { 'should return insufficientFunds error if isBalanceSufficient returns false': { amountConversionRate: 2, @@ -199,14 +199,14 @@ describe('send utils', () => { }, } Object.entries(config).map(([description, obj]) => { - it(description, () => { + it(description, function () { assert.deepEqual(getGasFeeErrorObject(obj), obj.expectedResult) }) }) }) - describe('calcTokenBalance()', () => { - it('should return the calculated token blance', () => { + describe('calcTokenBalance()', function () { + it('should return the calculated token blance', function () { assert.equal(calcTokenBalance({ selectedToken: { decimals: 11, @@ -218,8 +218,8 @@ describe('send utils', () => { }) }) - describe('isBalanceSufficient()', () => { - it('should correctly call addCurrencies and return the result of calling conversionGTE', () => { + describe('isBalanceSufficient()', function () { + it('should correctly call addCurrencies and return the result of calling conversionGTE', function () { stubs.conversionGTE.resetHistory() const result = isBalanceSufficient({ amount: 15, @@ -261,8 +261,8 @@ describe('send utils', () => { }) }) - describe('isTokenBalanceSufficient()', () => { - it('should correctly call conversionUtil and return the result of calling conversionGTE', () => { + describe('isTokenBalanceSufficient()', function () { + it('should correctly call conversionUtil and return the result of calling conversionGTE', function () { stubs.conversionGTE.resetHistory() stubs.conversionUtil.resetHistory() const result = isTokenBalanceSufficient({ @@ -295,7 +295,7 @@ describe('send utils', () => { }) }) - describe('estimateGas', () => { + describe('estimateGas', function () { const baseMockParams = { blockGasLimit: '0x64', selectedAddress: 'mockAddress', @@ -317,7 +317,7 @@ describe('send utils', () => { value: '0xff', } - beforeEach(() => { + beforeEach(function () { global.eth = { getCode: sinon.stub().callsFake( (address) => Promise.resolve(address.match(/isContract/) ? 'not-0x' : '0x') @@ -325,12 +325,12 @@ describe('send utils', () => { } }) - afterEach(() => { + afterEach(function () { baseMockParams.estimateGasMethod.resetHistory() global.eth.getCode.resetHistory() }) - it('should call ethQuery.estimateGas with the expected params', async () => { + it('should call ethQuery.estimateGas with the expected params', async function () { const result = await sendUtils.estimateGas(baseMockParams) assert.equal(baseMockParams.estimateGasMethod.callCount, 1) assert.deepEqual( @@ -340,7 +340,7 @@ describe('send utils', () => { assert.equal(result, '0xabc16') }) - it('should call ethQuery.estimateGas with the expected params when initialGasLimitHex is lower than the upperGasLimit', async () => { + it('should call ethQuery.estimateGas with the expected params when initialGasLimitHex is lower than the upperGasLimit', async function () { const result = await estimateGas(Object.assign({}, baseMockParams, { blockGasLimit: '0xbcd' })) assert.equal(baseMockParams.estimateGasMethod.callCount, 1) assert.deepEqual( @@ -350,7 +350,7 @@ describe('send utils', () => { assert.equal(result, '0xabc16x1.5') }) - it('should call ethQuery.estimateGas with a value of 0x0 and the expected data and to if passed a selectedToken', async () => { + it('should call ethQuery.estimateGas with a value of 0x0 and the expected data and to if passed a selectedToken', async function () { const result = await estimateGas(Object.assign({ data: 'mockData', selectedToken: { address: 'mockAddress' } }, baseMockParams)) assert.equal(baseMockParams.estimateGasMethod.callCount, 1) assert.deepEqual( @@ -365,7 +365,7 @@ describe('send utils', () => { assert.equal(result, '0xabc16') }) - it('should call ethQuery.estimateGas without a recipient if the recipient is empty and data passed', async () => { + it('should call ethQuery.estimateGas without a recipient if the recipient is empty and data passed', async function () { const data = 'mockData' const to = '' const result = await estimateGas({ ...baseMockParams, data, to }) @@ -377,44 +377,44 @@ describe('send utils', () => { assert.equal(result, '0xabc16') }) - it(`should return ${SIMPLE_GAS_COST} if ethQuery.getCode does not return '0x'`, async () => { + it(`should return ${SIMPLE_GAS_COST} if ethQuery.getCode does not return '0x'`, async function () { assert.equal(baseMockParams.estimateGasMethod.callCount, 0) const result = await estimateGas(Object.assign({}, baseMockParams, { to: '0x123' })) assert.equal(result, SIMPLE_GAS_COST) }) - it(`should return ${SIMPLE_GAS_COST} if not passed a selectedToken or truthy to address`, async () => { + it(`should return ${SIMPLE_GAS_COST} if not passed a selectedToken or truthy to address`, async function () { assert.equal(baseMockParams.estimateGasMethod.callCount, 0) const result = await estimateGas(Object.assign({}, baseMockParams, { to: null })) assert.equal(result, SIMPLE_GAS_COST) }) - it(`should not return ${SIMPLE_GAS_COST} if passed a selectedToken`, async () => { + it(`should not return ${SIMPLE_GAS_COST} if passed a selectedToken`, async function () { assert.equal(baseMockParams.estimateGasMethod.callCount, 0) const result = await estimateGas(Object.assign({}, baseMockParams, { to: '0x123', selectedToken: { address: '' } })) assert.notEqual(result, SIMPLE_GAS_COST) }) - it(`should return ${BASE_TOKEN_GAS_COST} if passed a selectedToken but no to address`, async () => { + it(`should return ${BASE_TOKEN_GAS_COST} if passed a selectedToken but no to address`, async function () { const result = await estimateGas(Object.assign({}, baseMockParams, { to: null, selectedToken: { address: '' } })) assert.equal(result, BASE_TOKEN_GAS_COST) }) - it(`should return the adjusted blockGasLimit if it fails with a 'Transaction execution error.'`, async () => { + it(`should return the adjusted blockGasLimit if it fails with a 'Transaction execution error.'`, async function () { const result = await estimateGas(Object.assign({}, baseMockParams, { to: 'isContract willFailBecauseOf:Transaction execution error.', })) assert.equal(result, '0x64x0.95') }) - it(`should return the adjusted blockGasLimit if it fails with a 'gas required exceeds allowance or always failing transaction.'`, async () => { + it(`should return the adjusted blockGasLimit if it fails with a 'gas required exceeds allowance or always failing transaction.'`, async function () { const result = await estimateGas(Object.assign({}, baseMockParams, { to: 'isContract willFailBecauseOf:gas required exceeds allowance or always failing transaction.', })) assert.equal(result, '0x64x0.95') }) - it(`should reject other errors`, async () => { + it(`should reject other errors`, async function () { try { await estimateGas(Object.assign({}, baseMockParams, { to: 'isContract willFailBecauseOf:some other error', @@ -425,7 +425,7 @@ describe('send utils', () => { }) }) - describe('estimateGasPriceFromRecentBlocks', () => { + describe('estimateGasPriceFromRecentBlocks', function () { const ONE_GWEI_IN_WEI_HEX_PLUS_ONE = addCurrencies(ONE_GWEI_IN_WEI_HEX, '0x1', { aBase: 16, bBase: 16, @@ -442,15 +442,15 @@ describe('send utils', () => { toNumericBase: 'hex', }) - it(`should return ${ONE_GWEI_IN_WEI_HEX} if recentBlocks is falsy`, () => { + it(`should return ${ONE_GWEI_IN_WEI_HEX} if recentBlocks is falsy`, function () { assert.equal(estimateGasPriceFromRecentBlocks(), ONE_GWEI_IN_WEI_HEX) }) - it(`should return ${ONE_GWEI_IN_WEI_HEX} if recentBlocks is empty`, () => { + it(`should return ${ONE_GWEI_IN_WEI_HEX} if recentBlocks is empty`, function () { assert.equal(estimateGasPriceFromRecentBlocks([]), ONE_GWEI_IN_WEI_HEX) }) - it(`should estimate a block's gasPrice as ${ONE_GWEI_IN_WEI_HEX} if it has no gas prices`, () => { + it(`should estimate a block's gasPrice as ${ONE_GWEI_IN_WEI_HEX} if it has no gas prices`, function () { const mockRecentBlocks = [ { gasPrices: null }, { gasPrices: [ ONE_GWEI_IN_WEI_HEX_PLUS_ONE ] }, @@ -459,7 +459,7 @@ describe('send utils', () => { assert.equal(estimateGasPriceFromRecentBlocks(mockRecentBlocks), ONE_GWEI_IN_WEI_HEX) }) - it(`should estimate a block's gasPrice as ${ONE_GWEI_IN_WEI_HEX} if it has empty gas prices`, () => { + it(`should estimate a block's gasPrice as ${ONE_GWEI_IN_WEI_HEX} if it has empty gas prices`, function () { const mockRecentBlocks = [ { gasPrices: [] }, { gasPrices: [ ONE_GWEI_IN_WEI_HEX_PLUS_ONE ] }, @@ -468,7 +468,7 @@ describe('send utils', () => { assert.equal(estimateGasPriceFromRecentBlocks(mockRecentBlocks), ONE_GWEI_IN_WEI_HEX) }) - it(`should return the middle value of all blocks lowest prices`, () => { + it(`should return the middle value of all blocks lowest prices`, function () { const mockRecentBlocks = [ { gasPrices: [ ONE_GWEI_IN_WEI_HEX_PLUS_TWO ] }, { gasPrices: [ ONE_GWEI_IN_WEI_HEX_MINUS_ONE ] }, @@ -477,7 +477,7 @@ describe('send utils', () => { assert.equal(estimateGasPriceFromRecentBlocks(mockRecentBlocks), ONE_GWEI_IN_WEI_HEX_PLUS_ONE) }) - it(`should work if a block has multiple gas prices`, () => { + it(`should work if a block has multiple gas prices`, function () { const mockRecentBlocks = [ { gasPrices: [ '0x1', '0x2', '0x3', '0x4', '0x5' ] }, { gasPrices: [ '0x101', '0x100', '0x103', '0x104', '0x102' ] }, @@ -487,30 +487,30 @@ describe('send utils', () => { }) }) - describe('getToAddressForGasUpdate()', () => { - it('should return empty string if all params are undefined or null', () => { + describe('getToAddressForGasUpdate()', function () { + it('should return empty string if all params are undefined or null', function () { assert.equal(getToAddressForGasUpdate(undefined, null), '') }) - it('should return the first string that is not defined or null in lower case', () => { + it('should return the first string that is not defined or null in lower case', function () { assert.equal(getToAddressForGasUpdate('A', null), 'a') assert.equal(getToAddressForGasUpdate(undefined, 'B'), 'b') }) }) - describe('removeLeadingZeroes()', () => { - it('should remove leading zeroes from int when user types', () => { + describe('removeLeadingZeroes()', function () { + it('should remove leading zeroes from int when user types', function () { assert.equal(removeLeadingZeroes('0'), '0') assert.equal(removeLeadingZeroes('1'), '1') assert.equal(removeLeadingZeroes('00'), '0') assert.equal(removeLeadingZeroes('01'), '1') }) - it('should remove leading zeroes from int when user copy/paste', () => { + it('should remove leading zeroes from int when user copy/paste', function () { assert.equal(removeLeadingZeroes('001'), '1') }) - it('should remove leading zeroes from float when user types', () => { + it('should remove leading zeroes from float when user types', function () { assert.equal(removeLeadingZeroes('0.'), '0.') assert.equal(removeLeadingZeroes('0.0'), '0.0') assert.equal(removeLeadingZeroes('0.00'), '0.00') @@ -518,7 +518,7 @@ describe('send utils', () => { assert.equal(removeLeadingZeroes('0.10'), '0.10') }) - it('should remove leading zeroes from float when user copy/paste', () => { + it('should remove leading zeroes from float when user copy/paste', function () { assert.equal(removeLeadingZeroes('00.1'), '0.1') }) }) diff --git a/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js b/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js index 70e8f4ca6..f8d9cfa0e 100644 --- a/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js +++ b/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js @@ -5,8 +5,8 @@ import { shallow } from 'enzyme' import AdvancedTab from '../advanced-tab.component' import TextField from '../../../../components/ui/text-field' -describe('AdvancedTab Component', () => { - it('should render correctly when threeBoxFeatureFlag', () => { +describe('AdvancedTab Component', function () { + it('should render correctly when threeBoxFeatureFlag', function () { const root = shallow( { assert.equal(root.find('.settings-page__content-row').length, 10) }) - it('should update autoLockTimeLimit', () => { + it('should update autoLockTimeLimit', function () { const setAutoLockTimeLimitSpy = sinon.spy() const root = shallow( { +describe('Security Tab', function () { let wrapper const props = { @@ -21,7 +21,7 @@ describe('Security Tab', () => { participateInMetaMetrics: false, } - beforeEach(() => { + beforeEach(function () { wrapper = mount( , { context: { @@ -32,7 +32,7 @@ describe('Security Tab', () => { ) }) - it('navigates to reveal seed words page', () => { + it('navigates to reveal seed words page', function () { const seedWords = wrapper.find('.button.btn-danger.btn--large') seedWords.simulate('click') @@ -40,13 +40,13 @@ describe('Security Tab', () => { assert.equal(props.history.push.getCall(0).args[0], '/seed') }) - it('toggles incoming txs', () => { + it('toggles incoming txs', function () { const incomingTxs = wrapper.find({ type: 'checkbox' }).at(0) incomingTxs.simulate('click') assert(props.setShowIncomingTransactionsFeatureFlag.calledOnce) }) - it('toggles metaMetrics', () => { + it('toggles metaMetrics', function () { const metaMetrics = wrapper.find({ type: 'checkbox' }).at(1) metaMetrics.simulate('click') diff --git a/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js b/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js index 6481b908d..e9ae891eb 100644 --- a/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js +++ b/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js @@ -4,7 +4,7 @@ import sinon from 'sinon' import { mount } from 'enzyme' import SettingsTab from '../index' -describe('Settings Tab', () => { +describe('Settings Tab', function () { let wrapper const props = { @@ -21,7 +21,7 @@ describe('Settings Tab', () => { nativeCurrency: 'eth', useNativeCurrencyAsPrimaryCurrency: true, } - beforeEach(() => { + beforeEach(function () { wrapper = mount( , { context: { @@ -31,28 +31,28 @@ describe('Settings Tab', () => { ) }) - it('selects currency', async () => { + it('selects currency', async function () { const selectCurrency = wrapper.find({ placeholder: 'selectCurrency' }) selectCurrency.props().onSelect('eur') assert(props.setCurrentCurrency.calledOnce) }) - it('selects locale', async () => { + it('selects locale', async function () { const selectLocale = wrapper.find({ placeholder: 'selectLocale' }) await selectLocale.props().onSelect('ja') assert(props.updateCurrentLocale.calledOnce) }) - it('sets fiat primary currency', () => { + it('sets fiat primary currency', function () { const selectFiat = wrapper.find('#fiat-primary-currency') selectFiat.simulate('change') assert(props.setUseNativeCurrencyAsPrimaryCurrencyPreference.calledOnce) }) - it('toggles blockies', () => { + it('toggles blockies', function () { const toggleBlockies = wrapper.find({ type: 'checkbox' }) toggleBlockies.simulate('click') diff --git a/ui/app/pages/unlock-page/tests/unlock-page.test.js b/ui/app/pages/unlock-page/tests/unlock-page.test.js index 8b1e05729..1af83682d 100644 --- a/ui/app/pages/unlock-page/tests/unlock-page.test.js +++ b/ui/app/pages/unlock-page/tests/unlock-page.test.js @@ -4,7 +4,7 @@ import sinon from 'sinon' import { mount } from 'enzyme' import UnlockPage from '../index' -describe('Unlock Page', () => { +describe('Unlock Page', function () { let wrapper const props = { @@ -20,7 +20,7 @@ describe('Unlock Page', () => { } - beforeEach(() => { + beforeEach(function () { wrapper = mount( , { @@ -32,15 +32,15 @@ describe('Unlock Page', () => { }) - after(() => { + after(function () { sinon.restore() }) - it('renders', () => { + it('renders', function () { assert.equal(wrapper.length, 1) }) - it('changes password and submits', () => { + it('changes password and submits', function () { const passwordField = wrapper.find({ type: 'password', id: 'password' }) const loginButton = wrapper.find({ type: 'submit' }).last() @@ -53,7 +53,7 @@ describe('Unlock Page', () => { assert(props.onSubmit.calledOnce) }) - it('clicks imports seed button', () => { + it('clicks imports seed button', function () { const importSeedButton = wrapper.find('.unlock-page__link--import') importSeedButton.simulate('click') @@ -61,7 +61,7 @@ describe('Unlock Page', () => { }) - it('clicks restore', () => { + it('clicks restore', function () { const restoreFromSeedButton = wrapper.find('.unlock-page__link').at(0) restoreFromSeedButton.simulate('click') assert(props.onRestore.calledOnce) diff --git a/ui/app/selectors/custom-gas.test.js b/ui/app/selectors/custom-gas.test.js index 16b30bedd..00c6d852a 100644 --- a/ui/app/selectors/custom-gas.test.js +++ b/ui/app/selectors/custom-gas.test.js @@ -13,45 +13,45 @@ const { getRenderableEstimateDataForSmallButtonsFromGWEI, } = proxyquire('./custom-gas', {}) -describe('custom-gas selectors', () => { +describe('custom-gas selectors', function () { - describe('getCustomGasPrice()', () => { - it('should return gas.customData.price', () => { + describe('getCustomGasPrice()', function () { + it('should return gas.customData.price', function () { const mockState = { gas: { customData: { price: 'mockPrice' } } } assert.equal(getCustomGasPrice(mockState), 'mockPrice') }) }) - describe('getCustomGasLimit()', () => { - it('should return gas.customData.limit', () => { + describe('getCustomGasLimit()', function () { + it('should return gas.customData.limit', function () { const mockState = { gas: { customData: { limit: 'mockLimit' } } } assert.equal(getCustomGasLimit(mockState), 'mockLimit') }) }) - describe('getCustomGasTotal()', () => { - it('should return gas.customData.total', () => { + describe('getCustomGasTotal()', function () { + it('should return gas.customData.total', function () { const mockState = { gas: { customData: { total: 'mockTotal' } } } assert.equal(getCustomGasTotal(mockState), 'mockTotal') }) }) - describe('getCustomGasErrors()', () => { - it('should return gas.errors', () => { + describe('getCustomGasErrors()', function () { + it('should return gas.errors', function () { const mockState = { gas: { errors: 'mockErrors' } } assert.equal(getCustomGasErrors(mockState), 'mockErrors') }) }) - describe('getPriceAndTimeEstimates', () => { - it('should return price and time estimates', () => { + describe('getPriceAndTimeEstimates', function () { + it('should return price and time estimates', function () { const mockState = { gas: { priceAndTimeEstimates: 'mockPriceAndTimeEstimates' } } assert.equal(getPriceAndTimeEstimates(mockState), 'mockPriceAndTimeEstimates') }) }) - describe('getEstimatedGasPrices', () => { - it('should return price and time estimates', () => { + describe('getEstimatedGasPrices', function () { + it('should return price and time estimates', function () { const mockState = { gas: { priceAndTimeEstimates: [ { gasprice: 12, somethingElse: 20 }, { gasprice: 22, expectedTime: 30 }, @@ -61,8 +61,8 @@ describe('custom-gas selectors', () => { }) }) - describe('getEstimatedGasTimes', () => { - it('should return price and time estimates', () => { + describe('getEstimatedGasTimes', function () { + it('should return price and time estimates', function () { const mockState = { gas: { priceAndTimeEstimates: [ { somethingElse: 12, expectedTime: 20 }, { gasPrice: 22, expectedTime: 30 }, @@ -72,7 +72,7 @@ describe('custom-gas selectors', () => { }) }) - describe('getRenderableBasicEstimateData()', () => { + describe('getRenderableBasicEstimateData()', function () { const tests = [ { expectedResult: [ @@ -337,7 +337,7 @@ describe('custom-gas selectors', () => { }, }, ] - it('should return renderable data about basic estimates', () => { + it('should return renderable data about basic estimates', function () { tests.forEach(test => { assert.deepEqual( getRenderableBasicEstimateData(test.mockState, '0x5208'), @@ -348,7 +348,7 @@ describe('custom-gas selectors', () => { }) - describe('getRenderableEstimateDataForSmallButtonsFromGWEI()', () => { + describe('getRenderableEstimateDataForSmallButtonsFromGWEI()', function () { const tests = [ { expectedResult: [ @@ -601,7 +601,7 @@ describe('custom-gas selectors', () => { }, }, ] - it('should return renderable data about basic estimates appropriate for buttons with less info', () => { + it('should return renderable data about basic estimates appropriate for buttons with less info', function () { tests.forEach(test => { assert.deepEqual( getRenderableEstimateDataForSmallButtonsFromGWEI(test.mockState), diff --git a/ui/app/selectors/tests/confirm-transaction.test.js b/ui/app/selectors/tests/confirm-transaction.test.js index db8772868..177d7b50a 100644 --- a/ui/app/selectors/tests/confirm-transaction.test.js +++ b/ui/app/selectors/tests/confirm-transaction.test.js @@ -7,9 +7,9 @@ import { contractExchangeRateSelector, } from '../confirm-transaction' -describe('Confirm Transaction Selector', () => { +describe('Confirm Transaction Selector', function () { - describe('unconfirmedTransactionsCountSelector', () => { + describe('unconfirmedTransactionsCountSelector', function () { const state = { metamask: { @@ -28,13 +28,13 @@ describe('Confirm Transaction Selector', () => { }, } - it('returns number of txs in unapprovedTxs state with the same network plus unapproved signing method counts', () => { + it('returns number of txs in unapprovedTxs state with the same network plus unapproved signing method counts', function () { assert.equal(unconfirmedTransactionsCountSelector(state), 4) }) }) - describe('tokenAmountAndToAddressSelector', () => { + describe('tokenAmountAndToAddressSelector', function () { const state = { confirmTransaction: { @@ -60,14 +60,14 @@ describe('Confirm Transaction Selector', () => { }, } - it('returns calulcated token amount based on token value and token decimals and recipient address', () => { + it('returns calulcated token amount based on token value and token decimals and recipient address', function () { assert.deepEqual(tokenAmountAndToAddressSelector(state), { toAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', tokenAmount: 0.01 }) }) }) - describe('approveTokenAmountAndToAddressSelector', () => { + describe('approveTokenAmountAndToAddressSelector', function () { const state = { confirmTransaction: { @@ -93,14 +93,14 @@ describe('Confirm Transaction Selector', () => { }, } - it('returns token amount and recipient for approve token allocation spending', () => { + it('returns token amount and recipient for approve token allocation spending', function () { assert.deepEqual(approveTokenAmountAndToAddressSelector(state), { toAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', tokenAmount: 0.01 }) }) }) - describe('sendTokenTokenAmountAndToAddressSelector', () => { + describe('sendTokenTokenAmountAndToAddressSelector', function () { const state = { confirmTransaction: { @@ -126,14 +126,14 @@ describe('Confirm Transaction Selector', () => { }, } - it('returns token address and calculated token amount', () => { + it('returns token address and calculated token amount', function () { assert.deepEqual(sendTokenTokenAmountAndToAddressSelector(state), { toAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', tokenAmount: 0.01 }) }) }) - describe('contractExchangeRateSelector', () => { + describe('contractExchangeRateSelector', function () { const state = { metamask: { @@ -150,7 +150,7 @@ describe('Confirm Transaction Selector', () => { }, } - it('returns contract exchange rate in metamask state based on confirm transaction txParams token recipient', () => { + it('returns contract exchange rate in metamask state based on confirm transaction txParams token recipient', function () { assert.equal(contractExchangeRateSelector(state), 10) }) diff --git a/ui/app/selectors/tests/selectors.test.js b/ui/app/selectors/tests/selectors.test.js index 16170bc6b..655073b8f 100644 --- a/ui/app/selectors/tests/selectors.test.js +++ b/ui/app/selectors/tests/selectors.test.js @@ -2,10 +2,10 @@ import assert from 'assert' import { getAddressBook } from '../selectors.js' import mockState from './selectors-test-data' -describe('selectors', () => { +describe('selectors', function () { - describe('getAddressBook()', () => { - it('should return the address book', () => { + describe('getAddressBook()', function () { + it('should return the address book', function () { assert.deepEqual( getAddressBook(mockState), [ diff --git a/ui/app/selectors/tests/tokens.test.js b/ui/app/selectors/tests/tokens.test.js index d058f4a05..c4c1cc554 100644 --- a/ui/app/selectors/tests/tokens.test.js +++ b/ui/app/selectors/tests/tokens.test.js @@ -20,8 +20,8 @@ const state = { ], }, } -describe('Selected Token Selector', () => { - it('selects token info from tokens based on selectedTokenAddress in state', () => { +describe('Selected Token Selector', function () { + it('selects token info from tokens based on selectedTokenAddress in state', function () { const tokenInfo = selectedTokenSelector(state) assert.equal(tokenInfo, metaToken) }) diff --git a/ui/app/selectors/tests/transactions.test.js b/ui/app/selectors/tests/transactions.test.js index 3ab1be47c..a6bc5c3af 100644 --- a/ui/app/selectors/tests/transactions.test.js +++ b/ui/app/selectors/tests/transactions.test.js @@ -8,10 +8,10 @@ import { submittedPendingTransactionsSelector, } from '../transactions' -describe('Transaction Selectors', () => { +describe('Transaction Selectors', function () { - describe('unapprovedMessagesSelector', () => { - it('returns eth sign msg from unapprovedMsgs', () => { + describe('unapprovedMessagesSelector', function () { + it('returns eth sign msg from unapprovedMsgs', function () { const msg = { id: 1, @@ -39,7 +39,7 @@ describe('Transaction Selectors', () => { assert.deepEqual(msgSelector, [msg]) }) - it('returns personal sign from unapprovedPersonalMsgsSelector', () => { + it('returns personal sign from unapprovedPersonalMsgsSelector', function () { const msg = { id: 1, @@ -67,7 +67,7 @@ describe('Transaction Selectors', () => { assert.deepEqual(msgSelector, [msg]) }) - it('returns typed message from unapprovedTypedMessagesSelector', () => { + it('returns typed message from unapprovedTypedMessagesSelector', function () { const msg = { id: 1, @@ -98,9 +98,9 @@ describe('Transaction Selectors', () => { }) }) - describe('transactionsSelector', () => { + describe('transactionsSelector', function () { - it('selectedAddressTxList', () => { + it('selectedAddressTxList', function () { const state = { metamask: { @@ -136,7 +136,7 @@ describe('Transaction Selectors', () => { assert.deepEqual(txSelector, orderedTxlist) }) - it('returns token tx from selectedAddressTxList when selectedTokenAddress is valid', () => { + it('returns token tx from selectedAddressTxList when selectedTokenAddress is valid', function () { const state = { metamask: { @@ -177,9 +177,9 @@ describe('Transaction Selectors', () => { }) - describe('nonceSortedTransactionsSelector', () => { + describe('nonceSortedTransactionsSelector', function () { - it('returns transaction group nonce sorted tx from from selectedTxList wit', () => { + it('returns transaction group nonce sorted tx from from selectedTxList wit', function () { const tx1 = { id: 0, @@ -236,7 +236,7 @@ describe('Transaction Selectors', () => { }) }) - describe('Sorting Transactions Selectors', () => { + describe('Sorting Transactions Selectors', function () { const submittedTx = { id: 0, @@ -296,7 +296,7 @@ describe('Transaction Selectors', () => { }, } - it('nonceSortedPendingTransactionsSelector', () => { + it('nonceSortedPendingTransactionsSelector', function () { const expectedResult = [ { @@ -328,7 +328,7 @@ describe('Transaction Selectors', () => { assert.deepEqual(nonceSortedPendingTransactionsSelector(state), expectedResult) }) - it('nonceSortedCompletedTransactionsSelector', () => { + it('nonceSortedCompletedTransactionsSelector', function () { const expectedResult = [ { @@ -344,7 +344,7 @@ describe('Transaction Selectors', () => { assert.deepEqual(nonceSortedCompletedTransactionsSelector(state), expectedResult) }) - it('submittedPendingTransactionsSelector', () => { + it('submittedPendingTransactionsSelector', function () { const expectedResult = [ submittedTx ] assert.deepEqual(submittedPendingTransactionsSelector(state), expectedResult) diff --git a/yarn.lock b/yarn.lock index 88a2e1388..6657b9e73 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1829,10 +1829,10 @@ scroll "^2.0.3" warning "^3.0.0" -"@metamask/eslint-config@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-1.0.0.tgz#046012398bb27f56395355c96ef07152925043b7" - integrity sha512-MmxM2sknVhIHyXCjR6LcK57OPJ30gTEX5v/jwC+qXuw4GIgUAPbxFp3AFmFRAJwty3RMjJSbRJ7YlamMq67U8w== +"@metamask/eslint-config@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-1.1.0.tgz#03c6fbec8ba3d95fa017d8b98ab5d0701f7458a4" + integrity sha512-yFFHIxFn3cBd9brIW/+0fJGq16hT0xUyElP0YxiZHaY7j2T/l+X/414L9kqBOuPfPa9bIKulIcJJOfcrMJZp9w== "@metamask/forwarder@^1.1.0": version "1.1.0" @@ -9878,12 +9878,12 @@ eslint-plugin-json@^1.2.0: dependencies: jshint "^2.8.0" -eslint-plugin-mocha@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-5.0.0.tgz#43946a7ecaf39039eb3ee20635ebd4cc19baf6dd" - integrity sha512-mpRWWsjxRco2bY4qE5DL8SmGoVF0Onb6DZrbgOjFoNo1YNN299K2voIozd8Kce3qC/neWNr2XF27E1ZDMl1yZg== +eslint-plugin-mocha@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-6.2.2.tgz#6ef4b78bd12d744beb08a06e8209de330985100d" + integrity sha512-oNhPzfkT6Q6CJ0HMVJ2KLxEWG97VWGTmuHOoRcDLE0U88ugUyFNV9wrT2XIt5cGtqc5W9k38m4xTN34L09KhBA== dependencies: - ramda "^0.25.0" + ramda "^0.26.1" eslint-plugin-no-unsafe-innerhtml@1.0.16: version "1.0.16" @@ -22830,10 +22830,10 @@ ramda@^0.24.1: resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.24.1.tgz#c3b7755197f35b8dc3502228262c4c91ddb6b857" integrity sha1-w7d1UZfzW43DUCIoJixMkd22uFc= -ramda@^0.25.0: - version "0.25.0" - resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.25.0.tgz#8fdf68231cffa90bc2f9460390a0cb74a29b29a9" - integrity sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ== +ramda@^0.26.1: + version "0.26.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06" + integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ== randexp@0.4.6: version "0.4.6" From 7f3cf07f94e4784757fe8ad6760e1e2ab3a464bf Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 11 Feb 2020 17:03:32 -0330 Subject: [PATCH 260/689] Update sinon and proxyquire (#8027) * Use sinon@8.1.1 * Use proxyquire@2.1.3 * Move sinon mocking out of global scope into hooks --- package.json | 4 +- .../tests/button-group-component.test.js | 30 ++-- .../tests/amount-max-button-component.test.js | 24 ++- .../send-dropdown-list-component.test.js | 21 ++- .../tests/send-footer-component.test.js | 35 ++-- .../tests/send-header-component.test.js | 25 +-- .../pages/send/tests/send-component.test.js | 58 ++++--- yarn.lock | 155 ++++++++---------- 8 files changed, 184 insertions(+), 168 deletions(-) diff --git a/package.json b/package.json index 27e9ed66e..5fd86913f 100644 --- a/package.json +++ b/package.json @@ -250,7 +250,7 @@ "node-sass": "^4.12.0", "nyc": "^15.0.0", "polyfill-crypto.getrandomvalues": "^1.0.0", - "proxyquire": "2.0.1", + "proxyquire": "^2.1.3", "qs": "^6.2.0", "qunitjs": "^2.4.1", "react-devtools": "^4.4.0", @@ -266,7 +266,7 @@ "serve-handler": "^6.1.2", "sesify": "^4.2.1", "sesify-viz": "^3.0.5", - "sinon": "^5.0.0", + "sinon": "^8.1.1", "source-map": "^0.7.2", "source-map-explorer": "^2.0.1", "string.prototype.matchall": "^4.0.2", diff --git a/ui/app/components/ui/button-group/tests/button-group-component.test.js b/ui/app/components/ui/button-group/tests/button-group-component.test.js index 52c0a5021..5e304bc7c 100644 --- a/ui/app/components/ui/button-group/tests/button-group-component.test.js +++ b/ui/app/components/ui/button-group/tests/button-group-component.test.js @@ -4,21 +4,23 @@ import { shallow } from 'enzyme' import sinon from 'sinon' import ButtonGroup from '../button-group.component.js' -const childButtonSpies = { - onClick: sinon.spy(), -} +describe('ButtonGroup Component', function () { + let wrapper -sinon.spy(ButtonGroup.prototype, 'handleButtonClick') -sinon.spy(ButtonGroup.prototype, 'renderButtons') + const childButtonSpies = { + onClick: sinon.spy(), + } -const mockButtons = [ - , - , - , -] + const mockButtons = [ + , + , + , + ] -describe('ButtonGroup Component', function () { - let wrapper + before(function () { + sinon.spy(ButtonGroup.prototype, 'handleButtonClick') + sinon.spy(ButtonGroup.prototype, 'renderButtons') + }) beforeEach(function () { wrapper = shallow(( @@ -39,6 +41,10 @@ describe('ButtonGroup Component', function () { ButtonGroup.prototype.renderButtons.resetHistory() }) + after(function () { + sinon.restore() + }) + describe('componentDidUpdate', function () { it('should set the activeButtonIndex to the updated newActiveButtonIndex', function () { assert.equal(wrapper.state('activeButtonIndex'), 1) diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js index 02b67621f..9ade59acf 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js @@ -4,19 +4,21 @@ import { shallow } from 'enzyme' import sinon from 'sinon' import AmountMaxButton from '../amount-max-button.component.js' -const propsMethodSpies = { - setAmountToMax: sinon.spy(), - setMaxModeTo: sinon.spy(), -} - -const MOCK_EVENT = { preventDefault: () => {} } - -sinon.spy(AmountMaxButton.prototype, 'setMaxAmount') - describe('AmountMaxButton Component', function () { let wrapper let instance + const propsMethodSpies = { + setAmountToMax: sinon.spy(), + setMaxModeTo: sinon.spy(), + } + + const MOCK_EVENT = { preventDefault: () => {} } + + before(function () { + sinon.spy(AmountMaxButton.prototype, 'setMaxAmount') + }) + beforeEach(function () { wrapper = shallow(( {} } - -sinon.spy(SendFooter.prototype, 'onCancel') -sinon.spy(SendFooter.prototype, 'onSubmit') - describe('SendFooter Component', function () { let wrapper + const propsMethodSpies = { + addToAddressBookIfNew: sinon.spy(), + clearSend: sinon.spy(), + sign: sinon.spy(), + update: sinon.spy(), + } + const historySpies = { + push: sinon.spy(), + } + const MOCK_EVENT = { preventDefault: () => {} } + + before(function () { + sinon.spy(SendFooter.prototype, 'onCancel') + sinon.spy(SendFooter.prototype, 'onSubmit') + }) + beforeEach(function () { wrapper = shallow(( obj.balance !== obj.prevBalance), -} - -const SendTransactionScreen = proxyquire('../send.component.js', { - './send.utils': utilsMethodStubs, -}).default - -sinon.spy(SendTransactionScreen.prototype, 'componentDidMount') -sinon.spy(SendTransactionScreen.prototype, 'updateGas') - describe('Send Component', function () { let wrapper + const mockBasicGasEstimates = { + blockTime: 'mockBlockTime', + } + + const propsMethodSpies = { + updateAndSetGasLimit: sinon.spy(), + updateSendErrors: sinon.spy(), + updateSendTokenBalance: sinon.spy(), + resetSendState: sinon.spy(), + fetchBasicGasEstimates: sinon.stub().returns(Promise.resolve(mockBasicGasEstimates)), + fetchGasEstimates: sinon.spy(), + updateToNicknameIfNecessary: sinon.spy(), + } + const utilsMethodStubs = { + getAmountErrorObject: sinon.stub().returns({ amount: 'mockAmountError' }), + getGasFeeErrorObject: sinon.stub().returns({ gasFee: 'mockGasFeeError' }), + doesAmountErrorRequireUpdate: sinon.stub().callsFake(obj => obj.balance !== obj.prevBalance), + } + + const SendTransactionScreen = proxyquire('../send.component.js', { + './send.utils': utilsMethodStubs, + }).default + + before(function () { + sinon.spy(SendTransactionScreen.prototype, 'componentDidMount') + sinon.spy(SendTransactionScreen.prototype, 'updateGas') + }) + beforeEach(function () { wrapper = shallow(( Date: Wed, 12 Feb 2020 08:17:13 -0800 Subject: [PATCH 261/689] fix faulty null checks --- app/scripts/controllers/permissions/permissionsLog.js | 3 ++- test/unit/app/controllers/transactions/tx-controller-test.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/scripts/controllers/permissions/permissionsLog.js b/app/scripts/controllers/permissions/permissionsLog.js index 7a9149a1c..2d3b86823 100644 --- a/app/scripts/controllers/permissions/permissionsLog.js +++ b/app/scripts/controllers/permissions/permissionsLog.js @@ -325,6 +325,7 @@ export default class PermissionsLogController { getRequestedMethods (request) { if ( !request.params || + !request.params[0] || typeof request.params[0] !== 'object' || Array.isArray(request.params[0]) ) { @@ -392,7 +393,7 @@ function getLastIndexOfObjectArray (array, key, value) { for (let i = array.length - 1; i >= 0; i--) { - if (typeof array[i] !== 'object') { + if (!array[i] || typeof array[i] !== 'object') { throw new Error(`Encountered non-Object element at index ${i}`) } diff --git a/test/unit/app/controllers/transactions/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js index 8aab61122..7bff1b94a 100644 --- a/test/unit/app/controllers/transactions/tx-controller-test.js +++ b/test/unit/app/controllers/transactions/tx-controller-test.js @@ -57,7 +57,7 @@ describe('Transaction Controller', function () { const exposedState = txController.getState() assert('unapprovedTxs' in exposedState, 'state should have the key unapprovedTxs') assert('selectedAddressTxList' in exposedState, 'state should have the key selectedAddressTxList') - assert(typeof exposedState.unapprovedTxs === 'object', 'should be an object') + assert(exposedState && typeof exposedState.unapprovedTxs === 'object', 'should be an object') assert(Array.isArray(exposedState.selectedAddressTxList), 'should be an array') }) }) From 85430746ad49b9c99fafd1131baee45e58a5d93b Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 12 Feb 2020 14:47:36 -0330 Subject: [PATCH 262/689] Update mocha version (#8028) * Use mocha@7.0.1 * Remove bad async test --- package.json | 2 +- test/unit/app/nodeify-test.js | 16 -- yarn.lock | 281 ++++++++++++++++++++++------------ 3 files changed, 184 insertions(+), 115 deletions(-) diff --git a/package.json b/package.json index 5fd86913f..528ecadda 100644 --- a/package.json +++ b/package.json @@ -244,7 +244,7 @@ "karma-qunit": "^1.2.1", "koa": "^2.7.0", "lockfile-lint": "^3.0.5", - "mocha": "^5.0.0", + "mocha": "^7.0.1", "nock": "^9.0.14", "node-fetch": "^2.6.0", "node-sass": "^4.12.0", diff --git a/test/unit/app/nodeify-test.js b/test/unit/app/nodeify-test.js index 04d56956e..a70446ef0 100644 --- a/test/unit/app/nodeify-test.js +++ b/test/unit/app/nodeify-test.js @@ -32,22 +32,6 @@ describe('nodeify', function () { } }) - it('no callback - should asyncly throw an error if underlying function does', function (done) { - const nodified = nodeify(async () => { - throw new Error('boom!') - }, obj) - process.prependOnceListener('uncaughtException', (err) => { - assert.ok(err, 'got expected error') - assert.ok(err.message.includes('boom!'), 'got expected error message') - done() - }) - try { - nodified('baz') - } catch (err) { - done(new Error('should not have thrown an error synchronously')) - } - }) - it('sync functions - returns value', function (done) { const nodified = nodeify(() => 42) try { diff --git a/yarn.lock b/yarn.lock index 75318d64b..b47212f58 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3406,6 +3406,11 @@ ansi-colors@1.1.0: dependencies: ansi-wrap "^0.1.0" +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + ansi-colors@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.0.1.tgz#e94c6c306005af8b482240241e2f3dea4b855ff3" @@ -3559,6 +3564,14 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + apollo-cache-control@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.1.1.tgz#173d14ceb3eb9e7cb53de7eb8b61bee6159d4171" @@ -5332,6 +5345,11 @@ binary-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" integrity sha1-RqoXUftqL5PuXmibsQh9SxTGwgU= +binary-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" + integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== + binary-querystring@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/binary-querystring/-/binary-querystring-0.1.2.tgz#84a6f9ac21fcf2752e305f60397d445bb84551e9" @@ -5640,7 +5658,7 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.1: +braces@^3.0.1, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -5698,10 +5716,10 @@ browser-resolve@^1.11.0, browser-resolve@^1.11.3, browser-resolve@^1.7.0: dependencies: resolve "1.1.7" -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.1.1" @@ -6566,6 +6584,21 @@ chokidar@1.6.1: optionalDependencies: fsevents "^1.0.0" +chokidar@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" + integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.2.0" + optionalDependencies: + fsevents "~2.1.1" + chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.0.4, chokidar@^2.1.1: version "2.1.6" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5" @@ -7043,7 +7076,7 @@ comma-separated-tokens@^1.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.7.tgz#419cd7fb3258b1ed838dc0953167a25e152f5b59" integrity sha512-Jrx3xsP4pPv4AwJUDWY9wOXGtwPXARej6Xd99h4TUGotmf8APuquKMpK+dnD3UgyxK7OEWaisjZz+3b5jtL6xQ== -commander@2, commander@2.11.0, commander@^2.6.0: +commander@2, commander@^2.6.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== @@ -8742,10 +8775,10 @@ diff-sequences@^24.9.0: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5" integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew== -diff@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" - integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== +diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== diff@^4.0.2: version "4.0.2" @@ -11954,6 +11987,13 @@ flat-cache@^2.0.1: rimraf "2.6.3" write "1.0.3" +flat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" + integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== + dependencies: + is-buffer "~2.0.3" + flatmap@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/flatmap/-/flatmap-0.0.3.tgz#1f18a4d938152d495965f9c958d923ab2dd669b4" @@ -12277,6 +12317,11 @@ fsevents@^1.0.0, fsevents@^1.2.7: nan "^2.12.1" node-pre-gyp "^0.12.0" +fsevents@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" + integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== + fsm-event@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fsm-event/-/fsm-event-2.1.0.tgz#d385716ed38f9c92feab2ba601e2aac6c0ba5a92" @@ -12678,10 +12723,10 @@ glob-parent@^3.0.1, glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954" - integrity sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg== +glob-parent@^5.0.0, glob-parent@~5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" + integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== dependencies: is-glob "^4.0.1" @@ -12723,10 +12768,10 @@ glob-watcher@^5.0.3: just-debounce "^1.0.0" object.defaults "^1.1.0" -glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.4, glob@^7.0.5, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1, glob@~7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -12735,7 +12780,7 @@ glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.4, glob@^7.0.5, glob@^7.1.0, glo once "^1.3.0" path-is-absolute "^1.0.0" -glob@7.1.4, glob@^7.1.3, glob@^7.1.4, glob@~7.1.4: +glob@7.1.4, glob@^7.0.0, glob@^7.0.3, glob@^7.0.4, glob@^7.0.5, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1, glob@~7.1.2, glob@~7.1.4: version "7.1.4" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== @@ -13124,10 +13169,10 @@ graphql@^0.13.0: dependencies: iterall "^1.2.1" -growl@1.10.3: - version "1.10.3" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" - integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== growly@^1.3.0: version "1.3.0" @@ -13629,12 +13674,7 @@ hdkey@^1.1.0: safe-buffer "^5.1.1" secp256k1 "^3.0.1" -he@1.1.1, he@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= - -he@1.2.x: +he@1.2.0, he@1.2.x, he@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -15074,6 +15114,13 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-boolean-object@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.0.tgz#98f8b28030684219a95f375cfbd88ce3405dff93" @@ -15089,7 +15136,7 @@ is-buffer@^2.0.0, is-buffer@^2.0.3: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== -is-buffer@^2.0.2: +is-buffer@^2.0.2, is-buffer@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== @@ -15286,7 +15333,7 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0, is-glob@^4.0.1: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== @@ -16379,7 +16426,7 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.2.5, js-yaml@^3.2.7, js-yaml@^3.5.1, js-yaml@^3.6.1, js-yaml@^3.9.0: +js-yaml@3.13.1, js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.2.5, js-yaml@^3.2.7, js-yaml@^3.5.1, js-yaml@^3.6.1, js-yaml@^3.9.0: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -18296,7 +18343,7 @@ log-driver@^1.2.5: resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056" integrity sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY= -log-symbols@^2.0.0, log-symbols@^2.2.0: +log-symbols@2.2.0, log-symbols@^2.0.0, log-symbols@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== @@ -19224,21 +19271,35 @@ mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0 dependencies: minimist "0.0.8" -mocha@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.0.0.tgz#cccac988b0bc5477119cba0e43de7af6d6ad8f4e" - integrity sha512-ukB2dF+u4aeJjc6IGtPNnJXfeby5d4ZqySlIBT0OEyva/DrMjVm5HkQxKnHDLKEfEQBsEnwTg9HHhtPHJdTd8w== +mocha@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.0.1.tgz#276186d35a4852f6249808c6dd4a1376cbf6c6ce" + integrity sha512-9eWmWTdHLXh72rGrdZjNbG3aa1/3NRPpul1z0D979QpEnFdCG0Q5tv834N+94QEN2cysfV72YocQ3fn87s70fg== dependencies: - browser-stdout "1.3.0" - commander "2.11.0" - debug "3.1.0" - diff "3.3.1" + ansi-colors "3.2.3" + browser-stdout "1.3.1" + chokidar "3.3.0" + debug "3.2.6" + diff "3.5.0" escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.3" - he "1.1.1" + find-up "3.0.0" + glob "7.1.3" + growl "1.10.5" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "2.2.0" + minimatch "3.0.4" mkdirp "0.5.1" - supports-color "4.4.0" + ms "2.1.1" + node-environment-flags "1.0.6" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.0" + yargs-parser "13.1.1" + yargs-unparser "1.6.0" mock-fs@^4.1.0: version "4.10.1" @@ -19726,6 +19787,14 @@ node-dir@^0.1.10: dependencies: minimatch "^3.0.2" +node-environment-flags@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" + integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + node-fetch@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" @@ -20026,7 +20095,7 @@ normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: dependencies: remove-trailing-separator "^1.0.1" -normalize-path@^3.0.0: +normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== @@ -20319,7 +20388,7 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.0.4, object.assign@^4.1.0: +object.assign@4.1.0, object.assign@^4.0.4, object.assign@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== @@ -21541,10 +21610,10 @@ phantomjs-prebuilt@^2.1.16, phantomjs-prebuilt@~2.1.7: request-progress "^2.0.1" which "^1.2.10" -picomatch@^2.0.5: - version "2.0.7" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" - integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA== +picomatch@^2.0.4, picomatch@^2.0.5: + version "2.2.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" + integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== pidtree@^0.3.0: version "0.3.0" @@ -23613,6 +23682,13 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" +readdirp@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" + integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== + dependencies: + picomatch "^2.0.4" + readline2@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" @@ -24377,12 +24453,12 @@ resolve@1.3.2: dependencies: path-parse "^1.0.5" -resolve@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86" - integrity sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q== +resolve@^1.1.4, resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.11.1, resolve@^1.12.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.8.1: + version "1.15.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" + integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== dependencies: - path-parse "^1.0.5" + path-parse "^1.0.6" resolve@~1.11.1: version "1.11.1" @@ -24391,12 +24467,12 @@ resolve@~1.11.1: dependencies: path-parse "^1.0.6" -resolve@^1.1.4, resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.8.1, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.11.1, resolve@^1.12.0: - version "1.15.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" - integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== +resolve@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86" + integrity sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q== dependencies: - path-parse "^1.0.6" + path-parse "^1.0.5" responselike@1.0.2, responselike@^1.0.2: version "1.0.2" @@ -26202,7 +26278,7 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -26479,7 +26555,7 @@ strip-json-comments@1.0.x: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" integrity sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E= -strip-json-comments@^2.0.0, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: +strip-json-comments@2.0.1, strip-json-comments@^2.0.0, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= @@ -26640,12 +26716,12 @@ superstruct@^0.6.0, superstruct@~0.6.0, superstruct@~0.6.1: clone-deep "^2.0.1" kind-of "^6.0.1" -supports-color@4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" - integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== +supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== dependencies: - has-flag "^2.0.0" + has-flag "^3.0.0" supports-color@^2.0.0: version "2.0.0" @@ -29124,7 +29200,7 @@ which@1, which@^1.2.1, which@^1.2.10, which@^1.2.12, which@^1.2.14, which@^1.3.0 dependencies: isexe "^2.0.0" -which@^1.2.9, which@^1.3.1: +which@1.3.1, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -29138,12 +29214,12 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" - integrity sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w== +wide-align@1.1.3, wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: - string-width "^1.0.2" + string-width "^1.0.2 || 2" widest-line@^2.0.0: version "2.0.1" @@ -29486,6 +29562,14 @@ yaml@^1.7.2: dependencies: "@babel/runtime" "^7.6.3" +yargs-parser@13.1.1, yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^10.0.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" @@ -29501,14 +29585,6 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@^16.1.0: version "16.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-16.1.0.tgz#73747d53ae187e7b8dbe333f95714c76ea00ecf1" @@ -29543,6 +29619,15 @@ yargs-promise@^1.1.0: resolved "https://registry.yarnpkg.com/yargs-promise/-/yargs-promise-1.1.0.tgz#97ebb5198df734bb3b11745133ae5b501b16ab1f" integrity sha1-l+u1GY33NLs7EXRRM65bUBsWqx8= +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + yargs@11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" @@ -29561,6 +29646,22 @@ yargs@11.1.0: y18n "^3.2.1" yargs-parser "^9.0.2" +yargs@13.3.0, yargs@^13.2.2, yargs@^13.2.4, yargs@^13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.1" + yargs@14.0.0, yargs@^14.0.0, yargs@~14.0.0: version "14.0.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.0.0.tgz#ba4cacc802b3c0b3e36a9e791723763d57a85066" @@ -29633,22 +29734,6 @@ yargs@^12.0.1: y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" -yargs@^13.2.2, yargs@^13.2.4, yargs@^13.3.0: - version "13.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.1" - yargs@^15.0.2: version "15.0.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.0.2.tgz#4248bf218ef050385c4f7e14ebdf425653d13bd3" From 9376c47dd1e54ac490b61689311394786cf32b8d Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Wed, 12 Feb 2020 10:39:47 -0800 Subject: [PATCH 263/689] update packages --- package.json | 6 +++--- yarn.lock | 43 ++++++++++++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 7e48f4147..6ab5a5d1f 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "eth-block-tracker": "^4.4.2", "eth-contract-metadata": "^1.12.1", "eth-ens-namehash": "^2.0.8", - "eth-json-rpc-errors": "^2.0.0", + "eth-json-rpc-errors": "^2.0.2", "eth-json-rpc-filters": "^4.1.1", "eth-json-rpc-infura": "^4.0.2", "eth-json-rpc-middleware": "^4.4.0", @@ -120,7 +120,7 @@ "lodash": "^4.17.15", "loglevel": "^1.4.1", "luxon": "^1.8.2", - "metamask-inpage-provider": "^4.0.4", + "metamask-inpage-provider": "^4.1.2", "metamask-logo": "^2.1.4", "multihashes": "^0.4.12", "nanoid": "^2.1.6", @@ -158,7 +158,7 @@ "redux": "^3.0.5", "redux-thunk": "^2.2.0", "reselect": "^3.0.1", - "rpc-cap": "^1.0.3", + "rpc-cap": "^1.0.5", "safe-event-emitter": "^1.0.1", "safe-json-stringify": "^1.2.0", "single-call-balance-checker-abi": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index 88a2e1388..82b3b7e18 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10226,6 +10226,13 @@ eth-json-rpc-errors@^2.0.0: dependencies: fast-safe-stringify "^2.0.6" +eth-json-rpc-errors@^2.0.1, eth-json-rpc-errors@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/eth-json-rpc-errors/-/eth-json-rpc-errors-2.0.2.tgz#c1965de0301fe941c058e928bebaba2e1285e3c4" + integrity sha512-uBCRM2w2ewusRHGxN8JhcuOb2RN3ueAOYH/0BhqdFmQkZx5lj5+fLKTz0mIVOzd4FG5/kUksCzCD7eTEim6gaA== + dependencies: + fast-safe-stringify "^2.0.6" + eth-json-rpc-filters@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/eth-json-rpc-filters/-/eth-json-rpc-filters-4.1.1.tgz#15277c66790236d85f798f4d7dc6bab99a798cd2" @@ -12354,7 +12361,7 @@ fuse.js@^3.4.6: resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.4.6.tgz#545c3411fed88bf2e27c457cab6e73e7af697a45" integrity sha512-H6aJY4UpLFwxj1+5nAvufom5b2BT2v45P1MkPvdGIK8fWjQx/7o6tTT1+ALV0yawQvbmvCF0ufl2et8eJ7v7Cg== -gaba@^1.6.0, gaba@^1.9.3: +gaba@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/gaba/-/gaba-1.9.3.tgz#4e0e106f3640930f1f06ffe72546903b4c51813e" integrity sha512-zC9CpaksncAT9SSc4QAxozUE+SKIWN+r9YwhjAJoSeh9joqPJsXlJOHg1/CrHABpvN68QdE00wAYSabYM02EqQ== @@ -16542,6 +16549,16 @@ json-rpc-engine@^5.1.3, json-rpc-engine@^5.1.5, json-rpc-engine@^5.1.6: promise-to-callback "^1.0.0" safe-event-emitter "^1.0.1" +json-rpc-engine@^5.1.8: + version "5.1.8" + resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-5.1.8.tgz#5ba0147ce571899bbaa7133ffbc05317c34a3c7f" + integrity sha512-vTBSDEPJV1fPAsbm2g5sEuPjsgLdiab2f1CTn2PyRr8nxggUpA996PDlNQDsM0gnrA99F8KIBLq2nIKrOFl1Mg== + dependencies: + async "^2.0.1" + eth-json-rpc-errors "^2.0.1" + promise-to-callback "^1.0.0" + safe-event-emitter "^1.0.1" + json-rpc-error@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" @@ -18868,12 +18885,12 @@ mersenne-twister@^1.0.1, mersenne-twister@^1.1.0: resolved "https://registry.yarnpkg.com/mersenne-twister/-/mersenne-twister-1.1.0.tgz#f916618ee43d7179efcf641bec4531eb9670978a" integrity sha1-+RZhjuQ9cXnvz2Qb7EUx65Zwl4o= -metamask-inpage-provider@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/metamask-inpage-provider/-/metamask-inpage-provider-4.0.4.tgz#697121873bf686a1fddc671832d9adbceda4c9ae" - integrity sha512-DCuqQ1NpAScesjvJac+8k4SbKzgcbmP78sAvo96i04qIszzH0LMg0dZLEViTz6/uqM7nU6JO3NIAcNF3iA2Lpw== +metamask-inpage-provider@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/metamask-inpage-provider/-/metamask-inpage-provider-4.1.2.tgz#8068004d51160dc5869c5aa881074284b8db03da" + integrity sha512-HLCW4DdvubLGntez5yB6kOqvptnpgUcUaRenEwzqN+hHQMnA2+1mNLp5IYks30kvX/fI2ACJgekFwIRDFWA9gQ== dependencies: - eth-json-rpc-errors "^2.0.0" + eth-json-rpc-errors "^2.0.2" fast-deep-equal "^2.0.1" json-rpc-engine "^5.1.5" json-rpc-middleware-stream "^2.1.1" @@ -24535,18 +24552,18 @@ rn-host-detect@^1.1.5: resolved "https://registry.yarnpkg.com/rn-host-detect/-/rn-host-detect-1.1.5.tgz#fbecb982b73932f34529e97932b9a63e58d8deb6" integrity sha512-ufk2dFT3QeP9HyZ/xTuMtW27KnFy815CYitJMqQm+pgG3ZAtHBsrU8nXizNKkqXGy3bQmhEoloVbrfbvMJMqkg== -rpc-cap@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/rpc-cap/-/rpc-cap-1.0.3.tgz#c58f99ee97a92441f4310f407c0f40fecdbf0e78" - integrity sha512-6lheD7UU4IY+OpILTL65E5NQWFPfG1Igd/CAGbnMJY+3szmQ9mUrf4/3bbcvNhu64Q/KYfCstVhxJREmTeFLOg== +rpc-cap@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/rpc-cap/-/rpc-cap-1.0.5.tgz#6f5ec41a7f0f85eb9aca8ccc7e618625109e6430" + integrity sha512-uZLjb609EbR+STeiLg27CVRWSKn/iKWeSkVYH5D1dj34ffpYcq6ByQBT7IN0AXozLUxmLulgpETB3gOS7fsH2w== dependencies: clone "^2.1.2" - eth-json-rpc-errors "^2.0.0" + eth-json-rpc-errors "^2.0.2" fast-deep-equal "^2.0.1" - gaba "^1.6.0" + gaba "^1.9.3" intersect-objects "^1.0.0" is-subset "^0.1.1" - json-rpc-engine "^5.1.3" + json-rpc-engine "^5.1.8" obs-store "^4.0.3" uuid "^3.3.2" From dcc7d295118ee1557850a41af118a3efa5df0287 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 13 Feb 2020 16:07:50 -0400 Subject: [PATCH 264/689] Refactor QR scanner to move all error handling within component (#7885) The QR scanner component error handling would sometimes redirect the user to the wrong page. It was also confusingly handled in two places; the action used to open the QR scanner, and the scanner component. The error handling has now been corrected, simplified, and integrated into the QR scanner component itself. The old way of handling an error within the component was to close the modal, then call the action to open it all over again. This action took a route parameter, which instructed the action on which route to open if the fullscreen UI needed to be opened (as the fullscreen UI is the only one where the browser will show the camera permission prompt). This redirection worked just fine for handling the initial opening of the QR scanner modal. But for any subsequent errors the same action was used with a _default route_, meaning the user could click "try again" and find themselves on a completely different screen. Instead, errors now trigger a state change instead of closing and re- opening the modal. The permission checks in the action have been integrated into the component as well. One functional change is that the scenario where you have an invalid QR code has been made an error. Previously this just showed the error message below the video preview, but left the user with no way to try again. There error page has a "Try again" button, so it seemed better suited as an error. Also the message literally started with "Error:". Another functional change is that _all_ errors during initialization will result in the error UI being shown. Previously there was one error case that would instead log to the console and leave the user stuck. --- .../modals/qr-scanner/qr-scanner.component.js | 261 +++++++++++------- .../modals/qr-scanner/qr-scanner.container.js | 15 +- ui/app/pages/send/send.container.js | 6 +- .../add-contact/add-contact.container.js | 5 +- ui/app/store/actions.js | 23 +- 5 files changed, 168 insertions(+), 142 deletions(-) diff --git a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js b/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js index 1537c0f52..0bd4ac79a 100644 --- a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js +++ b/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js @@ -1,99 +1,139 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' +import log from 'loglevel' import { BrowserQRCodeReader } from '@zxing/library' +import { getEnvironmentType } from '../../../../../../app/scripts/lib/util' +import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../../app/scripts/lib/enums' import Spinner from '../../../ui/spinner' import WebcamUtils from '../../../../../lib/webcam-utils' import PageContainerFooter from '../../../ui/page-container/page-container-footer/page-container-footer.component' +const READY_STATE = { + ACCESSING_CAMERA: 'ACCESSING_CAMERA', + NEED_TO_ALLOW_ACCESS: 'NEED_TO_ALLOW_ACCESS', + READY: 'READY', +} + export default class QrScanner extends Component { static propTypes = { hideModal: PropTypes.func.isRequired, - qrCodeDetected: PropTypes.func, - scanQrCode: PropTypes.func, - error: PropTypes.bool, - errorType: PropTypes.string, + qrCodeDetected: PropTypes.func.isRequired, } static contextTypes = { t: PropTypes.func, } - constructor (props, context) { + constructor (props) { super(props) - this.state = { - ready: false, - msg: context.t('accessingYourCamera'), - } + this.state = this.getInitialState() this.codeReader = null this.permissionChecker = null - this.needsToReinit = false + this.mounted = false // Clear pre-existing qr code data before scanning this.props.qrCodeDetected(null) } componentDidMount () { + this.mounted = true + this.checkEnvironment() + } + + componentDidUpdate (_, prevState) { + const { ready } = this.state + + if (prevState.ready !== ready) { + if (ready === READY_STATE.READY) { + this.initCamera() + } else if (ready === READY_STATE.NEED_TO_ALLOW_ACCESS) { + this.checkPermissions() + } + } + } + + getInitialState () { + return { + ready: READY_STATE.ACCESSING_CAMERA, + error: null, + } + } + + checkEnvironment = async () => { + try { + const { environmentReady } = await WebcamUtils.checkStatus() + if (!environmentReady && getEnvironmentType() !== ENVIRONMENT_TYPE_FULLSCREEN) { + const currentUrl = new URL(window.location.href) + const currentHash = currentUrl.hash + const currentRoute = currentHash + ? currentHash.substring(1) + : null + global.platform.openExtensionInBrowser(currentRoute) + } + } catch (error) { + if (this.mounted) { + this.setState({ error }) + } + } + // initial attempt is required to trigger permission prompt this.initCamera() } - async checkPermisisions () { - const { permissions } = await WebcamUtils.checkStatus() - if (permissions) { - clearTimeout(this.permissionChecker) - // Let the video stream load first... - setTimeout(_ => { - this.setState({ - ready: true, - msg: this.context.t('scanInstructions'), - }) - if (this.needsToReinit) { - this.initCamera() - this.needsToReinit = false + checkPermissions = async () => { + try { + const { permissions } = await WebcamUtils.checkStatus() + if (permissions) { + // Let the video stream load first... + await new Promise(resolve => setTimeout(resolve, 2000)) + if (!this.mounted) { + return } - }, 2000) - } else { - // Keep checking for permissions - this.permissionChecker = setTimeout(_ => { - this.checkPermisisions() - }, 1000) + this.setState({ ready: READY_STATE.READY }) + } else if (this.mounted) { + // Keep checking for permissions + this.permissionChecker = setTimeout(this.checkPermissions, 1000) + } + } catch (error) { + if (this.mounted) { + this.setState({ error }) + } } } componentWillUnmount () { + this.mounted = false clearTimeout(this.permissionChecker) if (this.codeReader) { this.codeReader.reset() } } - initCamera () { + initCamera = async () => { this.codeReader = new BrowserQRCodeReader() - this.codeReader.getVideoInputDevices() - .then(() => { - clearTimeout(this.permissionChecker) - this.checkPermisisions() - this.codeReader.decodeFromInputVideoDevice(undefined, 'video') - .then(content => { - const result = this.parseContent(content.text) - if (result.type !== 'unknown') { - this.props.qrCodeDetected(result) - this.stopAndClose() - } else { - this.setState({ msg: this.context.t('unknownQrCode') }) - } - }) - .catch(err => { - if (err && err.name === 'NotAllowedError') { - this.setState({ msg: this.context.t('youNeedToAllowCameraAccess') }) - clearTimeout(this.permissionChecker) - this.needsToReinit = true - this.checkPermisisions() - } - }) - }).catch(err => { - console.error('[QR-SCANNER]: getVideoInputDevices threw an exception: ', err) - }) + try { + await this.codeReader.getVideoInputDevices() + const content = await this.codeReader.decodeFromInputVideoDevice(undefined, 'video') + const result = this.parseContent(content.text) + if (!this.mounted) { + return + } else if (result.type !== 'unknown') { + this.props.qrCodeDetected(result) + this.stopAndClose() + } else { + this.setState({ error: new Error(this.context.t('unknownQrCode')) }) + } + } catch (error) { + if (!this.mounted) { + return + } + if (error.name === 'NotAllowedError') { + log.info(`Permission denied: '${error}'`) + this.setState({ ready: READY_STATE.NEED_TO_ALLOW_ACCESS }) + } else { + this.setState({ error }) + } + } } parseContent (content) { @@ -126,89 +166,108 @@ export default class QrScanner extends Component { if (this.codeReader) { this.codeReader.reset() } - this.setState({ ready: false }) this.props.hideModal() } tryAgain = () => { - // close the modal - this.stopAndClose() - // wait for the animation and try again - setTimeout(_ => { - this.props.scanQrCode() - }, 1000) + clearTimeout(this.permissionChecker) + if (this.codeReader) { + this.codeReader.reset() + } + this.setState(this.getInitialState(), () => { + this.checkEnvironment() + }) } - renderVideo () { - return ( -
    -
    - ) - } + renderError () { + const { t } = this.context + const { error } = this.state - renderErrorModal () { let title, msg - - if (this.props.error) { - if (this.props.errorType === 'NO_WEBCAM_FOUND') { - title = this.context.t('noWebcamFoundTitle') - msg = this.context.t('noWebcamFound') - } else { - title = this.context.t('unknownCameraErrorTitle') - msg = this.context.t('unknownCameraError') - } + if (error.type === 'NO_WEBCAM_FOUND') { + title = t('noWebcamFoundTitle') + msg = t('noWebcamFound') + } else if (error.message === t('unknownQrCode')) { + msg = t('unknownQrCode') + } else { + title = t('unknownCameraErrorTitle') + msg = t('unknownCameraError') } return ( -
    -
    - + <>
    -
    - { title } -
    + { + title + ? ( +
    + { title } +
    + ) + : null + }
    {msg}
    -
    + ) } - render () { + renderVideo () { const { t } = this.context + const { ready } = this.state - if (this.props.error) { - return this.renderErrorModal() + let message + if (ready === READY_STATE.ACCESSING_CAMERA) { + message = t('accessingYourCamera') + } else if (ready === READY_STATE.READY) { + message = t('scanInstructions') + } else if (ready === READY_STATE.NEED_TO_ALLOW_ACCESS) { + message = t('youNeedToAllowCameraAccess') } return ( -
    -
    + <>
    { `${t('scanQrCode')}` }
    - { this.renderVideo() } +
    +
    - {this.state.msg} + {message}
    + + ) + } + + render () { + const { error } = this.state + return ( +
    +
    + { + error + ? this.renderError() + : this.renderVideo() + }
    ) } diff --git a/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js b/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js index d553d1b76..2de4aeb73 100644 --- a/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js +++ b/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js @@ -1,24 +1,13 @@ import { connect } from 'react-redux' import QrScanner from './qr-scanner.component' -import { hideModal, qrCodeDetected, showQrScanner } from '../../../../store/actions' -import { - SEND_ROUTE, -} from '../../../../helpers/constants/routes' - -const mapStateToProps = state => { - return { - error: state.appState.modal.modalState.props.error, - errorType: state.appState.modal.modalState.props.errorType, - } -} +import { hideModal, qrCodeDetected } from '../../../../store/actions' const mapDispatchToProps = dispatch => { return { hideModal: () => dispatch(hideModal()), qrCodeDetected: (data) => dispatch(qrCodeDetected(data)), - scanQrCode: () => dispatch(showQrScanner(SEND_ROUTE)), } } -export default connect(mapStateToProps, mapDispatchToProps)(QrScanner) +export default connect(null, mapDispatchToProps)(QrScanner) diff --git a/ui/app/pages/send/send.container.js b/ui/app/pages/send/send.container.js index 7d0aabe66..da2b66f2f 100644 --- a/ui/app/pages/send/send.container.js +++ b/ui/app/pages/send/send.container.js @@ -53,10 +53,6 @@ import { isValidENSAddress, } from '../../helpers/utils/util' -import { - SEND_ROUTE, -} from '../../helpers/constants/routes' - function mapStateToProps (state) { return { addressBook: getAddressBook(state), @@ -111,7 +107,7 @@ function mapDispatchToProps (dispatch) { }, updateSendErrors: newError => dispatch(updateSendErrors(newError)), resetSendState: () => dispatch(resetSendState()), - scanQrCode: () => dispatch(showQrScanner(SEND_ROUTE)), + scanQrCode: () => dispatch(showQrScanner()), qrCodeDetected: (data) => dispatch(qrCodeDetected(data)), updateSendTo: (to, nickname) => dispatch(updateSendTo(to, nickname)), fetchBasicGasEstimates: () => dispatch(fetchBasicGasEstimates()), diff --git a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js index 10e2ab653..d6757f76f 100644 --- a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js +++ b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js @@ -3,9 +3,6 @@ import { compose } from 'recompose' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' import { addToAddressBook, showQrScanner, qrCodeDetected } from '../../../../store/actions' -import { - CONTACT_ADD_ROUTE, -} from '../../../../helpers/constants/routes' import { getQrCodeData, } from '../../../send/send.selectors' @@ -19,7 +16,7 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => { return { addToAddressBook: (recipient, nickname) => dispatch(addToAddressBook(recipient, nickname)), - scanQrCode: () => dispatch(showQrScanner(CONTACT_ADD_ROUTE)), + scanQrCode: () => dispatch(showQrScanner()), qrCodeDetected: (data) => dispatch(qrCodeDetected(data)), } } diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 5dad5deb8..855944f5d 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -12,7 +12,6 @@ import log from 'loglevel' import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../app/scripts/lib/enums' import { hasUnconfirmedTransactions } from '../helpers/utils/confirm-tx.util' import { setCustomGasLimit } from '../ducks/gas/gas.duck' -import WebcamUtils from '../../lib/webcam-utils' import txHelper from '../../lib/tx-helper' export const actionConstants = { @@ -550,25 +549,11 @@ export function unlockHardwareWalletAccount (index, deviceName, hdPath) { } } -export function showQrScanner (ROUTE) { +export function showQrScanner () { return (dispatch) => { - return WebcamUtils.checkStatus() - .then(status => { - if (!status.environmentReady) { - // We need to switch to fullscreen mode to ask for permission - global.platform.openExtensionInBrowser(`${ROUTE}`, `scan=true`) - } else { - dispatch(showModal({ - name: 'QR_SCANNER', - })) - } - }).catch(e => { - dispatch(showModal({ - name: 'QR_SCANNER', - error: true, - errorType: e.type, - })) - }) + dispatch(showModal({ + name: 'QR_SCANNER', + })) } } From b63b848ed4a112ebfe66c1565d8410edcb772a28 Mon Sep 17 00:00:00 2001 From: Vodopyanov Egor Date: Fri, 14 Feb 2020 19:31:44 +0300 Subject: [PATCH 265/689] add title to transaction action component (#8050) --- .../tests/transaction-action.component.test.js | 3 +++ .../app/transaction-action/transaction-action.component.js | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js b/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js index 2168fe1f7..2f99ca0cb 100644 --- a/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js +++ b/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js @@ -46,6 +46,7 @@ describe('TransactionAction Component', function () { assert.equal(wrapper.find('.transaction-action').length, 1) wrapper.setState({ transactionAction: 'sentEther' }) assert.equal(wrapper.text(), 'sentEther') + assert.equal(wrapper.find('.transaction-action').props().title.trim(), 'sentEther') }) it('should render Approved', async function () { @@ -81,6 +82,7 @@ describe('TransactionAction Component', function () { assert.ok(wrapper) assert.equal(wrapper.find('.transaction-action').length, 1) assert.equal(wrapper.find('.transaction-action').text().trim(), 'Approve') + assert.equal(wrapper.find('.transaction-action').props().title.trim(), 'Approve') }) it('should render contractInteraction', async function () { @@ -114,6 +116,7 @@ describe('TransactionAction Component', function () { assert.ok(wrapper) assert.equal(wrapper.find('.transaction-action').length, 1) assert.equal(wrapper.find('.transaction-action').text().trim(), 'contractInteraction') + assert.equal(wrapper.find('.transaction-action').props().title.trim(), 'contractInteraction') }) }) }) diff --git a/ui/app/components/app/transaction-action/transaction-action.component.js b/ui/app/components/app/transaction-action/transaction-action.component.js index 26012ff7f..e1617fcbc 100644 --- a/ui/app/components/app/transaction-action/transaction-action.component.js +++ b/ui/app/components/app/transaction-action/transaction-action.component.js @@ -29,9 +29,11 @@ export default class TransactionAction extends PureComponent { render () { const { className } = this.props + const action = this.getTransactionAction() + return ( -
    - { this.getTransactionAction() } +
    + { action }
    ) } From cfcccd266a14f0bc0a800ce84a43548c332751d3 Mon Sep 17 00:00:00 2001 From: Dan Finlay <542863+danfinlay@users.noreply.github.com> Date: Fri, 14 Feb 2020 11:27:12 -0800 Subject: [PATCH 266/689] Inline the source text not the binary encoding for inpage script (#8053) --- app/scripts/contentscript.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 8b2040b16..8cb4ab5c7 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -9,7 +9,7 @@ import PortStream from 'extension-port-stream' const fs = require('fs') const path = require('path') -const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'inpage.js')).toString() +const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'inpage.js'), 'utf8') const inpageSuffix = '//# sourceURL=' + extension.runtime.getURL('inpage.js') + '\n' const inpageBundle = inpageContent + inpageSuffix From eb577630562a89a05953d4f0b8949e795a419252 Mon Sep 17 00:00:00 2001 From: Dan Finlay <542863+danfinlay@users.noreply.github.com> Date: Fri, 14 Feb 2020 12:32:56 -0800 Subject: [PATCH 267/689] Add warning to watchAsset API when editing a known token (#8049) * Add warning when editing a known token with watchAsset API * Add warning when watchAsset attempts to reuse token symbol * Linted --- app/_locales/en/messages.json | 6 +++ .../confirm-add-suggested-token.component.js | 47 ++++++++++++++++++- .../confirm-add-suggested-token.container.js | 3 +- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index d6b0e2bcc..7e23fdb93 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -743,6 +743,12 @@ "knownAddressRecipient": { "message": "Known contract address." }, + "knownTokenWarning": { + "message": "This action will edit tokens that are already listed in your wallet, which can be used to phish you. Only approve if you are certain that you mean to change what these tokens represent." + }, + "reusedTokenNameWarning": { + "message": "A token here reuses a symbol from another token you watch, this can be confusing or deceptive." + }, "invalidAddressRecipientNotEthNetwork": { "message": "Not ETH network, set to lowercase" }, diff --git a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js index c727f4605..e96688220 100644 --- a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js +++ b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js @@ -15,6 +15,7 @@ export default class ConfirmAddSuggestedToken extends Component { addToken: PropTypes.func, pendingTokens: PropTypes.object, removeSuggestedTokens: PropTypes.func, + tokens: PropTypes.array, } componentDidMount () { @@ -32,9 +33,11 @@ export default class ConfirmAddSuggestedToken extends Component { } render () { - const { addToken, pendingTokens, removeSuggestedTokens, history } = this.props + const { addToken, pendingTokens, tokens, removeSuggestedTokens, history } = this.props const pendingTokenKey = Object.keys(pendingTokens)[0] const pendingToken = pendingTokens[pendingTokenKey] + const hasTokenDuplicates = this.checkTokenDuplicates(pendingTokens, tokens) + const reusesName = this.checkNameReuse(pendingTokens, tokens) return (
    @@ -45,6 +48,20 @@ export default class ConfirmAddSuggestedToken extends Component {
    { this.context.t('likeToAddTokens') }
    + { hasTokenDuplicates ? + ( +
    + { this.context.t('knownTokenWarning') } +
    + ) : null + } + { reusesName ? + ( +
    + { this.context.t('reusedTokenNameWarning') } +
    + ) : null + }
    @@ -118,4 +135,32 @@ export default class ConfirmAddSuggestedToken extends Component {
    ) } + + checkTokenDuplicates (pendingTokens, tokens) { + const pending = Object.keys(pendingTokens) + const existing = tokens.map(token => token.address) + const dupes = pending.filter((proposed) => { + return existing.includes(proposed) + }) + + return dupes.length > 0 + } + + /** + * Returns true if any pendingTokens both: + * - Share a symbol with an existing `tokens` member. + * - Does not share an address with that same `tokens` member. + * This should be flagged as possibly deceptive or confusing. + */ + checkNameReuse (pendingTokens, tokens) { + const duplicates = Object.keys(pendingTokens) + .map((addr) => pendingTokens[addr]) + .filter((token) => { + const dupes = tokens.filter(old => old.symbol === token.symbol) + .filter(old => old.address !== token.address) + return dupes.length > 0 + }) + return duplicates.length > 0 + } + } diff --git a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js index c3b576f25..9abf5edd3 100644 --- a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js +++ b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js @@ -5,11 +5,12 @@ import { withRouter } from 'react-router-dom' import { addToken, removeSuggestedTokens } from '../../store/actions' const mapStateToProps = ({ metamask }) => { - const { pendingTokens, suggestedTokens } = metamask + const { pendingTokens, suggestedTokens, tokens } = metamask const params = { ...pendingTokens, ...suggestedTokens } return { pendingTokens: params, + tokens, } } From 62c5ea4f804e1c93812004980859a8c2d113481c Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 14 Feb 2020 18:07:24 -0400 Subject: [PATCH 268/689] Update Wyre ETH purchase url (#8051) * Revert "Revert "Update Wyre ETH purchase url" (#7631)" This reverts commit bc67d1eecabb123bf21445e604780d2454d52d3e. * Restrict widget to just debit card payments Apple Pay apparently only works on Safari. --- app/scripts/lib/buy-eth-url.js | 2 +- test/unit/app/buy-eth-url.spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/scripts/lib/buy-eth-url.js b/app/scripts/lib/buy-eth-url.js index 2a924ecff..b83e83e2e 100644 --- a/app/scripts/lib/buy-eth-url.js +++ b/app/scripts/lib/buy-eth-url.js @@ -19,7 +19,7 @@ function getBuyEthUrl ({ network, amount, address, service }) { switch (service) { case 'wyre': - return `https://dash.sendwyre.com/sign-up` + return `https://pay.sendwyre.com/?dest=ethereum:${address}&destCurrency=ETH&accountId=AC-7AG3W4XH4N2&paymentMethod=debit-card` case 'coinswitch': return `https://metamask.coinswitch.co/?address=${address}&to=eth` case 'coinbase': diff --git a/test/unit/app/buy-eth-url.spec.js b/test/unit/app/buy-eth-url.spec.js index 15096d4c7..ab1b22c5f 100644 --- a/test/unit/app/buy-eth-url.spec.js +++ b/test/unit/app/buy-eth-url.spec.js @@ -20,7 +20,7 @@ describe('buy-eth-url', function () { it('returns wyre url with address for network 1', function () { const wyreUrl = getBuyEthUrl(mainnet) - assert.equal(wyreUrl, 'https://dash.sendwyre.com/sign-up') + assert.equal(wyreUrl, 'https://pay.sendwyre.com/?dest=ethereum:0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc&destCurrency=ETH&accountId=AC-7AG3W4XH4N2&paymentMethod=debit-card') }) From a78cf0ef3a463c5d9d56453e2f777e08cc2dcce7 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Sat, 15 Feb 2020 17:04:12 -0330 Subject: [PATCH 269/689] Enable arrow-parens ESLint rule --- .eslintrc.js | 1 + app/scripts/background.js | 6 +- app/scripts/contentscript.js | 2 +- app/scripts/controllers/app-state.js | 2 +- app/scripts/controllers/cached-balances.js | 2 +- .../controllers/incoming-transactions.js | 4 +- .../network/createLocalhostClient.js | 2 +- app/scripts/controllers/network/util.js | 2 +- app/scripts/controllers/permissions/index.js | 10 +- .../controllers/permissions/permissionsLog.js | 4 +- app/scripts/controllers/preferences.js | 6 +- app/scripts/controllers/token-rates.js | 4 +- app/scripts/controllers/transactions/index.js | 2 +- .../controllers/transactions/lib/util.js | 10 +- .../transactions/tx-state-manager.js | 2 +- app/scripts/lib/account-tracker.js | 6 +- app/scripts/lib/createDnodeRemoteGetter.js | 2 +- app/scripts/lib/ens-ipfs/setup.js | 2 +- .../lib/get-first-preferred-lang-code.js | 6 +- app/scripts/lib/message-manager.js | 4 +- app/scripts/lib/personal-message-manager.js | 4 +- app/scripts/lib/setupSentry.js | 8 +- app/scripts/lib/typed-message-manager.js | 4 +- app/scripts/lib/util.js | 4 +- app/scripts/metamask-controller.js | 26 +++--- app/scripts/migrations/025.js | 12 +-- app/scripts/platforms/extension.js | 2 +- development/metamaskbot-build-announce.js | 8 +- development/mock-3box.js | 4 +- development/show-deps-install-scripts.js | 2 +- development/sourcemap-validator.js | 2 +- development/verify-locale-strings.js | 12 +-- gulpfile.js | 34 +++---- test/e2e/address-book.spec.js | 2 +- test/e2e/benchmark.js | 20 ++-- test/e2e/ethereum-on.spec.js | 4 +- test/e2e/from-import-ui.spec.js | 2 +- test/e2e/incremental-security.spec.js | 2 +- test/e2e/metamask-responsive-ui.spec.js | 2 +- test/e2e/metamask-ui.spec.js | 6 +- test/e2e/mock-3box/server.js | 2 +- test/e2e/permissions.spec.js | 4 +- test/e2e/send-edit.spec.js | 2 +- test/e2e/signature-request.spec.js | 4 +- test/e2e/threebox.spec.js | 2 +- test/e2e/web3.spec.js | 4 +- test/e2e/webdriver/driver.js | 8 +- test/lib/render-helpers.js | 4 +- test/setup.js | 2 +- .../controllers/metamask-controller-test.js | 2 +- .../transactions/pending-tx-test.js | 2 +- .../transactions/tx-controller-test.js | 2 +- test/unit/app/fetch-with-timeout.test.js | 4 +- test/unit/migrations/031-test.js | 4 +- test/unit/migrations/033-test.js | 2 +- test/unit/migrations/migrator-test.js | 2 +- test/unit/ui/app/actions.spec.js | 14 +-- test/web3/web3.js | 4 +- .../account-menu/account-menu.component.js | 12 +-- .../account-menu/account-menu.container.js | 4 +- .../app/app-header/app-header.component.js | 2 +- .../app/app-header/app-header.container.js | 4 +- .../app/app-header/tests/app-header.test.js | 2 +- .../confirm-detail-row.component.js | 2 +- ...onfirm-page-container-summary.component.js | 2 +- ...onfirm-page-container-warning.component.js | 2 +- ...irm-page-container-navigation.component.js | 2 +- .../connected-sites-list.container.js | 4 +- .../app/dropdowns/network-dropdown.js | 4 +- .../app/dropdowns/simple-dropdown.js | 4 +- .../advanced-gas-inputs.container.js | 2 +- .../advanced-gas-input-component.test.js | 2 +- .../tests/basic-tab-content-component.test.js | 2 +- .../gas-modal-page-container.component.js | 4 +- .../gas-modal-page-container.container.js | 6 +- .../gas-price-chart/gas-price-chart.utils.js | 2 +- .../gas-slider/gas-slider.component.js | 2 +- .../loading-network-screen.container.js | 4 +- .../app/menu-bar/menu-bar.container.js | 4 +- .../account-details-modal.component.js | 2 +- .../add-to-addressbook-modal.component.js | 4 +- .../cancel-transaction.container.js | 2 +- .../cancel-transaction.component.test.js | 2 +- .../confirm-delete-network.container.js | 2 +- .../tests/confirm-delete-network.test.js | 2 +- .../confirm-remove-account.container.js | 4 +- .../tests/confirm-remove-account.test.js | 2 +- .../confirm-reset-account.container.js | 2 +- .../tests/confirm-reset-account.test.js | 2 +- .../deposit-ether-modal.component.js | 2 +- .../deposit-ether-modal.container.js | 2 +- .../disconnect-account.container.js | 6 +- .../disconnect-all.container.js | 2 +- .../export-private-key-modal.component.js | 4 +- ui/app/components/app/modals/fade-modal.js | 6 +- .../modals/hide-token-confirmation-modal.js | 2 +- .../metametrics-opt-in-modal.container.js | 2 +- .../new-account-modal.component.js | 4 +- .../new-account-modal.container.js | 6 +- .../app/modals/notification-modal.js | 2 +- .../modals/qr-scanner/qr-scanner.component.js | 2 +- .../modals/qr-scanner/qr-scanner.container.js | 2 +- .../tests/reject-transactions.test.js | 2 +- .../tests/account-details-modal.test.js | 2 +- .../tests/transaction-confirmed.test.js | 2 +- .../multiple-notifications.component.js | 2 +- .../permission-page-container.component.js | 4 +- .../selected-account.container.js | 2 +- .../signature-request-original.component.js | 4 +- ui/app/components/app/tab-bar.js | 2 +- .../app/token-cell/token-cell.container.js | 2 +- .../transaction-action.component.test.js | 4 +- ...transaction-activity-log.container.test.js | 2 +- .../transaction-activity-log.component.js | 2 +- .../transaction-activity-log.container.js | 4 +- .../transaction-activity-log.util.js | 4 +- ...transaction-list-item-details.component.js | 4 +- .../transaction-list-item.component.js | 6 +- .../transaction-list-item.container.js | 10 +- .../transaction-list.container.js | 4 +- .../transaction-status.component.test.js | 4 +- .../transaction-view-balance.container.js | 4 +- ...eferenced-currency-input.container.test.js | 2 +- ...er-preferenced-currency-input.container.js | 2 +- ...-preferenced-token-input.container.test.js | 2 +- .../user-preferenced-token-input.container.js | 2 +- ui/app/components/ui/alert/index.js | 2 +- .../ui/balance/balance.container.js | 2 +- .../tests/button-group-component.test.js | 2 +- .../currency-display.container.js | 2 +- .../currency-input.component.js | 2 +- .../currency-input.container.js | 2 +- .../tests/currency-input.component.test.js | 2 +- ui/app/components/ui/editable-label.js | 2 +- .../tests/error-message.component.test.js | 2 +- .../ui/identicon/identicon.component.js | 2 +- .../ui/identicon/identicon.container.js | 2 +- .../page-container-footer.component.js | 4 +- .../page-container.component.js | 4 +- ui/app/components/ui/readonly-input.js | 2 +- .../components/ui/tabs/tab/tab.component.js | 4 +- ui/app/components/ui/tabs/tabs.component.js | 2 +- .../toggle-button/toggle-button.component.js | 2 +- .../token-balance/token-balance.container.js | 2 +- .../tests/token-input.component.test.js | 2 +- .../ui/token-input/token-input.component.js | 2 +- .../ui/token-input/token-input.container.js | 2 +- .../ui/unit-input/unit-input.component.js | 4 +- .../confirm-transaction.duck.js | 2 +- .../confirm-transaction.duck.test.js | 2 +- ui/app/ducks/gas/gas-duck.test.js | 6 +- ui/app/ducks/gas/gas.duck.js | 14 +-- ui/app/ducks/metamask/metamask.js | 2 +- .../authenticated/authenticated.container.js | 2 +- .../higher-order-components/i18n-provider.js | 2 +- .../initialized/initialized.container.js | 2 +- .../metametrics/metametrics.provider.js | 2 +- .../with-modal-props/with-modal-props.js | 4 +- .../with-token-tracker.component.js | 4 +- ui/app/helpers/utils/common.util.js | 2 +- ui/app/helpers/utils/confirm-tx.util.js | 2 +- ui/app/helpers/utils/conversion-util.js | 26 +++--- ui/app/helpers/utils/switch-direction.js | 4 +- ui/app/helpers/utils/token-util.js | 4 +- ui/app/pages/add-token/add-token.component.js | 10 +- ui/app/pages/add-token/add-token.container.js | 4 +- .../token-search/token-search.component.js | 6 +- ui/app/pages/add-token/util.js | 2 +- .../confirm-add-suggested-token.container.js | 2 +- .../confirm-add-token.container.js | 4 +- .../confirm-deploy-contract.container.js | 2 +- .../confirm-send-ether.component.js | 2 +- .../confirm-send-ether.container.js | 6 +- .../confirm-send-token.component.js | 2 +- .../confirm-send-token.container.js | 4 +- .../confirm-transaction-base.component.js | 6 +- .../confirm-transaction-base.container.js | 14 +-- .../confirm-transaction.container.js | 4 +- .../connect-hardware/connect-screen.js | 6 +- .../create-account/connect-hardware/index.js | 26 +++--- .../create-account.component.js | 2 +- .../create-account/import-account/json.js | 10 +- .../import-account/private-key.js | 4 +- .../create-account/new-account.component.js | 4 +- .../create-account/new-account.container.js | 10 +- .../create-password.component.js | 4 +- .../create-password.container.js | 2 +- .../import-with-seed-phrase.component.js | 14 +-- .../import-with-seed-phrase.container.js | 2 +- .../import-with-seed-phrase.component.test.js | 2 +- .../new-account/new-account.component.js | 12 +-- .../end-of-flow/end-of-flow.container.js | 2 +- .../first-time-flow.component.js | 12 +-- .../first-time-flow.container.js | 6 +- .../metametrics-opt-in.container.js | 2 +- .../confirm-seed-phrase.component.js | 14 +-- .../confirm-seed-phrase.container.js | 4 +- .../reveal-seed-phrase.container.js | 2 +- .../tests/reveal-seed-phrase.test.js | 2 +- .../seed-phrase/seed-phrase.component.js | 8 +- .../confirm-seed-phrase-component.test.js | 8 +- .../select-action/select-action.container.js | 4 +- .../welcome/welcome.container.js | 2 +- ui/app/pages/home/home.container.js | 4 +- ui/app/pages/keychains/restore-vault.js | 10 +- ui/app/pages/keychains/reveal-seed.js | 14 +-- .../pages/keychains/tests/reveal-seed.test.js | 2 +- ui/app/pages/lock/lock.container.js | 4 +- .../mobile-sync/mobile-sync.component.js | 10 +- .../mobile-sync/mobile-sync.container.js | 4 +- .../permissions-connect.component.js | 6 +- .../permissions-connect.container.js | 8 +- ui/app/pages/routes/index.js | 4 +- .../tests/account-list-item-component.test.js | 2 +- .../add-recipient/ens-input.component.js | 8 +- .../add-recipient/ens-input.container.js | 2 +- .../tests/add-recipient-component.test.js | 2 +- .../tests/add-recipient-utils.test.js | 2 +- .../amount-max-button.container.js | 4 +- .../tests/amount-max-button-component.test.js | 2 +- .../send-amount-row.component.js | 2 +- .../send-amount-row.container.js | 4 +- .../tests/send-amount-row-component.test.js | 2 +- .../send-asset-row.component.js | 4 +- .../send-asset-row.container.js | 2 +- .../send-dropdown-list-component.test.js | 2 +- .../tests/send-from-row-component.test.js | 2 +- .../tests/send-from-row-container.test.js | 2 +- .../tests/gas-fee-display.component.test.js | 2 +- .../send-gas-row/send-gas-row.component.js | 4 +- .../send-gas-row/send-gas-row.container.js | 2 +- .../tests/send-gas-row-component.test.js | 2 +- .../send-row-error-message-component.test.js | 2 +- .../tests/send-content-component.test.js | 2 +- .../send/send-footer/send-footer.component.js | 4 +- .../send/send-footer/send-footer.selectors.js | 2 +- .../send/send-footer/send-footer.utils.js | 2 +- .../tests/send-footer-component.test.js | 4 +- ui/app/pages/send/send.component.js | 8 +- ui/app/pages/send/send.container.js | 2 +- ui/app/pages/send/send.utils.js | 4 +- .../pages/send/tests/send-component.test.js | 2 +- .../pages/send/tests/send-selectors.test.js | 2 +- .../advanced-tab/advanced-tab.component.js | 18 ++-- .../advanced-tab/advanced-tab.container.js | 20 ++-- .../tests/advanced-tab-component.test.js | 4 +- .../add-contact/add-contact.component.js | 12 +-- .../add-contact/add-contact.container.js | 4 +- .../edit-contact/edit-contact.component.js | 6 +- .../edit-contact/edit-contact.container.js | 2 +- .../network-form/network-form.component.js | 4 +- .../networks-tab/networks-tab.component.js | 8 +- .../networks-tab/networks-tab.container.js | 18 ++-- .../security-tab/security-tab.component.js | 6 +- .../security-tab/security-tab.container.js | 6 +- .../security-tab/tests/security-tab.test.js | 2 +- .../settings-tab/settings-tab.component.js | 10 +- .../settings-tab/settings-tab.container.js | 12 +-- .../settings-tab/tests/settings-tab.test.js | 2 +- ui/app/pages/settings/settings.component.js | 4 +- .../unlock-page/tests/unlock-page.test.js | 2 +- .../unlock-page/unlock-page.component.js | 4 +- .../unlock-page/unlock-page.container.js | 8 +- ui/app/selectors/confirm-transaction.js | 52 +++++------ ui/app/selectors/custom-gas.js | 8 +- ui/app/selectors/custom-gas.test.js | 4 +- ui/app/selectors/permissions.js | 4 +- ui/app/selectors/selectors.js | 34 +++---- ui/app/selectors/tokens.js | 4 +- ui/app/selectors/transactions.js | 22 ++--- ui/app/store/actions.js | 92 +++++++++---------- ui/lib/tx-helper.js | 2 +- ui/lib/webcam-utils.js | 4 +- 273 files changed, 709 insertions(+), 708 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index d40917334..6741ed60b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -44,6 +44,7 @@ module.exports = { }, rules: { + 'arrow-parens': 'error', 'import/default': 'error', 'import/export': 'error', 'import/named': 'error', diff --git a/app/scripts/background.js b/app/scripts/background.js index 774d04691..ed2070d9b 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -389,7 +389,7 @@ function setupController (initState, initLangCode) { const url = new URL(remotePort.sender.url) const origin = url.hostname - remotePort.onMessage.addListener(msg => { + remotePort.onMessage.addListener((msg) => { if (msg.data && msg.data.method === 'eth_requestAccounts') { requestAccountTabIds[origin] = tabId } @@ -446,8 +446,8 @@ function setupController (initState, initLangCode) { * Opens the browser popup for user confirmation */ function triggerUi () { - extension.tabs.query({ active: true }, tabs => { - const currentlyActiveMetamaskTab = Boolean(tabs.find(tab => openMetamaskTabsIDs[tab.id])) + extension.tabs.query({ active: true }, (tabs) => { + const currentlyActiveMetamaskTab = Boolean(tabs.find((tab) => openMetamaskTabsIDs[tab.id])) if (!popupIsOpen && !currentlyActiveMetamaskTab && !notificationIsOpen) { notificationManager.showPopup() notificationIsOpen = true diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 8b2040b16..5122a54cc 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -231,5 +231,5 @@ async function domIsReady () { return } // wait for load - return new Promise(resolve => window.addEventListener('DOMContentLoaded', resolve, { once: true })) + return new Promise((resolve) => window.addEventListener('DOMContentLoaded', resolve, { once: true })) } diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index f80fb1198..27e3a1acb 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -16,7 +16,7 @@ class AppStateController { }, initState)) this.timer = null - preferencesStore.subscribe(state => { + preferencesStore.subscribe((state) => { this._setInactiveTimeout(state.preferences.autoLockTimeLimit) }) diff --git a/app/scripts/controllers/cached-balances.js b/app/scripts/controllers/cached-balances.js index 936bda85b..af7862ffd 100644 --- a/app/scripts/controllers/cached-balances.js +++ b/app/scripts/controllers/cached-balances.js @@ -50,7 +50,7 @@ class CachedBalancesController { const { cachedBalances } = this.store.getState() const currentNetworkBalancesToCache = { ...cachedBalances[currentNetwork] } - Object.keys(newAccounts).forEach(accountID => { + Object.keys(newAccounts).forEach((accountID) => { const account = newAccounts[accountID] if (account.balance) { diff --git a/app/scripts/controllers/incoming-transactions.js b/app/scripts/controllers/incoming-transactions.js index 45e572ef2..dfd79e95b 100644 --- a/app/scripts/controllers/incoming-transactions.js +++ b/app/scripts/controllers/incoming-transactions.js @@ -165,7 +165,7 @@ class IncomingTransactionsController { const newIncomingTransactions = { ...currentIncomingTxs, } - newTxs.forEach(tx => { + newTxs.forEach((tx) => { newIncomingTransactions[tx.hash] = tx }) @@ -222,7 +222,7 @@ class IncomingTransactionsController { } }) - const incomingTxs = remoteTxs.filter(tx => tx.txParams.to && tx.txParams.to.toLowerCase() === address.toLowerCase()) + const incomingTxs = remoteTxs.filter((tx) => tx.txParams.to && tx.txParams.to.toLowerCase() === address.toLowerCase()) incomingTxs.sort((a, b) => (a.time < b.time ? -1 : 1)) let latestIncomingTxBlockNumber = null diff --git a/app/scripts/controllers/network/createLocalhostClient.js b/app/scripts/controllers/network/createLocalhostClient.js index 15238716b..b4429f86d 100644 --- a/app/scripts/controllers/network/createLocalhostClient.js +++ b/app/scripts/controllers/network/createLocalhostClient.js @@ -25,7 +25,7 @@ function createLocalhostClient () { } function delay (time) { - return new Promise(resolve => setTimeout(resolve, time)) + return new Promise((resolve) => setTimeout(resolve, time)) } diff --git a/app/scripts/controllers/network/util.js b/app/scripts/controllers/network/util.js index 570651d61..d4243a851 100644 --- a/app/scripts/controllers/network/util.js +++ b/app/scripts/controllers/network/util.js @@ -27,7 +27,7 @@ const networkToNameMap = { [GOERLI_CODE]: GOERLI_DISPLAY_NAME, } -export const getNetworkDisplayName = key => networkToNameMap[key] +export const getNetworkDisplayName = (key) => networkToNameMap[key] export function formatTxMetaForRpcResult (txMeta) { return { diff --git a/app/scripts/controllers/permissions/index.js b/app/scripts/controllers/permissions/index.js index ec45d9b2e..2e468af07 100644 --- a/app/scripts/controllers/permissions/index.js +++ b/app/scripts/controllers/permissions/index.js @@ -197,7 +197,7 @@ export class PermissionsController { let error try { await new Promise((resolve, reject) => { - this.permissions.grantNewPermissions(origin, permissions, {}, err => (err ? resolve() : reject(err))) + this.permissions.grantNewPermissions(origin, permissions, {}, (err) => (err ? resolve() : reject(err))) }) } catch (err) { error = err @@ -263,7 +263,7 @@ export class PermissionsController { } // caveat names are unique, and we will only construct this caveat here - ethAccounts.caveats = ethAccounts.caveats.filter(c => ( + ethAccounts.caveats = ethAccounts.caveats.filter((c) => ( c.name !== CAVEAT_NAMES.exposedAccounts )) @@ -291,7 +291,7 @@ export class PermissionsController { // assert accounts exist const allAccounts = await this.getKeyringAccounts() - accounts.forEach(acc => { + accounts.forEach((acc) => { if (!allAccounts.includes(acc)) { throw new Error(`Unknown account: ${acc}`) } @@ -331,7 +331,7 @@ export class PermissionsController { this.permissions.removePermissionsFor( origin, - perms.map(methodName => { + perms.map((methodName) => { if (methodName === 'eth_accounts') { this.notifyDomain( @@ -366,7 +366,7 @@ export class PermissionsController { } const newPermittedAccounts = [account].concat( - permittedAccounts.filter(_account => _account !== account) + permittedAccounts.filter((_account) => _account !== account) ) // update permitted accounts to ensure that accounts are returned diff --git a/app/scripts/controllers/permissions/permissionsLog.js b/app/scripts/controllers/permissions/permissionsLog.js index 2d3b86823..e574b6cc3 100644 --- a/app/scripts/controllers/permissions/permissionsLog.js +++ b/app/scripts/controllers/permissions/permissionsLog.js @@ -116,7 +116,7 @@ export default class PermissionsLogController { } // call next with a return handler for capturing the response - next(cb => { + next((cb) => { const time = Date.now() this.logActivityResponse(requestId, res, time) @@ -234,7 +234,7 @@ export default class PermissionsLogController { // accounts were last seen or approved by the origin. newEntries = result ? result - .map(perm => { + .map((perm) => { if (perm.parentCapability === 'eth_accounts') { accounts = this.getAccountsFromPermission(perm) diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index e9a10ebce..b3de6a3e5 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -408,7 +408,7 @@ class PreferencesController { const { lastSelectedAddressByOrigin } = this.store.getState() - origins.forEach(origin => { + origins.forEach((origin) => { delete lastSelectedAddressByOrigin[origin] }) this.store.updateState({ lastSelectedAddressByOrigin }) @@ -472,7 +472,7 @@ class PreferencesController { removeToken (rawAddress) { const tokens = this.store.getState().tokens const assetImages = this.getAssetImages() - const updatedTokens = tokens.filter(token => token.address !== rawAddress) + const updatedTokens = tokens.filter((token) => token.address !== rawAddress) delete assetImages[rawAddress] this._updateAccountTokens(updatedTokens, assetImages) return Promise.resolve(updatedTokens) @@ -758,7 +758,7 @@ class PreferencesController { const tokenOpts = { rawAddress, decimals, symbol, image } this.addSuggestedERC20Asset(tokenOpts) return this.openPopup().then(() => { - const tokenAddresses = this.getTokens().filter(token => token.address === normalizeAddress(rawAddress)) + const tokenAddresses = this.getTokens().filter((token) => token.address === normalizeAddress(rawAddress)) return tokenAddresses.length > 0 }) } diff --git a/app/scripts/controllers/token-rates.js b/app/scripts/controllers/token-rates.js index 5abe9d122..1854a31c8 100644 --- a/app/scripts/controllers/token-rates.js +++ b/app/scripts/controllers/token-rates.js @@ -33,13 +33,13 @@ class TokenRatesController { } const contractExchangeRates = {} const nativeCurrency = this.currency ? this.currency.state.nativeCurrency.toLowerCase() : 'eth' - const pairs = this._tokens.map(token => token.address).join(',') + const pairs = this._tokens.map((token) => token.address).join(',') const query = `contract_addresses=${pairs}&vs_currencies=${nativeCurrency}` if (this._tokens.length > 0) { try { const response = await fetch(`https://api.coingecko.com/api/v3/simple/token_price/ethereum?${query}`) const prices = await response.json() - this._tokens.forEach(token => { + this._tokens.forEach((token) => { const price = prices[token.address.toLowerCase()] || prices[ethUtil.toChecksumAddress(token.address)] contractExchangeRates[normalizeAddress(token.address)] = price ? price[nativeCurrency] : 0 }) diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index 4b5ad2e9a..9560f2235 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -657,7 +657,7 @@ class TransactionController extends EventEmitter { TOKEN_METHOD_APPROVE, TOKEN_METHOD_TRANSFER, TOKEN_METHOD_TRANSFER_FROM, - ].find(tokenMethodName => tokenMethodName === name && name.toLowerCase()) + ].find((tokenMethodName) => tokenMethodName === name && name.toLowerCase()) let result if (txParams.data && tokenMethodName) { diff --git a/app/scripts/controllers/transactions/lib/util.js b/app/scripts/controllers/transactions/lib/util.js index 7df8e4764..589e26635 100644 --- a/app/scripts/controllers/transactions/lib/util.js +++ b/app/scripts/controllers/transactions/lib/util.js @@ -5,11 +5,11 @@ import { addHexPrefix, isValidAddress } from 'ethereumjs-util' const normalizers = { from: (from, LowerCase = true) => (LowerCase ? addHexPrefix(from).toLowerCase() : addHexPrefix(from)), to: (to, LowerCase = true) => (LowerCase ? addHexPrefix(to).toLowerCase() : addHexPrefix(to)), - nonce: nonce => addHexPrefix(nonce), - value: value => addHexPrefix(value), - data: data => addHexPrefix(data), - gas: gas => addHexPrefix(gas), - gasPrice: gasPrice => addHexPrefix(gasPrice), + nonce: (nonce) => addHexPrefix(nonce), + value: (value) => addHexPrefix(value), + data: (data) => addHexPrefix(data), + gas: (gas) => addHexPrefix(gas), + gasPrice: (gasPrice) => addHexPrefix(gasPrice), } /** diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index e8255841f..cbb57e0ed 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -207,7 +207,7 @@ class TransactionStateManager extends EventEmitter { // commit txMeta to state const txId = txMeta.id const txList = this.getFullTxList() - const index = txList.findIndex(txData => txData.id === txId) + const index = txList.findIndex((txData) => txData.id === txId) txList[index] = txMeta this._saveTxList(txList) } diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js index c18807479..57c2d6f63 100644 --- a/app/scripts/lib/account-tracker.js +++ b/app/scripts/lib/account-tracker.js @@ -57,7 +57,7 @@ class AccountTracker { this._blockTracker = opts.blockTracker // blockTracker.currentBlock may be null this._currentBlockNumber = this._blockTracker.getCurrentBlock() - this._blockTracker.once('latest', blockNumber => { + this._blockTracker.once('latest', (blockNumber) => { this._currentBlockNumber = blockNumber }) // bind function for easier listener syntax @@ -124,7 +124,7 @@ class AccountTracker { addAccounts (addresses) { const accounts = this.store.getState().accounts // add initial state for addresses - addresses.forEach(address => { + addresses.forEach((address) => { accounts[address] = {} }) // save accounts state @@ -145,7 +145,7 @@ class AccountTracker { removeAccount (addresses) { const accounts = this.store.getState().accounts // remove each state object - addresses.forEach(address => { + addresses.forEach((address) => { delete accounts[address] }) // save accounts state diff --git a/app/scripts/lib/createDnodeRemoteGetter.js b/app/scripts/lib/createDnodeRemoteGetter.js index 8f06a40a8..038ae412d 100644 --- a/app/scripts/lib/createDnodeRemoteGetter.js +++ b/app/scripts/lib/createDnodeRemoteGetter.js @@ -11,7 +11,7 @@ function createDnodeRemoteGetter (dnode) { if (remote) { return remote } - return await new Promise(resolve => dnode.once('remote', resolve)) + return await new Promise((resolve) => dnode.once('remote', resolve)) } return getRemote diff --git a/app/scripts/lib/ens-ipfs/setup.js b/app/scripts/lib/ens-ipfs/setup.js index ee04b9340..351418754 100644 --- a/app/scripts/lib/ens-ipfs/setup.js +++ b/app/scripts/lib/ens-ipfs/setup.js @@ -9,7 +9,7 @@ export default setupEnsIpfsResolver function setupEnsIpfsResolver ({ provider, getCurrentNetwork, getIpfsGateway }) { // install listener - const urlPatterns = supportedTopLevelDomains.map(tld => `*://*.${tld}/*`) + const urlPatterns = supportedTopLevelDomains.map((tld) => `*://*.${tld}/*`) extension.webRequest.onErrorOccurred.addListener(webRequestDidFail, { urls: urlPatterns, types: ['main_frame'] }) // return api object diff --git a/app/scripts/lib/get-first-preferred-lang-code.js b/app/scripts/lib/get-first-preferred-lang-code.js index 3e052bd09..806a4a70e 100644 --- a/app/scripts/lib/get-first-preferred-lang-code.js +++ b/app/scripts/lib/get-first-preferred-lang-code.js @@ -9,7 +9,7 @@ const getPreferredLocales = extension.i18n ? promisify( // mapping some browsers return hyphen instead underscore in locale codes (e.g. zh_TW -> zh-tw) const existingLocaleCodes = {} -allLocales.forEach(locale => { +allLocales.forEach((locale) => { if (locale && locale.code) { existingLocaleCodes[locale.code.toLowerCase().replace('_', '-')] = locale.code } @@ -39,8 +39,8 @@ async function getFirstPreferredLangCode () { } const firstPreferredLangCode = userPreferredLocaleCodes - .map(code => code.toLowerCase().replace('_', '-')) - .find(code => existingLocaleCodes.hasOwnProperty(code)) + .map((code) => code.toLowerCase().replace('_', '-')) + .find((code) => existingLocaleCodes.hasOwnProperty(code)) return existingLocaleCodes[firstPreferredLangCode] || 'en' } diff --git a/app/scripts/lib/message-manager.js b/app/scripts/lib/message-manager.js index 9af28663e..387ccce47 100644 --- a/app/scripts/lib/message-manager.js +++ b/app/scripts/lib/message-manager.js @@ -61,7 +61,7 @@ export default class MessageManager extends EventEmitter { * */ getUnapprovedMsgs () { - return this.messages.filter(msg => msg.status === 'unapproved') + return this.messages.filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { result[msg.id] = msg; return result }, {}) @@ -145,7 +145,7 @@ export default class MessageManager extends EventEmitter { * */ getMsg (msgId) { - return this.messages.find(msg => msg.id === msgId) + return this.messages.find((msg) => msg.id === msgId) } /** diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index e708ed1c8..88cdee44b 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -65,7 +65,7 @@ export default class PersonalMessageManager extends EventEmitter { * */ getUnapprovedMsgs () { - return this.messages.filter(msg => msg.status === 'unapproved') + return this.messages.filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { result[msg.id] = msg; return result }, {}) @@ -155,7 +155,7 @@ export default class PersonalMessageManager extends EventEmitter { * */ getMsg (msgId) { - return this.messages.find(msg => msg.id === msgId) + return this.messages.find((msg) => msg.id === msgId) } /** diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index 18c3507ea..b1f65246b 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -37,7 +37,7 @@ function setupSentry (opts) { beforeSend: (report) => rewriteReport(report), }) - Sentry.configureScope(scope => { + Sentry.configureScope((scope) => { scope.setExtra('isBrave', isBrave) }) @@ -81,7 +81,7 @@ function rewriteErrorMessages (report, rewriteFn) { } // rewrite each exception message if (report.exception && report.exception.values) { - report.exception.values.forEach(item => { + report.exception.values.forEach((item) => { if (typeof item.value === 'string') { item.value = rewriteFn(item.value) } @@ -94,8 +94,8 @@ function rewriteReportUrls (report) { report.request.url = toMetamaskUrl(report.request.url) // update exception stack trace if (report.exception && report.exception.values) { - report.exception.values.forEach(item => { - item.stacktrace.frames.forEach(frame => { + report.exception.values.forEach((item) => { + item.stacktrace.frames.forEach((frame) => { frame.filename = toMetamaskUrl(frame.filename) }) }) diff --git a/app/scripts/lib/typed-message-manager.js b/app/scripts/lib/typed-message-manager.js index 84c1864a4..346051e30 100644 --- a/app/scripts/lib/typed-message-manager.js +++ b/app/scripts/lib/typed-message-manager.js @@ -57,7 +57,7 @@ export default class TypedMessageManager extends EventEmitter { * */ getUnapprovedMsgs () { - return this.messages.filter(msg => msg.status === 'unapproved') + return this.messages.filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { result[msg.id] = msg; return result }, {}) @@ -189,7 +189,7 @@ export default class TypedMessageManager extends EventEmitter { * */ getMsg (msgId) { - return this.messages.find(msg => msg.id === msgId) + return this.messages.find((msg) => msg.id === msgId) } /** diff --git a/app/scripts/lib/util.js b/app/scripts/lib/util.js index 119470250..05ea98518 100644 --- a/app/scripts/lib/util.js +++ b/app/scripts/lib/util.js @@ -44,7 +44,7 @@ const getEnvironmentType = (url = window.location.href) => { * @returns {string} - the platform ENUM * */ -const getPlatform = _ => { +const getPlatform = (_) => { const ua = navigator.userAgent if (ua.search('Firefox') !== -1) { return PLATFORM_FIREFOX @@ -135,7 +135,7 @@ function getRandomArrayItem (array) { function mapObjectValues (object, cb) { const mappedObject = {} - Object.keys(object).forEach(key => { + Object.keys(object).forEach((key) => { mappedObject[key] = cb(key, object[key]) }) return mappedObject diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 4fe9903ea..5448a74b3 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -697,11 +697,11 @@ export default class MetamaskController extends EventEmitter { // Filter ERC20 tokens const filteredAccountTokens = {} - Object.keys(accountTokens).forEach(address => { + Object.keys(accountTokens).forEach((address) => { const checksummedAddress = ethUtil.toChecksumAddress(address) filteredAccountTokens[checksummedAddress] = {} Object.keys(accountTokens[address]).forEach( - networkType => (filteredAccountTokens[checksummedAddress][networkType] = networkType !== 'mainnet' ? + (networkType) => (filteredAccountTokens[checksummedAddress][networkType] = networkType !== 'mainnet' ? accountTokens[address][networkType] : accountTokens[address][networkType].filter(({ address }) => { const tokenAddress = ethUtil.toChecksumAddress(address) @@ -724,7 +724,7 @@ export default class MetamaskController extends EventEmitter { const hdKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0] const hdAccounts = await hdKeyring.getAccounts() const accounts = { - hd: hdAccounts.filter((item, pos) => (hdAccounts.indexOf(item) === pos)).map(address => ethUtil.toChecksumAddress(address)), + hd: hdAccounts.filter((item, pos) => (hdAccounts.indexOf(item) === pos)).map((address) => ethUtil.toChecksumAddress(address)), simpleKeyPair: [], ledger: [], trezor: [], @@ -734,7 +734,7 @@ export default class MetamaskController extends EventEmitter { let transactions = this.txController.store.getState().transactions // delete tx for other accounts that we're not importing - transactions = transactions.filter(tx => { + transactions = transactions.filter((tx) => { const checksummedTxFrom = ethUtil.toChecksumAddress(tx.txParams.from) return ( accounts.hd.includes(checksummedTxFrom) @@ -762,7 +762,7 @@ export default class MetamaskController extends EventEmitter { const accounts = await this.keyringController.getAccounts() // verify keyrings - const nonSimpleKeyrings = this.keyringController.keyrings.filter(keyring => keyring.type !== 'Simple Key Pair') + const nonSimpleKeyrings = this.keyringController.keyrings.filter((keyring) => keyring.type !== 'Simple Key Pair') if (nonSimpleKeyrings.length > 1 && this.diagnostics) { await this.diagnostics.reportMultipleKeyrings(nonSimpleKeyrings) } @@ -855,7 +855,7 @@ export default class MetamaskController extends EventEmitter { // Merge with existing accounts // and make sure addresses are not repeated const oldAccounts = await this.keyringController.getAccounts() - const accountsToTrack = [...new Set(oldAccounts.concat(accounts.map(a => a.address.toLowerCase())))] + const accountsToTrack = [...new Set(oldAccounts.concat(accounts.map((a) => a.address.toLowerCase())))] this.accountTracker.syncWithAddresses(accountsToTrack) return accounts } @@ -895,7 +895,7 @@ export default class MetamaskController extends EventEmitter { const keyState = await this.keyringController.addNewAccount(keyring) const newAccounts = await this.keyringController.getAccounts() this.preferencesController.setAddresses(newAccounts) - newAccounts.forEach(address => { + newAccounts.forEach((address) => { if (!oldAccounts.includes(address)) { // Set the account label to Trezor 1 / Ledger 1, etc this.preferencesController.setAccountLabel(address, `${deviceName[0].toUpperCase()}${deviceName.slice(1)} ${parseInt(index, 10) + 1}`) @@ -1580,7 +1580,7 @@ export default class MetamaskController extends EventEmitter { return } - Object.values(connections).forEach(conn => { + Object.values(connections).forEach((conn) => { conn.engine && conn.engine.emit('notification', payload) }) } @@ -1599,8 +1599,8 @@ export default class MetamaskController extends EventEmitter { return } - Object.values(this.connections).forEach(origin => { - Object.values(origin).forEach(conn => { + Object.values(this.connections).forEach((origin) => { + Object.values(origin).forEach((conn) => { conn.engine && conn.engine.emit('notification', payload) }) }) @@ -1671,13 +1671,13 @@ export default class MetamaskController extends EventEmitter { return GWEI_BN } return block.gasPrices - .map(hexPrefix => hexPrefix.substr(2)) - .map(hex => new BN(hex, 16)) + .map((hexPrefix) => hexPrefix.substr(2)) + .map((hex) => new BN(hex, 16)) .sort((a, b) => { return a.gt(b) ? 1 : -1 })[0] }) - .map(number => number.div(GWEI_BN).toNumber()) + .map((number) => number.div(GWEI_BN).toNumber()) const percentileNum = percentile(65, lowestPrices) const percentileNumBn = new BN(percentileNum) diff --git a/app/scripts/migrations/025.js b/app/scripts/migrations/025.js index d338f265f..1f3721d27 100644 --- a/app/scripts/migrations/025.js +++ b/app/scripts/migrations/025.js @@ -45,13 +45,13 @@ function transformState (state) { function normalizeTxParams (txParams) { // functions that handle normalizing of that key in txParams const whiteList = { - from: from => ethUtil.addHexPrefix(from).toLowerCase(), + from: (from) => ethUtil.addHexPrefix(from).toLowerCase(), to: () => ethUtil.addHexPrefix(txParams.to).toLowerCase(), - nonce: nonce => ethUtil.addHexPrefix(nonce), - value: value => ethUtil.addHexPrefix(value), - data: data => ethUtil.addHexPrefix(data), - gas: gas => ethUtil.addHexPrefix(gas), - gasPrice: gasPrice => ethUtil.addHexPrefix(gasPrice), + nonce: (nonce) => ethUtil.addHexPrefix(nonce), + value: (value) => ethUtil.addHexPrefix(value), + data: (data) => ethUtil.addHexPrefix(data), + gas: (gas) => ethUtil.addHexPrefix(gas), + gasPrice: (gasPrice) => ethUtil.addHexPrefix(gasPrice), } // apply only keys in the whiteList diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 85119b054..2d40e087e 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -67,7 +67,7 @@ class ExtensionPlatform { currentTab () { return new Promise((resolve, reject) => { - extension.tabs.getCurrent(tab => { + extension.tabs.getCurrent((tab) => { const err = checkForError() if (err) { reject(err) diff --git a/development/metamaskbot-build-announce.js b/development/metamaskbot-build-announce.js index baf82a0f1..dc0dab936 100755 --- a/development/metamaskbot-build-announce.js +++ b/development/metamaskbot-build-announce.js @@ -33,14 +33,14 @@ async function start () { // links to extension builds const platforms = ['chrome', 'firefox', 'opera'] - const buildLinks = platforms.map(platform => { + const buildLinks = platforms.map((platform) => { const url = `${BUILD_LINK_BASE}/builds/metamask-${platform}-${VERSION}.zip` return `${platform}` }).join(', ') // links to bundle browser builds const bundles = ['background', 'ui', 'inpage', 'contentscript', 'ui-libs', 'bg-libs', 'phishing-detect'] - const bundleLinks = bundles.map(bundle => { + const bundleLinks = bundles.map((bundle) => { const url = `${BUILD_LINK_BASE}/build-artifacts/source-map-explorer/${bundle}.html` return `${bundle}` }).join(', ') @@ -58,7 +58,7 @@ async function start () { `dep viz: ${depVizLink}`, `all artifacts`, ] - const hiddenContent = `
      ` + contentRows.map(row => `
    • ${row}
    • `).join('\n') + `
    ` + const hiddenContent = `
      ` + contentRows.map((row) => `
    • ${row}
    • `).join('\n') + `
    ` const exposedContent = `Builds ready [${SHORT_SHA1}]` const artifactsBody = `
    ${exposedContent}${hiddenContent}
    ` @@ -136,7 +136,7 @@ async function start () { for (const measure of allMeasures) { benchmarkTableHeaders.push(`${capitalizeFirstLetter(measure)} (ms)`) } - const benchmarkTableHeader = `${benchmarkTableHeaders.map(header => `${header}`).join('')}` + const benchmarkTableHeader = `${benchmarkTableHeaders.map((header) => `${header}`).join('')}` const benchmarkTableBody = `${tableRows.join('')}` const benchmarkTable = `${benchmarkTableHeader}${benchmarkTableBody}
    ` const benchmarkBody = `
    ${benchmarkSummary}${benchmarkTable}
    ` diff --git a/development/mock-3box.js b/development/mock-3box.js index af95a74bb..44307dd99 100644 --- a/development/mock-3box.js +++ b/development/mock-3box.js @@ -1,5 +1,5 @@ function delay (time) { - return new Promise(resolve => setTimeout(resolve, time)) + return new Promise((resolve) => setTimeout(resolve, time)) } async function loadFromMock3Box (key) { @@ -24,7 +24,7 @@ class Mock3Box { static openBox (address) { this.address = address return Promise.resolve({ - onSyncDone: cb => { + onSyncDone: (cb) => { setTimeout(cb, 200) }, openSpace: async (spaceName, config) => { diff --git a/development/show-deps-install-scripts.js b/development/show-deps-install-scripts.js index 419c9d25f..12301fe0d 100644 --- a/development/show-deps-install-scripts.js +++ b/development/show-deps-install-scripts.js @@ -14,7 +14,7 @@ readInstalled('./', { dev: true }, function (err, data) { const packageScripts = packageData.scripts || {} const scriptKeys = Reflect.ownKeys(packageScripts) - const hasInstallScript = installScripts.some(installKey => scriptKeys.includes(installKey)) + const hasInstallScript = installScripts.some((installKey) => scriptKeys.includes(installKey)) if (!hasInstallScript) { return } diff --git a/development/sourcemap-validator.js b/development/sourcemap-validator.js index 797f84656..e87c0604f 100644 --- a/development/sourcemap-validator.js +++ b/development/sourcemap-validator.js @@ -63,7 +63,7 @@ async function validateSourcemapForFile ({ buildName }) { const buildLines = rawBuild.split('\n') const targetString = 'new Error' // const targetString = 'null' - const matchesPerLine = buildLines.map(line => indicesOf(targetString, line)) + const matchesPerLine = buildLines.map((line) => indicesOf(targetString, line)) matchesPerLine.forEach((matchIndices, lineIndex) => { matchIndices.forEach((matchColumn) => { sampleCount++ diff --git a/development/verify-locale-strings.js b/development/verify-locale-strings.js index 3b114a1e8..990ed95f4 100644 --- a/development/verify-locale-strings.js +++ b/development/verify-locale-strings.js @@ -47,7 +47,7 @@ for (const arg of process.argv.slice(2)) { } main(specifiedLocale, fix) - .catch(error => { + .catch((error) => { log.error(error) process.exit(1) }) @@ -55,7 +55,7 @@ main(specifiedLocale, fix) async function main (specifiedLocale, fix) { if (specifiedLocale) { log.info(`Verifying selected locale "${specifiedLocale}":\n`) - const locale = localeIndex.find(localeMeta => localeMeta.code === specifiedLocale) + const locale = localeIndex.find((localeMeta) => localeMeta.code === specifiedLocale) const failed = locale.code === 'en' ? await verifyEnglishLocale(fix) : await verifyLocale(locale, fix) @@ -66,8 +66,8 @@ async function main (specifiedLocale, fix) { log.info('Verifying all locales:\n') let failed = await verifyEnglishLocale(fix) const localeCodes = localeIndex - .filter(localeMeta => localeMeta.code !== 'en') - .map(localeMeta => localeMeta.code) + .filter((localeMeta) => localeMeta.code !== 'en') + .map((localeMeta) => localeMeta.code) for (const code of localeCodes) { log.info() // Separate each locale report by a newline when not in '--quiet' mode @@ -179,7 +179,7 @@ async function verifyEnglishLocale (fix = false) { const templateMatches = fileContents.match(templateStringRegex) if (templateMatches) { // concat doesn't work here for some reason - templateMatches.forEach(match => templateUsage.push(match)) + templateMatches.forEach((match) => templateUsage.push(match)) } } @@ -188,7 +188,7 @@ async function verifyEnglishLocale (fix = false) { const englishMessages = Object.keys(englishLocale) const unusedMessages = englishMessages - .filter(message => !messageExceptions.includes(message) && !usedMessages.has(message)) + .filter((message) => !messageExceptions.includes(message) && !usedMessages.has(message)) if (unusedMessages.length) { console.log(`**en**: ${unusedMessages.length} unused messages`) diff --git a/gulpfile.js b/gulpfile.js index fb37c457b..c1e65ea12 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -33,7 +33,7 @@ sass.compiler = require('node-sass') const dependencies = Object.keys(packageJSON && packageJSON.dependencies || {}) const materialUIDependencies = ['@material-ui/core'] -const reactDepenendencies = dependencies.filter(dep => dep.match(/react/)) +const reactDepenendencies = dependencies.filter((dep) => dep.match(/react/)) const d3Dependencies = ['c3', 'd3'] const externalDependenciesMap = { @@ -77,38 +77,38 @@ const copyDevTaskNames = [] createCopyTasks('locales', { source: './app/_locales/', - destinations: commonPlatforms.map(platform => `./dist/${platform}/_locales`), + destinations: commonPlatforms.map((platform) => `./dist/${platform}/_locales`), }) createCopyTasks('images', { source: './app/images/', - destinations: commonPlatforms.map(platform => `./dist/${platform}/images`), + destinations: commonPlatforms.map((platform) => `./dist/${platform}/images`), }) createCopyTasks('contractImages', { source: './node_modules/eth-contract-metadata/images/', - destinations: commonPlatforms.map(platform => `./dist/${platform}/images/contract`), + destinations: commonPlatforms.map((platform) => `./dist/${platform}/images/contract`), }) createCopyTasks('fonts', { source: './app/fonts/', - destinations: commonPlatforms.map(platform => `./dist/${platform}/fonts`), + destinations: commonPlatforms.map((platform) => `./dist/${platform}/fonts`), }) createCopyTasks('vendor', { source: './app/vendor/', - destinations: commonPlatforms.map(platform => `./dist/${platform}/vendor`), + destinations: commonPlatforms.map((platform) => `./dist/${platform}/vendor`), }) createCopyTasks('css', { source: './ui/app/css/output/', - destinations: commonPlatforms.map(platform => `./dist/${platform}`), + destinations: commonPlatforms.map((platform) => `./dist/${platform}`), }) createCopyTasks('reload', { devOnly: true, source: './app/scripts/', pattern: '/chromereload.js', - destinations: commonPlatforms.map(platform => `./dist/${platform}`), + destinations: commonPlatforms.map((platform) => `./dist/${platform}`), }) createCopyTasks('html', { source: './app/', pattern: '/*.html', - destinations: commonPlatforms.map(platform => `./dist/${platform}`), + destinations: commonPlatforms.map((platform) => `./dist/${platform}`), }) // copy extension @@ -116,7 +116,7 @@ createCopyTasks('html', { createCopyTasks('manifest', { source: './app/', pattern: '/*.json', - destinations: browserPlatforms.map(platform => `./dist/${platform}`), + destinations: browserPlatforms.map((platform) => `./dist/${platform}`), }) function createCopyTasks (label, opts) { @@ -235,7 +235,7 @@ gulp.task('manifest:testing-local', function () { .pipe(jsoneditor(function (json) { json.background = { ...json.background, - scripts: json.background.scripts.filter(scriptName => !scriptsToExcludeFromBackgroundDevBuild[scriptName]), + scripts: json.background.scripts.filter((scriptName) => !scriptsToExcludeFromBackgroundDevBuild[scriptName]), } json.permissions = [...json.permissions, 'webRequestBlocking', 'http://localhost/*'] return json @@ -254,7 +254,7 @@ gulp.task('manifest:dev', function () { .pipe(jsoneditor(function (json) { json.background = { ...json.background, - scripts: json.background.scripts.filter(scriptName => !scriptsToExcludeFromBackgroundDevBuild[scriptName]), + scripts: json.background.scripts.filter((scriptName) => !scriptsToExcludeFromBackgroundDevBuild[scriptName]), } json.permissions = [...json.permissions, 'webRequestBlocking'] return json @@ -378,7 +378,7 @@ createTasksForBuildJsExtension({ buildJsFiles, taskPrefix: 'build:extension:js' createTasksForBuildJsExtension({ buildJsFiles, taskPrefix: 'build:test:extension:js', testing: 'true' }) function createTasksForBuildJsDeps ({ key, filename }) { - const destinations = browserPlatforms.map(platform => `./dist/${platform}`) + const destinations = browserPlatforms.map((platform) => `./dist/${platform}`) const bundleTaskOpts = Object.assign({ buildSourceMaps: true, @@ -400,10 +400,10 @@ function createTasksForBuildJsDeps ({ key, filename }) { function createTasksForBuildJsExtension ({ buildJsFiles, taskPrefix, devMode, testing, bundleTaskOpts = {} }) { // inpage must be built before all other scripts: const rootDir = './app/scripts' - const nonInpageFiles = buildJsFiles.filter(file => file !== 'inpage') + const nonInpageFiles = buildJsFiles.filter((file) => file !== 'inpage') const buildPhase1 = ['inpage'] const buildPhase2 = nonInpageFiles - const destinations = browserPlatforms.map(platform => `./dist/${platform}`) + const destinations = browserPlatforms.map((platform) => `./dist/${platform}`) bundleTaskOpts = Object.assign({ buildSourceMaps: true, sourceMapDir: '../sourcemaps', @@ -430,9 +430,9 @@ function createTasksForBuildJs ({ rootDir, taskPrefix, bundleTaskOpts, destinati }) // compose into larger task const subtasks = [] - subtasks.push(gulp.parallel(buildPhase1.map(file => `${taskPrefix}:${file}`))) + subtasks.push(gulp.parallel(buildPhase1.map((file) => `${taskPrefix}:${file}`))) if (buildPhase2.length) { - subtasks.push(gulp.parallel(buildPhase2.map(file => `${taskPrefix}:${file}`))) + subtasks.push(gulp.parallel(buildPhase2.map((file) => `${taskPrefix}:${file}`))) } gulp.task(taskPrefix, gulp.series(subtasks)) diff --git a/test/e2e/address-book.spec.js b/test/e2e/address-book.spec.js index 95c78b27d..6171dc222 100644 --- a/test/e2e/address-book.spec.js +++ b/test/e2e/address-book.spec.js @@ -37,7 +37,7 @@ describe('MetaMask', function () { if (process.env.SELENIUM_BROWSER === 'chrome') { const errors = await driver.checkBrowserForConsoleErrors() if (errors.length) { - const errorReports = errors.map(err => err.message) + const errorReports = errors.map((err) => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` console.error(new Error(errorMessage)) } diff --git a/test/e2e/benchmark.js b/test/e2e/benchmark.js index 825382559..6917005c9 100644 --- a/test/e2e/benchmark.js +++ b/test/e2e/benchmark.js @@ -37,10 +37,10 @@ const calculateSum = (array) => array.reduce((sum, val) => sum + val) const calculateAverage = (array) => calculateSum(array) / array.length const minResult = calculateResult((array) => Math.min(...array)) const maxResult = calculateResult((array) => Math.max(...array)) -const averageResult = calculateResult(array => calculateAverage(array)) +const averageResult = calculateResult((array) => calculateAverage(array)) const standardDeviationResult = calculateResult((array) => { const average = calculateAverage(array) - const squareDiffs = array.map(value => Math.pow(value - average, 2)) + const squareDiffs = array.map((value) => Math.pow(value - average, 2)) return Math.sqrt(calculateAverage(squareDiffs)) }) // 95% margin of error calculated using Student's t-distrbution @@ -55,17 +55,17 @@ async function profilePageLoad (pages, numSamples) { runResults.push(await measurePage(pageName)) } - if (runResults.some(result => result.navigation.lenth > 1)) { + if (runResults.some((result) => result.navigation.lenth > 1)) { throw new Error(`Multiple navigations not supported`) - } else if (runResults.some(result => result.navigation[0].type !== 'navigate')) { - throw new Error(`Navigation type ${runResults.find(result => result.navigation[0].type !== 'navigate').navigation[0].type} not supported`) + } else if (runResults.some((result) => result.navigation[0].type !== 'navigate')) { + throw new Error(`Navigation type ${runResults.find((result) => result.navigation[0].type !== 'navigate').navigation[0].type} not supported`) } const result = { - firstPaint: runResults.map(result => result.paint['first-paint']), - domContentLoaded: runResults.map(result => result.navigation[0] && result.navigation[0].domContentLoaded), - load: runResults.map(result => result.navigation[0] && result.navigation[0].load), - domInteractive: runResults.map(result => result.navigation[0] && result.navigation[0].domInteractive), + firstPaint: runResults.map((result) => result.paint['first-paint']), + domContentLoaded: runResults.map((result) => result.navigation[0] && result.navigation[0].domContentLoaded), + load: runResults.map((result) => result.navigation[0] && result.navigation[0].load), + domInteractive: runResults.map((result) => result.navigation[0] && result.navigation[0].domInteractive), } results[pageName] = { @@ -166,7 +166,7 @@ async function main () { } main() - .catch(e => { + .catch((e) => { console.error(e) process.exit(1) }) diff --git a/test/e2e/ethereum-on.spec.js b/test/e2e/ethereum-on.spec.js index 8fce9c45b..deb7c16f1 100644 --- a/test/e2e/ethereum-on.spec.js +++ b/test/e2e/ethereum-on.spec.js @@ -36,7 +36,7 @@ describe('MetaMask', function () { if (process.env.SELENIUM_BROWSER === 'chrome') { const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { - const errorReports = errors.map(err => err.message) + const errorReports = errors.map((err) => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` console.error(new Error(errorMessage)) } @@ -119,7 +119,7 @@ describe('MetaMask', function () { extension = windowHandles[0] dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) - popup = windowHandles.find(handle => handle !== extension && handle !== dapp) + popup = windowHandles.find((handle) => handle !== extension && handle !== dapp) await driver.switchToWindow(popup) diff --git a/test/e2e/from-import-ui.spec.js b/test/e2e/from-import-ui.spec.js index 666981bc3..ab8832392 100644 --- a/test/e2e/from-import-ui.spec.js +++ b/test/e2e/from-import-ui.spec.js @@ -41,7 +41,7 @@ describe('Using MetaMask with an existing account', function () { if (process.env.SELENIUM_BROWSER === 'chrome') { const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { - const errorReports = errors.map(err => err.message) + const errorReports = errors.map((err) => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` console.error(new Error(errorMessage)) } diff --git a/test/e2e/incremental-security.spec.js b/test/e2e/incremental-security.spec.js index 57b38cb65..4964dfb0f 100644 --- a/test/e2e/incremental-security.spec.js +++ b/test/e2e/incremental-security.spec.js @@ -41,7 +41,7 @@ describe('MetaMask', function () { if (process.env.SELENIUM_BROWSER === 'chrome') { const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { - const errorReports = errors.map(err => err.message) + const errorReports = errors.map((err) => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` console.error(new Error(errorMessage)) } diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index 41eee8efd..e4d18f01d 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -31,7 +31,7 @@ describe('MetaMask', function () { if (process.env.SELENIUM_BROWSER === 'chrome') { const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { - const errorReports = errors.map(err => err.message) + const errorReports = errors.map((err) => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` console.error(new Error(errorMessage)) } diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index ad86c1ec1..d2a1472da 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -32,7 +32,7 @@ describe('MetaMask', function () { if (process.env.SELENIUM_BROWSER === 'chrome') { const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { - const errorReports = errors.map(err => err.message) + const errorReports = errors.map((err) => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` console.error(new Error(errorMessage)) } @@ -407,7 +407,7 @@ describe('MetaMask', function () { extension = windowHandles[0] dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) - popup = windowHandles.find(handle => handle !== extension && handle !== dapp) + popup = windowHandles.find((handle) => handle !== extension && handle !== dapp) await driver.switchToWindow(popup) @@ -1273,7 +1273,7 @@ describe('MetaMask', function () { 'http://127.0.0.1:8545/4', ] - customRpcUrls.forEach(customRpcUrl => { + customRpcUrls.forEach((customRpcUrl) => { it(`creates custom RPC: ${customRpcUrl}`, async function () { await driver.clickElement(By.css('.network-name')) await driver.delay(regularDelayMs) diff --git a/test/e2e/mock-3box/server.js b/test/e2e/mock-3box/server.js index afbfa8031..9d6bc7372 100644 --- a/test/e2e/mock-3box/server.js +++ b/test/e2e/mock-3box/server.js @@ -9,7 +9,7 @@ const requestHandler = (request, response) => { response.setHeader('Content-Type', 'application/json') if (request.method === 'POST') { let body = '' - request.on('data', chunk => { + request.on('data', (chunk) => { body += chunk.toString() // convert Buffer to string }) request.on('end', () => { diff --git a/test/e2e/permissions.spec.js b/test/e2e/permissions.spec.js index a34b11a8d..d287cff6d 100644 --- a/test/e2e/permissions.spec.js +++ b/test/e2e/permissions.spec.js @@ -36,7 +36,7 @@ describe('MetaMask', function () { if (process.env.SELENIUM_BROWSER === 'chrome') { const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { - const errorReports = errors.map(err => err.message) + const errorReports = errors.map((err) => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` console.error(new Error(errorMessage)) } @@ -117,7 +117,7 @@ describe('MetaMask', function () { extension = windowHandles[0] dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) - popup = windowHandles.find(handle => handle !== extension && handle !== dapp) + popup = windowHandles.find((handle) => handle !== extension && handle !== dapp) await driver.switchToWindow(popup) diff --git a/test/e2e/send-edit.spec.js b/test/e2e/send-edit.spec.js index 8af966a20..9cb39b5e6 100644 --- a/test/e2e/send-edit.spec.js +++ b/test/e2e/send-edit.spec.js @@ -38,7 +38,7 @@ describe('Using MetaMask with an existing account', function () { if (process.env.SELENIUM_BROWSER === 'chrome') { const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { - const errorReports = errors.map(err => err.message) + const errorReports = errors.map((err) => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` console.error(new Error(errorMessage)) } diff --git a/test/e2e/signature-request.spec.js b/test/e2e/signature-request.spec.js index 738ea262c..b17bf48c5 100644 --- a/test/e2e/signature-request.spec.js +++ b/test/e2e/signature-request.spec.js @@ -35,7 +35,7 @@ describe('MetaMask', function () { if (process.env.SELENIUM_BROWSER === 'chrome') { const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { - const errorReports = errors.map(err => err.message) + const errorReports = errors.map((err) => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` console.error(new Error(errorMessage)) } @@ -78,7 +78,7 @@ describe('MetaMask', function () { extension = windowHandles[0] dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) - popup = windowHandles.find(handle => handle !== extension && handle !== dapp) + popup = windowHandles.find((handle) => handle !== extension && handle !== dapp) await driver.switchToWindow(popup) diff --git a/test/e2e/threebox.spec.js b/test/e2e/threebox.spec.js index d55e9419a..85ba75834 100644 --- a/test/e2e/threebox.spec.js +++ b/test/e2e/threebox.spec.js @@ -39,7 +39,7 @@ describe('MetaMask', function () { if (process.env.SELENIUM_BROWSER === 'chrome') { const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { - const errorReports = errors.map(err => err.message) + const errorReports = errors.map((err) => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` console.error(new Error(errorMessage)) } diff --git a/test/e2e/web3.spec.js b/test/e2e/web3.spec.js index 9769459f8..108fdc8c5 100644 --- a/test/e2e/web3.spec.js +++ b/test/e2e/web3.spec.js @@ -38,7 +38,7 @@ describe('Using MetaMask with an existing account', function () { if (process.env.SELENIUM_BROWSER === 'chrome') { const errors = await driver.checkBrowserForConsoleErrors(driver) if (errors.length) { - const errorReports = errors.map(err => err.message) + const errorReports = errors.map((err) => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` console.error(new Error(errorMessage)) } @@ -116,7 +116,7 @@ describe('Using MetaMask with an existing account', function () { const extension = windowHandles[0] const popup = await driver.switchToWindowWithTitle('MetaMask Notification', windowHandles) - const dapp = windowHandles.find(handle => handle !== extension && handle !== popup) + const dapp = windowHandles.find((handle) => handle !== extension && handle !== popup) await driver.delay(regularDelayMs) await driver.clickElement(By.xpath(`//button[contains(text(), 'Connect')]`)) diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index 4369f88cd..169e09a23 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -16,7 +16,7 @@ class Driver { } async delay (time) { - await new Promise(resolve => setTimeout(resolve, time)) + await new Promise((resolve) => setTimeout(resolve, time)) } async wait (condition, timeout = this.timeout) { @@ -180,9 +180,9 @@ class Driver { 'favicon.ico - Failed to load resource: the server responded with a status of 404 (Not Found)', ] const browserLogs = await this.driver.manage().logs().get('browser') - const errorEntries = browserLogs.filter(entry => !ignoredLogTypes.includes(entry.level.toString())) - const errorObjects = errorEntries.map(entry => entry.toJSON()) - return errorObjects.filter(entry => !ignoredErrorMessages.some(message => entry.message.includes(message))) + const errorEntries = browserLogs.filter((entry) => !ignoredLogTypes.includes(entry.level.toString())) + const errorObjects = errorEntries.map((entry) => entry.toJSON()) + return errorObjects.filter((entry) => !ignoredErrorMessages.some((message) => entry.message.includes(message))) } } diff --git a/test/lib/render-helpers.js b/test/lib/render-helpers.js index 45bcb1656..874c80846 100644 --- a/test/lib/render-helpers.js +++ b/test/lib/render-helpers.js @@ -26,8 +26,8 @@ export function mountWithRouter (component, store = {}, pathname = '/') { const createContext = () => ({ context: { router, - t: str => str, - tOrKey: str => str, + t: (str) => str, + tOrKey: (str) => str, metricsEvent: () => {}, store, }, diff --git a/test/setup.js b/test/setup.js index 5aa6e59dd..0e4ebe248 100644 --- a/test/setup.js +++ b/test/setup.js @@ -1,5 +1,5 @@ require('@babel/register')({ - ignore: [name => name.includes('node_modules') && !name.includes('obs-store')], + ignore: [(name) => name.includes('node_modules') && !name.includes('obs-store')], }) require('./helper') diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index e0d805961..9d01c1549 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -903,7 +903,7 @@ describe('MetaMaskController', function () { function deferredPromise () { let resolve - const promise = new Promise(_resolve => { + const promise = new Promise((_resolve) => { resolve = _resolve }) return { promise, resolve } diff --git a/test/unit/app/controllers/transactions/pending-tx-test.js b/test/unit/app/controllers/transactions/pending-tx-test.js index 3dfd852c2..7bbc5c58c 100644 --- a/test/unit/app/controllers/transactions/pending-tx-test.js +++ b/test/unit/app/controllers/transactions/pending-tx-test.js @@ -226,7 +226,7 @@ describe('PendingTransactionTracker', function () { it('should emit \'tx:warning\' if it encountered a real error', function (done) { pendingTxTracker.once('tx:warning', (txMeta, err) => { if (err.message === 'im some real error') { - const matchingTx = txList.find(tx => tx.id === txMeta.id) + const matchingTx = txList.find((tx) => tx.id === txMeta.id) matchingTx.resolve() } else { done(err) diff --git a/test/unit/app/controllers/transactions/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js index a973a6093..0284fb376 100644 --- a/test/unit/app/controllers/transactions/tx-controller-test.js +++ b/test/unit/app/controllers/transactions/tx-controller-test.js @@ -683,7 +683,7 @@ describe('Transaction Controller', function () { ]) assert(txController.pendingTxTracker.getPendingTransactions().length, 2) - const states = txController.pendingTxTracker.getPendingTransactions().map(tx => tx.status) + const states = txController.pendingTxTracker.getPendingTransactions().map((tx) => tx.status) assert(states.includes('approved'), 'includes approved') assert(states.includes('submitted'), 'includes submitted') }) diff --git a/test/unit/app/fetch-with-timeout.test.js b/test/unit/app/fetch-with-timeout.test.js index 52b79c338..af25a329c 100644 --- a/test/unit/app/fetch-with-timeout.test.js +++ b/test/unit/app/fetch-with-timeout.test.js @@ -27,7 +27,7 @@ describe('fetchWithTimeout', function () { }) try { - await fetch('https://api.infura.io/moon').then(r => r.json()) + await fetch('https://api.infura.io/moon').then((r) => r.json()) assert.fail('Request should throw') } catch (e) { assert.ok(e) @@ -45,7 +45,7 @@ describe('fetchWithTimeout', function () { }) try { - await fetch('https://api.infura.io/moon').then(r => r.json()) + await fetch('https://api.infura.io/moon').then((r) => r.json()) assert.fail('Request should be aborted') } catch (e) { assert.deepEqual(e.message, 'Aborted') diff --git a/test/unit/migrations/031-test.js b/test/unit/migrations/031-test.js index 8b040aed9..5c9f7d20b 100644 --- a/test/unit/migrations/031-test.js +++ b/test/unit/migrations/031-test.js @@ -24,7 +24,7 @@ describe('migration #31', function () { } migration31.migrate(oldStorage) - .then(newStorage => { + .then((newStorage) => { assert.equal(newStorage.data.PreferencesController.completedOnboarding, true) done() }) @@ -47,7 +47,7 @@ describe('migration #31', function () { } migration31.migrate(oldStorage) - .then(newStorage => { + .then((newStorage) => { assert.equal(newStorage.data.PreferencesController.completedOnboarding, false) done() }) diff --git a/test/unit/migrations/033-test.js b/test/unit/migrations/033-test.js index 3e6065724..4456a7e4a 100644 --- a/test/unit/migrations/033-test.js +++ b/test/unit/migrations/033-test.js @@ -33,7 +33,7 @@ describe('Migration to delete notice controller', function () { it('removes notice controller from state', function () { migration33.migrate(oldStorage) - .then(newStorage => { + .then((newStorage) => { assert.equal(newStorage.data.NoticeController, undefined) }) }) diff --git a/test/unit/migrations/migrator-test.js b/test/unit/migrations/migrator-test.js index 959ad60be..4823234f4 100644 --- a/test/unit/migrations/migrator-test.js +++ b/test/unit/migrations/migrator-test.js @@ -44,7 +44,7 @@ const firstTimeState = { describe('migrations', function () { describe('liveMigrations require list', function () { it('should include all the migrations', async function () { - const fileNames = await pify(cb => fs.readdir('./app/scripts/migrations/', cb))() + const fileNames = await pify((cb) => fs.readdir('./app/scripts/migrations/', cb))() const migrationNumbers = fileNames.reduce((agg, filename) => { const name = filename.split('.')[0] if (/^\d+$/.test(name)) { diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js index b2d8ba26a..22fc53b6e 100644 --- a/test/unit/ui/app/actions.spec.js +++ b/test/unit/ui/app/actions.spec.js @@ -119,7 +119,7 @@ describe('Actions', function () { const unlockFailedError = [ { type: 'UNLOCK_FAILED', value: 'error' } ] verifySeedPhraseSpy = sinon.stub(background, 'verifySeedPhrase') - verifySeedPhraseSpy.callsFake(callback => { + verifySeedPhraseSpy.callsFake((callback) => { callback(new Error('error')) }) @@ -128,8 +128,8 @@ describe('Actions', function () { assert.fail('Should have thrown error') } catch (_) { const actions1 = store.getActions() - const warning = actions1.filter(action => action.type === 'DISPLAY_WARNING') - const unlockFailed = actions1.filter(action => action.type === 'UNLOCK_FAILED') + const warning = actions1.filter((action) => action.type === 'DISPLAY_WARNING') + const unlockFailed = actions1.filter((action) => action.type === 'UNLOCK_FAILED') assert.deepEqual(warning, displayWarningError) assert.deepEqual(unlockFailed, unlockFailedError) } @@ -245,7 +245,7 @@ describe('Actions', function () { assert(removeAccountSpy.calledOnce) const actionTypes = store .getActions() - .map(action => action.type) + .map((action) => action.type) assert.deepEqual(actionTypes, expectedActions) }) @@ -269,7 +269,7 @@ describe('Actions', function () { } catch (_) { const actionTypes = store .getActions() - .map(action => action.type) + .map((action) => action.type) assert.deepEqual(actionTypes, expectedActions) } @@ -995,7 +995,7 @@ describe('Actions', function () { { type: 'LOCK_METAMASK' }, ] backgroundSetLockedSpy = sinon.stub(background, 'setLocked') - backgroundSetLockedSpy.callsFake(callback => { + backgroundSetLockedSpy.callsFake((callback) => { callback(new Error('error')) }) @@ -1375,7 +1375,7 @@ describe('Actions', function () { describe('#setCompletedOnboarding', function () { it('completes onboarding', async function () { const completeOnboardingSpy = sinon.stub(background, 'completeOnboarding') - completeOnboardingSpy.callsFake(cb => cb()) + completeOnboardingSpy.callsFake((cb) => cb()) const store = mockStore() await store.dispatch(actions.setCompletedOnboarding()) assert.equal(completeOnboardingSpy.callCount, 1) diff --git a/test/web3/web3.js b/test/web3/web3.js index 590a5d990..49898044d 100644 --- a/test/web3/web3.js +++ b/test/web3/web3.js @@ -4,12 +4,12 @@ const json = methods web3.currentProvider.enable().then(() => { - Object.keys(json).forEach(methodGroupKey => { + Object.keys(json).forEach((methodGroupKey) => { console.log(methodGroupKey) const methodGroup = json[methodGroupKey] console.log(methodGroup) - Object.keys(methodGroup).forEach(methodKey => { + Object.keys(methodGroup).forEach((methodKey) => { const methodButton = document.getElementById(methodKey) methodButton.addEventListener('click', () => { diff --git a/ui/app/components/app/account-menu/account-menu.component.js b/ui/app/components/app/account-menu/account-menu.component.js index b249ee179..fb9ac9ac6 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/app/components/app/account-menu/account-menu.component.js @@ -103,7 +103,7 @@ export default class AccountMenu extends Component { placeholder={this.context.t('searchAccounts')} type="text" value={this.state.searchQuery} - onChange={e => this.setSearchQuery(e.target.value)} + onChange={(e) => this.setSearchQuery(e.target.value)} startAdornment={inputAdornment} fullWidth theme="material-white-padded" @@ -133,12 +133,12 @@ export default class AccountMenu extends Component { return

    {this.context.t('noAccountsFound')}

    } - return filteredIdentities.map(identity => { + return filteredIdentities.map((identity) => { const isSelected = identity.address === selectedAddress const simpleAddress = identity.address.substring(2).toLowerCase() - const keyring = keyrings.find(kr => { + const keyring = keyrings.find((kr) => { return kr.accounts.includes(simpleAddress) || kr.accounts.includes(identity.address) }) const addressDomains = addressConnectedDomainMap[identity.address] || {} @@ -210,7 +210,7 @@ export default class AccountMenu extends Component { > this.removeAccount(e, identity)} + onClick={(e) => this.removeAccount(e, identity)} /> ) @@ -275,7 +275,7 @@ export default class AccountMenu extends Component { onScroll = debounce(this.setShouldShowScrollButton, 25) - handleScrollDown = e => { + handleScrollDown = (e) => { e.stopPropagation() const { scrollHeight } = this.accountsRef @@ -336,7 +336,7 @@ export default class AccountMenu extends Component {
    { + ref={(ref) => { this.accountsRef = ref }} > diff --git a/ui/app/components/app/account-menu/account-menu.container.js b/ui/app/components/app/account-menu/account-menu.container.js index 7bc62603e..68f330972 100644 --- a/ui/app/components/app/account-menu/account-menu.container.js +++ b/ui/app/components/app/account-menu/account-menu.container.js @@ -53,7 +53,7 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { toggleAccountMenu: () => dispatch(toggleAccountMenu()), - showAccountDetail: address => { + showAccountDetail: (address) => { dispatch(showAccountDetail(address)) dispatch(hideSidebar()) dispatch(toggleAccountMenu()) @@ -64,7 +64,7 @@ function mapDispatchToProps (dispatch) { dispatch(hideSidebar()) dispatch(toggleAccountMenu()) }, - showRemoveAccountConfirmationModal: identity => { + showRemoveAccountConfirmationModal: (identity) => { return dispatch(showModal({ name: 'CONFIRM_REMOVE_ACCOUNT', identity })) }, } diff --git a/ui/app/components/app/app-header/app-header.component.js b/ui/app/components/app/app-header/app-header.component.js index 533cb09f4..b4c4fa992 100644 --- a/ui/app/components/app/app-header/app-header.component.js +++ b/ui/app/components/app/app-header/app-header.component.js @@ -103,7 +103,7 @@ export default class AppHeader extends PureComponent { this.handleNetworkIndicatorClick(event)} + onClick={(event) => this.handleNetworkIndicatorClick(event)} disabled={disabled} />
    diff --git a/ui/app/components/app/app-header/app-header.container.js b/ui/app/components/app/app-header/app-header.container.js index 861d30989..28d9a796d 100644 --- a/ui/app/components/app/app-header/app-header.container.js +++ b/ui/app/components/app/app-header/app-header.container.js @@ -5,7 +5,7 @@ import { compose } from 'recompose' import AppHeader from './app-header.component' import * as actions from '../../../store/actions' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { appState, metamask } = state const { networkDropdownOpen } = appState const { @@ -26,7 +26,7 @@ const mapStateToProps = state => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { showNetworkDropdown: () => dispatch(actions.showNetworkDropdown()), hideNetworkDropdown: () => dispatch(actions.hideNetworkDropdown()), diff --git a/ui/app/components/app/app-header/tests/app-header.test.js b/ui/app/components/app/app-header/tests/app-header.test.js index f63567e95..a788e1053 100644 --- a/ui/app/components/app/app-header/tests/app-header.test.js +++ b/ui/app/components/app/app-header/tests/app-header.test.js @@ -29,7 +29,7 @@ describe('App Header', function () { wrapper = shallow( , { context: { - t: str => str, + t: (str) => str, metricsEvent: () => {}, }, } diff --git a/ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js b/ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js index 18571eccb..d4b6cee68 100644 --- a/ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js @@ -4,7 +4,7 @@ import classnames from 'classnames' import UserPreferencedCurrencyDisplay from '../../user-preferenced-currency-display' import { PRIMARY, SECONDARY } from '../../../../helpers/constants/common' -const ConfirmDetailRow = props => { +const ConfirmDetailRow = (props) => { const { label, primaryText, diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js index b973ad84d..85cbc0076 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import classnames from 'classnames' import Identicon from '../../../../ui/identicon' -const ConfirmPageContainerSummary = props => { +const ConfirmPageContainerSummary = (props) => { const { action, title, diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/confirm-page-container-warning.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/confirm-page-container-warning.component.js index 79901c8fc..8865fb976 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/confirm-page-container-warning.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/confirm-page-container-warning.component.js @@ -1,7 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' -const ConfirmPageContainerWarning = props => { +const ConfirmPageContainerWarning = (props) => { return (
    { +const ConfirmPageContainerNavigation = (props) => { const { onNextTx, totalTx, positionOfCurrentTx, nextTxId, prevTxId, showNavigation, firstTx, lastTx, ofText, requestsWaitingText } = props return ( diff --git a/ui/app/components/app/connected-sites-list/connected-sites-list.container.js b/ui/app/components/app/connected-sites-list/connected-sites-list.container.js index 1058152e1..6bbc5be5b 100644 --- a/ui/app/components/app/connected-sites-list/connected-sites-list.container.js +++ b/ui/app/components/app/connected-sites-list/connected-sites-list.container.js @@ -14,7 +14,7 @@ import { } from '../../../selectors/selectors' import { getOriginFromUrl } from '../../../helpers/utils/util' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const addressConnectedToCurrentTab = getAddressConnectedToCurrentTab(state) const { openMetaMaskTabs } = state.appState const { title, url, id } = state.activeTab @@ -36,7 +36,7 @@ const mapStateToProps = state => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { showDisconnectAccountModal: (domainKey, domain) => { dispatch(showModal({ name: 'DISCONNECT_ACCOUNT', domainKey, domain })) diff --git a/ui/app/components/app/dropdowns/network-dropdown.js b/ui/app/components/app/dropdowns/network-dropdown.js index 99c9a7ec4..6825c8a16 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.js +++ b/ui/app/components/app/dropdowns/network-dropdown.js @@ -39,7 +39,7 @@ function mapDispatchToProps (dispatch) { dispatch(actions.delRpcTarget(target)) }, hideNetworkDropdown: () => dispatch(actions.hideNetworkDropdown()), - setNetworksTabAddMode: isInAddMode => dispatch(actions.setNetworksTabAddMode(isInAddMode)), + setNetworksTabAddMode: (isInAddMode) => dispatch(actions.setNetworksTabAddMode(isInAddMode)), } } @@ -216,7 +216,7 @@ class NetworkDropdown extends Component { isOpen={isOpen} onClickOutside={(event) => { const { classList } = event.target - const isInClassList = className => classList.contains(className) + const isInClassList = (className) => classList.contains(className) const notToggleElementIndex = R.findIndex(isInClassList)(notToggleElementClassnames) if (notToggleElementIndex === -1) { diff --git a/ui/app/components/app/dropdowns/simple-dropdown.js b/ui/app/components/app/dropdowns/simple-dropdown.js index 5d764b374..06cf3c631 100644 --- a/ui/app/components/app/dropdowns/simple-dropdown.js +++ b/ui/app/components/app/dropdowns/simple-dropdown.js @@ -17,7 +17,7 @@ class SimpleDropdown extends Component { getDisplayValue () { const { selectedOption, options } = this.props - const matchesOption = option => option.value === selectedOption + const matchesOption = (option) => option.value === selectedOption const matchingOption = R.find(matchesOption)(options) return matchingOption ? matchingOption.displayValue || matchingOption.value @@ -41,7 +41,7 @@ class SimpleDropdown extends Component {
    { + onClick={(event) => { event.stopPropagation() this.handleClose() }} diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js b/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js index 6b547abc6..61c73bcf1 100644 --- a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js +++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js @@ -15,7 +15,7 @@ function convertGasLimitForInputs (gasLimitInHexWEI) { return parseInt(gasLimitInHexWEI, 16) || 0 } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { showGasPriceInfoModal: () => dispatch(showModal({ name: 'GAS_PRICE_INFO_MODAL' })), showGasLimitInfoModal: () => dispatch(showModal({ name: 'GAS_LIMIT_INFO_MODAL' })), diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js b/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js index 2da1911ea..b28da6615 100644 --- a/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js +++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js @@ -27,7 +27,7 @@ describe('Advanced Gas Inputs', function () { {...props} />, { context: { - t: str => str, + t: (str) => str, }, }) }) diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js index 87dbf73a7..2e2e8dab5 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js @@ -32,7 +32,7 @@ const mockGasPriceButtonGroupProps = { gasEstimateType: GAS_ESTIMATE_TYPES.AVERAGE, }, ], - handleGasPriceSelection: newPrice => console.log('NewPrice: ', newPrice), + handleGasPriceSelection: (newPrice) => console.log('NewPrice: ', newPrice), noButtonActiveByDefault: true, showCheck: true, } diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js index b02778754..65a35101d 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js @@ -49,10 +49,10 @@ export default class GasModalPageContainer extends Component { const promise = this.props.hideBasic ? Promise.resolve(this.props.blockTime) : this.props.fetchBasicGasAndTimeEstimates() - .then(basicEstimates => basicEstimates.blockTime) + .then((basicEstimates) => basicEstimates.blockTime) promise - .then(blockTime => { + .then((blockTime) => { this.props.fetchGasEstimates(blockTime) }) } diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js index 530996b9d..1b530fe85 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js @@ -165,8 +165,8 @@ const mapStateToProps = (state, ownProps) => { } } -const mapDispatchToProps = dispatch => { - const updateCustomGasPrice = newPrice => dispatch(setCustomGasPrice(addHexPrefix(newPrice))) +const mapDispatchToProps = (dispatch) => { + const updateCustomGasPrice = (newPrice) => dispatch(setCustomGasPrice(addHexPrefix(newPrice))) return { cancelAndClose: () => { @@ -175,7 +175,7 @@ const mapDispatchToProps = dispatch => { }, hideModal: () => dispatch(hideModal()), updateCustomGasPrice, - updateCustomGasLimit: newLimit => dispatch(setCustomGasLimit(addHexPrefix(newLimit))), + updateCustomGasLimit: (newLimit) => dispatch(setCustomGasLimit(addHexPrefix(newLimit))), setGasData: (newLimit, newPrice) => { dispatch(setGasLimit(newLimit)) dispatch(setGasPrice(newPrice)) diff --git a/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js b/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js index 02f018995..ad98b61a6 100644 --- a/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js +++ b/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js @@ -261,7 +261,7 @@ export function generateChart (gasPrices, estimatedTimes, gasPricesMax, estimate contents: function (d) { const titleFormat = this.config.tooltip_format_title let text - d.forEach(el => { + d.forEach((el) => { if (el && (el.value || el.value === 0) && !text) { text = "" + "' } diff --git a/ui/app/components/app/gas-customization/gas-slider/gas-slider.component.js b/ui/app/components/app/gas-customization/gas-slider/gas-slider.component.js index 629d81f0e..1e072d300 100644 --- a/ui/app/components/app/gas-customization/gas-slider/gas-slider.component.js +++ b/ui/app/components/app/gas-customization/gas-slider/gas-slider.component.js @@ -33,7 +33,7 @@ export default class GasSlider extends Component { min={min} value={value} id="gasSlider" - onChange={event => onChange(event.target.value)} + onChange={(event) => onChange(event.target.value)} />
    diff --git a/ui/app/components/app/loading-network-screen/loading-network-screen.container.js b/ui/app/components/app/loading-network-screen/loading-network-screen.container.js index f33a12e56..d17ce67a8 100644 --- a/ui/app/components/app/loading-network-screen/loading-network-screen.container.js +++ b/ui/app/components/app/loading-network-screen/loading-network-screen.container.js @@ -3,7 +3,7 @@ import LoadingNetworkScreen from './loading-network-screen.component' import * as actions from '../../../store/actions' import { getNetworkIdentifier } from '../../../selectors/selectors' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { loadingMessage, } = state.appState @@ -28,7 +28,7 @@ const mapStateToProps = state => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { setProviderType: (type) => { dispatch(actions.setProviderType(type)) diff --git a/ui/app/components/app/menu-bar/menu-bar.container.js b/ui/app/components/app/menu-bar/menu-bar.container.js index 059263ff3..30455e28c 100644 --- a/ui/app/components/app/menu-bar/menu-bar.container.js +++ b/ui/app/components/app/menu-bar/menu-bar.container.js @@ -3,7 +3,7 @@ import { WALLET_VIEW_SIDEBAR } from '../sidebars/sidebar.constants' import MenuBar from './menu-bar.component' import { showSidebar, hideSidebar } from '../../../store/actions' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { appState: { sidebar: { isOpen } } } = state return { @@ -11,7 +11,7 @@ const mapStateToProps = state => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { showSidebar: () => { dispatch(showSidebar({ diff --git a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js index d47401fb6..1c46d792b 100644 --- a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js +++ b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js @@ -46,7 +46,7 @@ export default class AccountDetailsModal extends Component { setAccountLabel(address, label)} + onSubmit={(label) => setAccountLabel(address, label)} /> { + onChange = (e) => { this.setState({ alias: e.target.value, }) } - onKeyPress = e => { + onKeyPress = (e) => { if (e.key === 'Enter' && this.state.alias) { this.onSave() } diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.container.js b/ui/app/components/app/modals/cancel-transaction/cancel-transaction.container.js index 6959889d9..bed72119a 100644 --- a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.container.js +++ b/ui/app/components/app/modals/cancel-transaction/cancel-transaction.container.js @@ -33,7 +33,7 @@ const mapStateToProps = (state, ownProps) => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { createCancelTransaction: (txId, customGasPrice) => { return dispatch(createCancelTransaction(txId, customGasPrice)) diff --git a/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js b/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js index 5991c6ca0..faa917db3 100644 --- a/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js +++ b/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js @@ -7,7 +7,7 @@ import CancelTransactionGasFee from '../cancel-transaction-gas-fee' import Modal from '../../../modal' describe('CancelTransaction Component', function () { - const t = key => key + const t = (key) => key it('should render a CancelTransaction modal', function () { const wrapper = shallow( diff --git a/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js b/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js index 4c9bb279f..6df902572 100644 --- a/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js +++ b/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js @@ -4,7 +4,7 @@ import withModalProps from '../../../../helpers/higher-order-components/with-mod import ConfirmDeleteNetwork from './confirm-delete-network.component' import { delRpcTarget } from '../../../../store/actions' -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { delRpcTarget: (target) => dispatch(delRpcTarget(target)), } diff --git a/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js b/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js index 390d5bb53..77e8b3faa 100644 --- a/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js +++ b/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js @@ -18,7 +18,7 @@ describe('Confirm Delete Network', function () { wrapper = mount( , { context: { - t: str => str, + t: (str) => str, }, } ) diff --git a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js b/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js index 0a3cda5b6..6434899a2 100644 --- a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js +++ b/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js @@ -4,13 +4,13 @@ import ConfirmRemoveAccount from './confirm-remove-account.component' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' import { removeAccount } from '../../../../store/actions' -const mapStateToProps = state => { +const mapStateToProps = (state) => { return { network: state.metamask.network, } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { removeAccount: (address) => dispatch(removeAccount(address)), } diff --git a/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js b/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js index 8be07d0d1..417923628 100644 --- a/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js +++ b/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js @@ -37,7 +37,7 @@ describe('Confirm Remove Account', function () { , { context: { - t: str => str, + t: (str) => str, store, }, childContextTypes: { diff --git a/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.container.js b/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.container.js index ffbd40d9d..b870f191c 100644 --- a/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.container.js +++ b/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.container.js @@ -4,7 +4,7 @@ import withModalProps from '../../../../helpers/higher-order-components/with-mod import ConfirmResetAccount from './confirm-reset-account.component' import { resetAccount } from '../../../../store/actions' -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { resetAccount: () => dispatch(resetAccount()), } diff --git a/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js b/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js index 46ec14050..fdb268e63 100644 --- a/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js +++ b/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js @@ -16,7 +16,7 @@ describe('Confirm Reset Account', function () { wrapper = mount( , { context: { - t: str => str, + t: (str) => str, }, } ) diff --git a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js index 1e6715ef8..5e074e56f 100644 --- a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js +++ b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js @@ -79,7 +79,7 @@ export default class DepositEtherModal extends Component { render () { const { network, toWyre, toCoinSwitch, address, toFaucet } = this.props - const isTestNetwork = ['3', '4', '5', '42'].find(n => n === network) + const isTestNetwork = ['3', '4', '5', '42'].find((n) => n === network) const networkName = getNetworkDisplayName(network) return ( diff --git a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js index cccbe7667..31f10eff9 100644 --- a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js +++ b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js @@ -26,7 +26,7 @@ function mapDispatchToProps (dispatch) { showAccountDetailModal: () => { dispatch(showModal({ name: 'ACCOUNT_DETAILS' })) }, - toFaucet: network => dispatch(buyEth({ network })), + toFaucet: (network) => dispatch(buyEth({ network })), } } diff --git a/ui/app/components/app/modals/disconnect-account/disconnect-account.container.js b/ui/app/components/app/modals/disconnect-account/disconnect-account.container.js index ca26bd95f..c0b406d8e 100644 --- a/ui/app/components/app/modals/disconnect-account/disconnect-account.container.js +++ b/ui/app/components/app/modals/disconnect-account/disconnect-account.container.js @@ -5,17 +5,17 @@ import DisconnectAccount from './disconnect-account.component' import { getCurrentAccountWithSendEtherInfo } from '../../../../selectors/selectors' import { removePermissionsFor } from '../../../../store/actions' -const mapStateToProps = state => { +const mapStateToProps = (state) => { return { ...(state.appState.modal.modalState.props || {}), accountLabel: getCurrentAccountWithSendEtherInfo(state).name, } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { disconnectAccount: (domainKey, domain) => { - const permissionMethodNames = domain.permissions.map(perm => perm.parentCapability) + const permissionMethodNames = domain.permissions.map((perm) => perm.parentCapability) dispatch(removePermissionsFor({ [domainKey]: permissionMethodNames })) }, } diff --git a/ui/app/components/app/modals/disconnect-all/disconnect-all.container.js b/ui/app/components/app/modals/disconnect-all/disconnect-all.container.js index 2415c3fa9..fe733a5b1 100644 --- a/ui/app/components/app/modals/disconnect-all/disconnect-all.container.js +++ b/ui/app/components/app/modals/disconnect-all/disconnect-all.container.js @@ -5,7 +5,7 @@ import withModalProps from '../../../../helpers/higher-order-components/with-mod import DisconnectAll from './disconnect-all.component' import { clearPermissions } from '../../../../store/actions' -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { disconnectAll: () => { dispatch(clearPermissions()) diff --git a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js index 76dbb92dd..695762b73 100644 --- a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js +++ b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js @@ -38,7 +38,7 @@ export default class ExportPrivateKeyModal extends Component { const { exportAccount } = this.props exportAccount(password, address) - .then(privateKey => this.setState({ + .then((privateKey) => this.setState({ privateKey, showWarning: false, })) @@ -65,7 +65,7 @@ export default class ExportPrivateKeyModal extends Component { this.setState({ password: event.target.value })} + onChange={(event) => this.setState({ password: event.target.value })} /> ) } diff --git a/ui/app/components/app/modals/fade-modal.js b/ui/app/components/app/modals/fade-modal.js index 3f9269a2f..d4cad7615 100644 --- a/ui/app/components/app/modals/fade-modal.js +++ b/ui/app/components/app/modals/fade-modal.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types' let index = 0 let extraSheet -const insertRule = css => { +const insertRule = (css) => { if (!extraSheet) { // First time, create an extra stylesheet for adding rules @@ -20,7 +20,7 @@ const insertRule = css => { return extraSheet } -const insertKeyframesRule = keyframes => { +const insertKeyframesRule = (keyframes) => { // random name const name = 'anim_' + (++index) + (+new Date()) let css = '@' + 'keyframes ' + name + ' {' @@ -212,7 +212,7 @@ class FadeModal extends Component {
    (this.content = el)} + ref={(el) => (this.content = el)} tabIndex="-1" style={contentStyle} > diff --git a/ui/app/components/app/modals/hide-token-confirmation-modal.js b/ui/app/components/app/modals/hide-token-confirmation-modal.js index e70e0c877..fdd452b35 100644 --- a/ui/app/components/app/modals/hide-token-confirmation-modal.js +++ b/ui/app/components/app/modals/hide-token-confirmation-modal.js @@ -15,7 +15,7 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { hideModal: () => dispatch(actions.hideModal()), - hideToken: address => { + hideToken: (address) => { dispatch(actions.removeToken(address)) .then(() => { dispatch(actions.hideModal()) diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js b/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js index ea7d71a73..6ac78ff56 100644 --- a/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js +++ b/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js @@ -12,7 +12,7 @@ const mapStateToProps = (_, ownProps) => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { setParticipateInMetaMetrics: (val) => dispatch(setParticipateInMetaMetrics(val)), } diff --git a/ui/app/components/app/modals/new-account-modal/new-account-modal.component.js b/ui/app/components/app/modals/new-account-modal/new-account-modal.component.js index 26224ae63..01940cbc0 100644 --- a/ui/app/components/app/modals/new-account-modal/new-account-modal.component.js +++ b/ui/app/components/app/modals/new-account-modal/new-account-modal.component.js @@ -18,7 +18,7 @@ export default class NewAccountModal extends Component { alias: '', } - onChange = e => { + onChange = (e) => { this.setState({ alias: e.target.value, }) @@ -29,7 +29,7 @@ export default class NewAccountModal extends Component { .then(this.props.hideModal) } - onKeyPress = e => { + onKeyPress = (e) => { if (e.key === 'Enter' && this.state.alias) { this.onSubmit() } diff --git a/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js b/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js index f4ebac86c..adda14d37 100644 --- a/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js +++ b/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js @@ -11,9 +11,9 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { hideModal: () => dispatch(actions.hideModal()), - createAccount: newAccountName => { + createAccount: (newAccountName) => { return dispatch(actions.addNewAccount()) - .then(newAccountAddress => { + .then((newAccountAddress) => { if (newAccountName) { dispatch(actions.setAccountLabel(newAccountAddress, newAccountName)) } @@ -36,7 +36,7 @@ function mergeProps (stateProps, dispatchProps) { ...dispatchProps, onSave: (newAccountName) => { return createAccount(newAccountName) - .then(newAccountAddress => onCreateNewAccount(newAccountAddress)) + .then((newAccountAddress) => onCreateNewAccount(newAccountAddress)) }, } } diff --git a/ui/app/components/app/modals/notification-modal.js b/ui/app/components/app/modals/notification-modal.js index b31367636..7fe776934 100644 --- a/ui/app/components/app/modals/notification-modal.js +++ b/ui/app/components/app/modals/notification-modal.js @@ -72,7 +72,7 @@ NotificationModal.propTypes = { onConfirm: PropTypes.func, } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { hideModal: () => { dispatch(hideModal()) diff --git a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js b/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js index 0bd4ac79a..63ca45b88 100644 --- a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js +++ b/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js @@ -85,7 +85,7 @@ export default class QrScanner extends Component { const { permissions } = await WebcamUtils.checkStatus() if (permissions) { // Let the video stream load first... - await new Promise(resolve => setTimeout(resolve, 2000)) + await new Promise((resolve) => setTimeout(resolve, 2000)) if (!this.mounted) { return } diff --git a/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js b/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js index 2de4aeb73..b7fce7523 100644 --- a/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js +++ b/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js @@ -3,7 +3,7 @@ import QrScanner from './qr-scanner.component' import { hideModal, qrCodeDetected } from '../../../../store/actions' -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { hideModal: () => dispatch(hideModal()), qrCodeDetected: (data) => dispatch(qrCodeDetected(data)), diff --git a/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js b/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js index eac74c474..fb8deb65d 100644 --- a/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js +++ b/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js @@ -17,7 +17,7 @@ describe('Reject Transactions Model', function () { wrapper = mount( , { context: { - t: str => str, + t: (str) => str, }, } ) diff --git a/ui/app/components/app/modals/tests/account-details-modal.test.js b/ui/app/components/app/modals/tests/account-details-modal.test.js index b00b1418e..db0e4094f 100644 --- a/ui/app/components/app/modals/tests/account-details-modal.test.js +++ b/ui/app/components/app/modals/tests/account-details-modal.test.js @@ -40,7 +40,7 @@ describe('Account Details Modal', function () { wrapper = shallow( , { context: { - t: str => str, + t: (str) => str, }, } ) diff --git a/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js b/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js index 529e0cdbc..222fff8f4 100644 --- a/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js +++ b/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js @@ -13,7 +13,7 @@ describe('Transaction Confirmed', function () { const wrapper = mount( , { context: { - t: str => str, + t: (str) => str, }, } ) diff --git a/ui/app/components/app/multiple-notifications/multiple-notifications.component.js b/ui/app/components/app/multiple-notifications/multiple-notifications.component.js index 59f540045..410bef6a9 100644 --- a/ui/app/components/app/multiple-notifications/multiple-notifications.component.js +++ b/ui/app/components/app/multiple-notifications/multiple-notifications.component.js @@ -21,7 +21,7 @@ export default class MultipleNotifications extends PureComponent { const { showAll } = this.state const { children, classNames } = this.props - const childrenToRender = children.filter(child => child) + const childrenToRender = children.filter((child) => child) if (childrenToRender.length === 0) { return null } diff --git a/ui/app/components/app/permission-page-container/permission-page-container.component.js b/ui/app/components/app/permission-page-container/permission-page-container.component.js index bb5afac9e..35e111ba2 100644 --- a/ui/app/components/app/permission-page-container/permission-page-container.component.js +++ b/ui/app/components/app/permission-page-container/permission-page-container.component.js @@ -62,7 +62,7 @@ export default class PermissionPageContainer extends Component { return Object.keys(props.request.permissions || {}) } - onPermissionToggle = methodName => { + onPermissionToggle = (methodName) => { this.setState({ selectedPermissions: { ...this.state.selectedPermissions, @@ -96,7 +96,7 @@ export default class PermissionPageContainer extends Component { permissions: { ..._request.permissions }, } - Object.keys(this.state.selectedPermissions).forEach(key => { + Object.keys(this.state.selectedPermissions).forEach((key) => { if (!this.state.selectedPermissions[key]) { delete request.permissions[key] } diff --git a/ui/app/components/app/selected-account/selected-account.container.js b/ui/app/components/app/selected-account/selected-account.container.js index afa113117..4ec23f5e6 100644 --- a/ui/app/components/app/selected-account/selected-account.container.js +++ b/ui/app/components/app/selected-account/selected-account.container.js @@ -3,7 +3,7 @@ import SelectedAccount from './selected-account.component' import { getSelectedAddress, getSelectedIdentity } from '../../../selectors/selectors' -const mapStateToProps = state => { +const mapStateToProps = (state) => { return { selectedAddress: getSelectedAddress(state), selectedIdentity: getSelectedIdentity(state), diff --git a/ui/app/components/app/signature-request-original/signature-request-original.component.js b/ui/app/components/app/signature-request-original/signature-request-original.component.js index 775245539..7a08e36a1 100644 --- a/ui/app/components/app/signature-request-original/signature-request-original.component.js +++ b/ui/app/components/app/signature-request-original/signature-request-original.component.js @@ -272,7 +272,7 @@ export default class SignatureRequestOriginal extends Component { type="default" large className="request-signature__footer__cancel-button" - onClick={async event => { + onClick={async (event) => { this._removeBeforeUnload() await cancel(event) this.context.metricsEvent({ @@ -292,7 +292,7 @@ export default class SignatureRequestOriginal extends Component { type="secondary" large className="request-signature__footer__sign-button" - onClick={async event => { + onClick={async (event) => { this._removeBeforeUnload() await sign(event) this.context.metricsEvent({ diff --git a/ui/app/components/app/tab-bar.js b/ui/app/components/app/tab-bar.js index e39e80d55..6abd56936 100644 --- a/ui/app/components/app/tab-bar.js +++ b/ui/app/components/app/tab-bar.js @@ -2,7 +2,7 @@ import React from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' -const TabBar = props => { +const TabBar = (props) => { const { tabs = [], onSelect, isActive } = props return ( diff --git a/ui/app/components/app/token-cell/token-cell.container.js b/ui/app/components/app/token-cell/token-cell.container.js index 176e93008..0cc8f106f 100644 --- a/ui/app/components/app/token-cell/token-cell.container.js +++ b/ui/app/components/app/token-cell/token-cell.container.js @@ -17,7 +17,7 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - setSelectedToken: address => dispatch(setSelectedToken(address)), + setSelectedToken: (address) => dispatch(setSelectedToken(address)), hideSidebar: () => dispatch(hideSidebar()), } } diff --git a/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js b/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js index 2f99ca0cb..5bd0fddfc 100644 --- a/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js +++ b/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js @@ -5,13 +5,13 @@ import sinon from 'sinon' import TransactionAction from '../transaction-action.component' describe('TransactionAction Component', function () { - const t = key => key + const t = (key) => key describe('Outgoing transaction', function () { beforeEach(function () { global.eth = { - getCode: sinon.stub().callsFake(address => { + getCode: sinon.stub().callsFake((address) => { const code = address === 'approveAddress' ? 'contract' : '0x' return Promise.resolve(code) }), diff --git a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.container.test.js b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.container.test.js index f071ea96a..6d72794f3 100644 --- a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.container.test.js +++ b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.container.test.js @@ -5,7 +5,7 @@ let mapStateToProps proxyquire('../transaction-activity-log.container.js', { 'react-redux': { - connect: ms => { + connect: (ms) => { mapStateToProps = ms return () => ({}) }, diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.component.js b/ui/app/components/app/transaction-activity-log/transaction-activity-log.component.js index b37d5efa0..24b057b64 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log.component.js +++ b/ui/app/components/app/transaction-activity-log/transaction-activity-log.component.js @@ -26,7 +26,7 @@ export default class TransactionActivityLog extends PureComponent { isEarliestNonce: PropTypes.bool, } - handleActivityClick = hash => { + handleActivityClick = (hash) => { const { primaryTransaction } = this.props const { metamaskNetworkId } = primaryTransaction diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.container.js b/ui/app/components/app/transaction-activity-log/transaction-activity-log.container.js index 11b20f245..a6ecb3617 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log.container.js +++ b/ui/app/components/app/transaction-activity-log/transaction-activity-log.container.js @@ -8,9 +8,9 @@ import { TRANSACTION_CANCEL_ATTEMPTED_EVENT, } from './transaction-activity-log.constants' -const matchesEventKey = matchEventKey => ({ eventKey }) => eventKey === matchEventKey +const matchesEventKey = (matchEventKey) => ({ eventKey }) => eventKey === matchEventKey -const mapStateToProps = state => { +const mapStateToProps = (state) => { return { conversionRate: conversionRateSelector(state), nativeCurrency: getNativeCurrency(state), diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js b/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js index b1ab275ed..3cd1bb785 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js +++ b/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js @@ -86,7 +86,7 @@ export function getActivities (transaction, isFirstTransaction = false) { } else if (Array.isArray(base)) { const events = [] - base.forEach(entry => { + base.forEach((entry) => { const { op, path, value, timestamp: entryTimestamp } = entry // Not all sub-entries in a history entry have a timestamp. If the sub-entry does not have a // timestamp, the first sub-entry in a history entry should. @@ -194,7 +194,7 @@ function filterSortedActivities (activities) { ))) let addedDroppedActivity = false - activities.forEach(activity => { + activities.forEach((activity) => { if (activity.eventKey === TRANSACTION_DROPPED_EVENT) { if (!hasConfirmedActivity && !addedDroppedActivity) { filteredActivities.push(activity) diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js index d193f9fb9..2fece12dc 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js +++ b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js @@ -58,14 +58,14 @@ export default class TransactionListItemDetails extends PureComponent { global.platform.openWindow({ url: getBlockExplorerUrlForTx(metamaskNetworkId, hash, rpcPrefs) }) } - handleCancel = event => { + handleCancel = (event) => { const { transactionGroup: { initialTransaction: { id } = {} } = {}, onCancel } = this.props event.stopPropagation() onCancel(id) } - handleRetry = event => { + handleRetry = (event) => { const { transactionGroup: { initialTransaction: { id } = {} } = {}, onRetry } = this.props event.stopPropagation() diff --git a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js b/ui/app/components/app/transaction-list-item/transaction-list-item.component.js index 8ab08ccad..d89ba1dcb 100644 --- a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js +++ b/ui/app/components/app/transaction-list-item/transaction-list-item.component.js @@ -90,7 +90,7 @@ export default class TransactionListItem extends PureComponent { this.setState({ showTransactionDetails: !showTransactionDetails }) } - handleCancel = id => { + handleCancel = (id) => { const { primaryTransaction: { txParams: { gasPrice } } = {}, transaction: { id: initialTransactionId }, @@ -108,7 +108,7 @@ export default class TransactionListItem extends PureComponent { * transaction. * @param {number} id - Transaction id */ - handleRetry = id => { + handleRetry = (id) => { const { primaryTransaction: { txParams: { gasPrice } } = {}, transaction: { txParams: { to } = {}, id: initialTransactionId }, @@ -134,7 +134,7 @@ export default class TransactionListItem extends PureComponent { }) return fetchBasicGasAndTimeEstimates() - .then(basicEstimates => fetchGasEstimates(basicEstimates.blockTime)) + .then((basicEstimates) => fetchGasEstimates(basicEstimates.blockTime)) .then(retryTransaction(retryId, gasPrice)) } diff --git a/ui/app/components/app/transaction-list-item/transaction-list-item.container.js b/ui/app/components/app/transaction-list-item/transaction-list-item.container.js index 26ccec1f7..9569040bb 100644 --- a/ui/app/components/app/transaction-list-item/transaction-list-item.container.js +++ b/ui/app/components/app/transaction-list-item/transaction-list-item.container.js @@ -32,7 +32,7 @@ const mapStateToProps = (state, ownProps) => { const selectedAddress = getSelectedAddress(state) const selectedAccountBalance = accounts[selectedAddress].balance const isDeposit = transactionCategory === 'incoming' - const selectRpcInfo = frequentRpcListDetail.find(rpcInfo => rpcInfo.rpcUrl === provider.rpcTarget) + const selectRpcInfo = frequentRpcListDetail.find((rpcInfo) => rpcInfo.rpcUrl === provider.rpcTarget) const { rpcPrefs } = selectRpcInfo || {} const hasEnoughCancelGas = primaryTransaction.txParams && isBalanceSufficient({ @@ -58,12 +58,12 @@ const mapStateToProps = (state, ownProps) => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { fetchBasicGasAndTimeEstimates: () => dispatch(fetchBasicGasAndTimeEstimates()), fetchGasEstimates: (blockTime) => dispatch(fetchGasEstimates(blockTime)), - setSelectedToken: tokenAddress => dispatch(setSelectedToken(tokenAddress)), - getContractMethodData: methodData => dispatch(getContractMethodData(methodData)), + setSelectedToken: (tokenAddress) => dispatch(setSelectedToken(tokenAddress)), + getContractMethodData: (methodData) => dispatch(getContractMethodData(methodData)), retryTransaction: (transaction, gasPrice) => { dispatch(setCustomGasPriceForRetry(gasPrice || transaction.txParams.gasPrice)) dispatch(setCustomGasLimit(transaction.txParams.gas)) @@ -100,7 +100,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { primaryTransaction, retryTransaction: (transactionId, gasPrice) => { const { transactionGroup: { transactions = [] } } = ownProps - const transaction = transactions.find(tx => tx.id === transactionId) || {} + const transaction = transactions.find((tx) => tx.id === transactionId) || {} const increasedGasPrice = increaseLastGasPrice(gasPrice) retryTransaction(transaction, increasedGasPrice) }, diff --git a/ui/app/components/app/transaction-list/transaction-list.container.js b/ui/app/components/app/transaction-list/transaction-list.container.js index 0695c28c2..a6f08603f 100644 --- a/ui/app/components/app/transaction-list/transaction-list.container.js +++ b/ui/app/components/app/transaction-list/transaction-list.container.js @@ -23,9 +23,9 @@ const mapStateToProps = (state) => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { - updateNetworkNonce: address => dispatch(updateNetworkNonce(address)), + updateNetworkNonce: (address) => dispatch(updateNetworkNonce(address)), fetchGasEstimates: (blockTime) => dispatch(fetchGasEstimates(blockTime)), fetchBasicGasAndTimeEstimates: () => dispatch(fetchBasicGasAndTimeEstimates()), } diff --git a/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js b/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js index f37bebb6f..510950248 100644 --- a/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js +++ b/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js @@ -11,7 +11,7 @@ describe('TransactionStatus Component', function () { statusKey="approved" title="test-title" />, - { context: { t: str => str.toUpperCase() } } + { context: { t: (str) => str.toUpperCase() } } ) assert.ok(wrapper) @@ -24,7 +24,7 @@ describe('TransactionStatus Component', function () { , - { context: { t: str => str.toUpperCase() } } + { context: { t: (str) => str.toUpperCase() } } ) assert.ok(wrapper) diff --git a/ui/app/components/app/transaction-view-balance/transaction-view-balance.container.js b/ui/app/components/app/transaction-view-balance/transaction-view-balance.container.js index 41a4525dc..b85e9d0fe 100644 --- a/ui/app/components/app/transaction-view-balance/transaction-view-balance.container.js +++ b/ui/app/components/app/transaction-view-balance/transaction-view-balance.container.js @@ -14,7 +14,7 @@ import { } from '../../../selectors/selectors' import { showModal } from '../../../store/actions' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { showFiatInTestnets } = preferencesSelector(state) const isMainnet = getIsMainnet(state) const selectedAddress = getSelectedAddress(state) @@ -34,7 +34,7 @@ const mapStateToProps = state => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { showDepositModal: () => dispatch(showModal({ name: 'DEPOSIT_ETHER' })), } diff --git a/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.container.test.js b/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.container.test.js index b4bbdf109..84c67f453 100644 --- a/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.container.test.js +++ b/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.container.test.js @@ -5,7 +5,7 @@ let mapStateToProps proxyquire('../user-preferenced-currency-input.container.js', { 'react-redux': { - connect: ms => { + connect: (ms) => { mapStateToProps = ms return () => ({}) }, diff --git a/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js b/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js index 72f17fde4..4f3795c6d 100644 --- a/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js +++ b/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux' import UserPreferencedCurrencyInput from './user-preferenced-currency-input.component' import { preferencesSelector } from '../../../selectors/selectors' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { useNativeCurrencyAsPrimaryCurrency } = preferencesSelector(state) return { diff --git a/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.container.test.js b/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.container.test.js index fac111fd8..f7bef30e4 100644 --- a/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.container.test.js +++ b/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.container.test.js @@ -5,7 +5,7 @@ let mapStateToProps proxyquire('../user-preferenced-token-input.container.js', { 'react-redux': { - connect: ms => { + connect: (ms) => { mapStateToProps = ms return () => ({}) }, diff --git a/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js b/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js index 4a20b20d9..6263928ba 100644 --- a/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js +++ b/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux' import UserPreferencedTokenInput from './user-preferenced-token-input.component' import { preferencesSelector } from '../../../selectors/selectors' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { useNativeCurrencyAsPrimaryCurrency } = preferencesSelector(state) return { diff --git a/ui/app/components/ui/alert/index.js b/ui/app/components/ui/alert/index.js index 707ac7a3a..3bc1b4581 100644 --- a/ui/app/components/ui/alert/index.js +++ b/ui/app/components/ui/alert/index.js @@ -31,7 +31,7 @@ class Alert extends Component { className: 'hidden', }) - setTimeout(_ => { + setTimeout((_) => { this.setState({ visible: false }) }, 500) diff --git a/ui/app/components/ui/balance/balance.container.js b/ui/app/components/ui/balance/balance.container.js index 2ad5c5ad8..997935ee7 100644 --- a/ui/app/components/ui/balance/balance.container.js +++ b/ui/app/components/ui/balance/balance.container.js @@ -10,7 +10,7 @@ import { preferencesSelector, } from '../../../selectors/selectors' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { showFiatInTestnets } = preferencesSelector(state) const isMainnet = getIsMainnet(state) const accounts = getMetaMaskAccounts(state) diff --git a/ui/app/components/ui/button-group/tests/button-group-component.test.js b/ui/app/components/ui/button-group/tests/button-group-component.test.js index 5e304bc7c..755b0789d 100644 --- a/ui/app/components/ui/button-group/tests/button-group-component.test.js +++ b/ui/app/components/ui/button-group/tests/button-group-component.test.js @@ -92,7 +92,7 @@ describe('ButtonGroup Component', function () { it('should render all child buttons as disabled if props.disabled is true', function () { const childButtons = wrapper.find('.button-group__button') - childButtons.forEach(button => { + childButtons.forEach((button) => { assert.equal(button.props().disabled, undefined) }) wrapper.setProps({ disabled: true }) diff --git a/ui/app/components/ui/currency-display/currency-display.container.js b/ui/app/components/ui/currency-display/currency-display.container.js index 803c11f68..30055e31b 100644 --- a/ui/app/components/ui/currency-display/currency-display.container.js +++ b/ui/app/components/ui/currency-display/currency-display.container.js @@ -4,7 +4,7 @@ import CurrencyDisplay from './currency-display.component' import { getValueFromWeiHex, formatCurrency } from '../../../helpers/utils/confirm-tx.util' import { GWEI } from '../../../helpers/constants/common' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { metamask: { nativeCurrency, currentCurrency, conversionRate } } = state return { diff --git a/ui/app/components/ui/currency-input/currency-input.component.js b/ui/app/components/ui/currency-input/currency-input.component.js index 398b49884..f17fb5792 100644 --- a/ui/app/components/ui/currency-input/currency-input.component.js +++ b/ui/app/components/ui/currency-input/currency-input.component.js @@ -83,7 +83,7 @@ export default class CurrencyInput extends PureComponent { }) } - handleChange = decimalValue => { + handleChange = (decimalValue) => { const { currentCurrency: fromCurrency, conversionRate, onChange } = this.props const hexValue = this.shouldUseFiat() diff --git a/ui/app/components/ui/currency-input/currency-input.container.js b/ui/app/components/ui/currency-input/currency-input.container.js index 0c76d6ce5..64a8d96b4 100644 --- a/ui/app/components/ui/currency-input/currency-input.container.js +++ b/ui/app/components/ui/currency-input/currency-input.container.js @@ -4,7 +4,7 @@ import { ETH } from '../../../helpers/constants/common' import { getMaxModeOn } from '../../../pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.selectors' import { getIsMainnet, preferencesSelector } from '../../../selectors/selectors' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { metamask: { nativeCurrency, currentCurrency, conversionRate } } = state const { showFiatInTestnets } = preferencesSelector(state) const isMainnet = getIsMainnet(state) diff --git a/ui/app/components/ui/currency-input/tests/currency-input.component.test.js b/ui/app/components/ui/currency-input/tests/currency-input.component.test.js index 471cb9f6b..7f8e54dbe 100644 --- a/ui/app/components/ui/currency-input/tests/currency-input.component.test.js +++ b/ui/app/components/ui/currency-input/tests/currency-input.component.test.js @@ -137,7 +137,7 @@ describe('CurrencyInput Component', function () { /> , { - context: { t: str => str + '_t' }, + context: { t: (str) => str + '_t' }, childContextTypes: { t: PropTypes.func }, } ) diff --git a/ui/app/components/ui/editable-label.js b/ui/app/components/ui/editable-label.js index bf1f290d0..553965b1c 100644 --- a/ui/app/components/ui/editable-label.js +++ b/ui/app/components/ui/editable-label.js @@ -40,7 +40,7 @@ class EditableLabel extends Component { this.handleSubmit() } }} - onChange={event => this.setState({ value: event.target.value })} + onChange={(event) => this.setState({ value: event.target.value })} className={classnames('large-input', 'editable-label__input', { 'editable-label__input--error': value === '', })} diff --git a/ui/app/components/ui/error-message/tests/error-message.component.test.js b/ui/app/components/ui/error-message/tests/error-message.component.test.js index 40e77161b..2f13b24eb 100644 --- a/ui/app/components/ui/error-message/tests/error-message.component.test.js +++ b/ui/app/components/ui/error-message/tests/error-message.component.test.js @@ -4,7 +4,7 @@ import { shallow } from 'enzyme' import ErrorMessage from '../error-message.component' describe('ErrorMessage Component', function () { - const t = key => `translate ${key}` + const t = (key) => `translate ${key}` it('should render a message from props.errorMessage', function () { const wrapper = shallow( diff --git a/ui/app/components/ui/identicon/identicon.component.js b/ui/app/components/ui/identicon/identicon.component.js index 913b8d493..5fed06304 100644 --- a/ui/app/components/ui/identicon/identicon.component.js +++ b/ui/app/components/ui/identicon/identicon.component.js @@ -7,7 +7,7 @@ import BlockieIdenticon from './blockieIdenticon' import { checksumAddress } from '../../../helpers/utils/util' import Jazzicon from '../jazzicon' -const getStyles = diameter => ( +const getStyles = (diameter) => ( { height: diameter, width: diameter, diff --git a/ui/app/components/ui/identicon/identicon.container.js b/ui/app/components/ui/identicon/identicon.container.js index bc49bc18e..8565a2df2 100644 --- a/ui/app/components/ui/identicon/identicon.container.js +++ b/ui/app/components/ui/identicon/identicon.container.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' import Identicon from './identicon.component' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { metamask: { useBlockie } } = state return { diff --git a/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js b/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js index 7927c20d8..b9c0b554a 100644 --- a/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js +++ b/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js @@ -44,7 +44,7 @@ export default class PageContainerFooter extends Component { type={cancelButtonType || 'default'} large={buttonSizeLarge} className="page-container__footer-button" - onClick={e => onCancel(e)} + onClick={(e) => onCancel(e)} data-testid="page-container-footer-cancel" > { cancelText || this.context.t('cancel') } @@ -56,7 +56,7 @@ export default class PageContainerFooter extends Component { large={buttonSizeLarge} className="page-container__footer-button" disabled={disabled} - onClick={e => onSubmit(e)} + onClick={(e) => onSubmit(e)} data-testid="page-container-footer-next" > { submitText || this.context.t('next') } diff --git a/ui/app/components/ui/page-container/page-container.component.js b/ui/app/components/ui/page-container/page-container.component.js index 45dfff517..8ea9aa6b0 100644 --- a/ui/app/components/ui/page-container/page-container.component.js +++ b/ui/app/components/ui/page-container/page-container.component.js @@ -48,7 +48,7 @@ export default class PageContainer extends PureComponent { return React.Children.map(tabsComponent.props.children, (child, tabIndex) => { return child && React.cloneElement(child, { - onClick: index => this.handleTabClick(index), + onClick: (index) => this.handleTabClick(index), tabIndex, isActive: numberOfTabs > 1 && tabIndex === this.state.activeTabIndex, key: tabIndex, @@ -61,7 +61,7 @@ export default class PageContainer extends PureComponent { renderActiveTabContent () { const { tabsComponent } = this.props let { children } = tabsComponent.props - children = children.filter(child => child) + children = children.filter((child) => child) const { activeTabIndex } = this.state return children[activeTabIndex] diff --git a/ui/app/components/ui/readonly-input.js b/ui/app/components/ui/readonly-input.js index f78c48027..b884da1bc 100644 --- a/ui/app/components/ui/readonly-input.js +++ b/ui/app/components/ui/readonly-input.js @@ -18,7 +18,7 @@ export default function ReadOnlyInput (props) { className={inputClass} value={value} readOnly - onFocus={event => event.target.select()} + onFocus={(event) => event.target.select()} onClick={onClick} />
    diff --git a/ui/app/components/ui/tabs/tab/tab.component.js b/ui/app/components/ui/tabs/tab/tab.component.js index 9e590391c..d01f3a591 100644 --- a/ui/app/components/ui/tabs/tab/tab.component.js +++ b/ui/app/components/ui/tabs/tab/tab.component.js @@ -2,7 +2,7 @@ import React from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' -const Tab = props => { +const Tab = (props) => { const { name, onClick, isActive, tabIndex, className, activeClassName } = props return ( @@ -11,7 +11,7 @@ const Tab = props => { className, { [activeClassName]: isActive }, )} - onClick={event => { + onClick={(event) => { event.preventDefault() onClick(tabIndex) }} diff --git a/ui/app/components/ui/tabs/tabs.component.js b/ui/app/components/ui/tabs/tabs.component.js index 7d8230189..383332ac9 100644 --- a/ui/app/components/ui/tabs/tabs.component.js +++ b/ui/app/components/ui/tabs/tabs.component.js @@ -30,7 +30,7 @@ export default class Tabs extends Component { return React.Children.map(this.props.children, (child, index) => { return child && React.cloneElement(child, { - onClick: index => this.handleTabClick(index), + onClick: (index) => this.handleTabClick(index), tabIndex: index, isActive: numberOfTabs > 1 && index === this.state.activeTabIndex, key: index, diff --git a/ui/app/components/ui/toggle-button/toggle-button.component.js b/ui/app/components/ui/toggle-button/toggle-button.component.js index 3f13203a5..38ffb27fd 100644 --- a/ui/app/components/ui/toggle-button/toggle-button.component.js +++ b/ui/app/components/ui/toggle-button/toggle-button.component.js @@ -45,7 +45,7 @@ const colors = { }, } -const ToggleButton = props => { +const ToggleButton = (props) => { const { value, onToggle, offLabel, onLabel } = props return ( diff --git a/ui/app/components/ui/token-balance/token-balance.container.js b/ui/app/components/ui/token-balance/token-balance.container.js index 6425f89d9..6198bcc5c 100644 --- a/ui/app/components/ui/token-balance/token-balance.container.js +++ b/ui/app/components/ui/token-balance/token-balance.container.js @@ -4,7 +4,7 @@ import withTokenTracker from '../../../helpers/higher-order-components/with-toke import TokenBalance from './token-balance.component' import { getSelectedAddress } from '../../../selectors/selectors' -const mapStateToProps = state => { +const mapStateToProps = (state) => { return { userAddress: getSelectedAddress(state), } diff --git a/ui/app/components/ui/token-input/tests/token-input.component.test.js b/ui/app/components/ui/token-input/tests/token-input.component.test.js index 75f400c90..3cf121bdb 100644 --- a/ui/app/components/ui/token-input/tests/token-input.component.test.js +++ b/ui/app/components/ui/token-input/tests/token-input.component.test.js @@ -10,7 +10,7 @@ import UnitInput from '../../unit-input' import CurrencyDisplay from '../../currency-display' describe('TokenInput Component', function () { - const t = key => `translate ${key}` + const t = (key) => `translate ${key}` describe('rendering', function () { it('should render properly without a token', function () { diff --git a/ui/app/components/ui/token-input/token-input.component.js b/ui/app/components/ui/token-input/token-input.component.js index aed6c7d3f..c7c025658 100644 --- a/ui/app/components/ui/token-input/token-input.component.js +++ b/ui/app/components/ui/token-input/token-input.component.js @@ -66,7 +66,7 @@ export default class TokenInput extends PureComponent { return Number(decimalValueString) ? decimalValueString : '' } - handleChange = decimalValue => { + handleChange = (decimalValue) => { const { selectedToken: { decimals } = {}, onChange } = this.props const multiplier = Math.pow(10, Number(decimals || 0)) diff --git a/ui/app/components/ui/token-input/token-input.container.js b/ui/app/components/ui/token-input/token-input.container.js index 8c867e8e6..7d614f7c4 100644 --- a/ui/app/components/ui/token-input/token-input.container.js +++ b/ui/app/components/ui/token-input/token-input.container.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux' import TokenInput from './token-input.component' import { getIsMainnet, getSelectedToken, getSelectedTokenExchangeRate, preferencesSelector } from '../../../selectors/selectors' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { metamask: { currentCurrency } } = state const { showFiatInTestnets } = preferencesSelector(state) const isMainnet = getIsMainnet(state) diff --git a/ui/app/components/ui/unit-input/unit-input.component.js b/ui/app/components/ui/unit-input/unit-input.component.js index 83170ec24..d2368291f 100644 --- a/ui/app/components/ui/unit-input/unit-input.component.js +++ b/ui/app/components/ui/unit-input/unit-input.component.js @@ -43,7 +43,7 @@ export default class UnitInput extends PureComponent { this.unitInput.focus() } - handleChange = event => { + handleChange = (event) => { const { value: userInput } = event.target let value = userInput @@ -81,7 +81,7 @@ export default class UnitInput extends PureComponent { placeholder={placeholder} onChange={this.handleChange} style={{ width: this.getInputWidth(value) }} - ref={ref => { + ref={(ref) => { this.unitInput = ref }} disabled={maxModeOn} diff --git a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js index e05445441..150ac1d06 100644 --- a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js +++ b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js @@ -24,7 +24,7 @@ import { conversionUtil } from '../../helpers/utils/conversion-util' import { addHexPrefix } from 'ethereumjs-util' // Actions -const createActionType = action => `metamask/confirm-transaction/${action}` +const createActionType = (action) => `metamask/confirm-transaction/${action}` const UPDATE_TX_DATA = createActionType('UPDATE_TX_DATA') const CLEAR_TX_DATA = createActionType('CLEAR_TX_DATA') diff --git a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js index ca59ca14c..606e989d6 100644 --- a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js +++ b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js @@ -482,7 +482,7 @@ describe('Confirm Transaction Duck', function () { beforeEach(function () { global.eth = { getCode: sinon.stub().callsFake( - address => Promise.resolve(address && address.match(/isContract/) ? 'not-0x' : '0x') + (address) => Promise.resolve(address && address.match(/isContract/) ? 'not-0x' : '0x') ), } }) diff --git a/ui/app/ducks/gas/gas-duck.test.js b/ui/app/ducks/gas/gas-duck.test.js index 8583d61db..87db1e423 100644 --- a/ui/app/ducks/gas/gas-duck.test.js +++ b/ui/app/ducks/gas/gas-duck.test.js @@ -66,12 +66,12 @@ describe('Gas Duck', function () { { expectedTime: 1.1, expectedWait: 0.6, gasprice: 19.9, somethingElse: 'foobar' }, { expectedTime: 1, expectedWait: 0.5, gasprice: 20, somethingElse: 'foobar' }, ] - const fakeFetch = (url) => new Promise(resolve => { + const fakeFetch = (url) => new Promise((resolve) => { const dataToResolve = url.match(/ethgasAPI/) ? mockEthGasApiResponse : mockPredictTableResponse resolve({ - json: () => new Promise(resolve => resolve(dataToResolve)), + json: () => new Promise((resolve) => resolve(dataToResolve)), }) }) @@ -648,7 +648,7 @@ describe('Gas Duck', function () { const { type: thirdDispatchCallType, value: priceAndTimeEstimateResult } = mockDistpatch.getCall(2).args[0] assert.equal(thirdDispatchCallType, SET_PRICE_AND_TIME_ESTIMATES) assert(priceAndTimeEstimateResult.length < mockPredictTableResponse.length * 3 - 2) - assert(!priceAndTimeEstimateResult.find(d => d.expectedTime > 100)) + assert(!priceAndTimeEstimateResult.find((d) => d.expectedTime > 100)) assert(!priceAndTimeEstimateResult.find((d, _, a) => a[a + 1] && d.expectedTime > a[a + 1].expectedTime)) assert(!priceAndTimeEstimateResult.find((d, _, a) => a[a + 1] && d.gasprice > a[a + 1].gasprice)) diff --git a/ui/app/ducks/gas/gas.duck.js b/ui/app/ducks/gas/gas.duck.js index 13a0fc5a1..36148ecc0 100644 --- a/ui/app/ducks/gas/gas.duck.js +++ b/ui/app/ducks/gas/gas.duck.js @@ -218,7 +218,7 @@ async function fetchExternalBasicGasEstimates (dispatch) { fastTimes10, fastestTimes10, safeLowTimes10, - ].map(price => (new BigNumber(price)).div(10).toNumber()) + ].map((price) => (new BigNumber(price)).div(10).toNumber()) const basicEstimates = { safeLow, @@ -286,7 +286,7 @@ async function fetchExternalBasicGasAndTimeEstimates (dispatch) { fastTimes10, fastestTimes10, safeLowTimes10, - ].map(price => (new BigNumber(price)).div(10).toNumber()) + ].map((price) => (new BigNumber(price)).div(10).toNumber()) const basicEstimates = { average, @@ -350,11 +350,11 @@ function quartiles (data) { } function inliersByIQR (data, prop) { - const { lowerQuartile, upperQuartile } = quartiles(data.map(d => (prop ? d[prop] : d))) + const { lowerQuartile, upperQuartile } = quartiles(data.map((d) => (prop ? d[prop] : d))) const IQR = upperQuartile - lowerQuartile const lowerBound = lowerQuartile - 1.5 * IQR const upperBound = upperQuartile + 1.5 * IQR - return data.filter(d => { + return data.filter((d) => { const value = prop ? d[prop] : d return value >= lowerBound && value <= upperBound }) @@ -385,8 +385,8 @@ export function fetchGasEstimates (blockTime) { 'method': 'GET', 'mode': 'cors' } ) - .then(r => r.json()) - .then(r => { + .then((r) => r.json()) + .then((r) => { const estimatedPricesAndTimes = r.map(({ expectedTime, expectedWait, gasprice }) => ({ expectedTime, expectedWait, gasprice })) const estimatedTimeWithUniquePrices = uniqBy(({ expectedTime }) => expectedTime, estimatedPricesAndTimes) @@ -439,7 +439,7 @@ export function fetchGasEstimates (blockTime) { : loadLocalStorageData('GAS_API_ESTIMATES') ) - return promiseToFetch.then(estimates => { + return promiseToFetch.then((estimates) => { dispatch(setPricesAndTimeEstimates(estimates)) dispatch(gasEstimatesLoadingFinished()) }) diff --git a/ui/app/ducks/metamask/metamask.js b/ui/app/ducks/metamask/metamask.js index ce2b52a85..26ebb8761 100644 --- a/ui/app/ducks/metamask/metamask.js +++ b/ui/app/ducks/metamask/metamask.js @@ -280,7 +280,7 @@ export default function reduceMetamask (state = {}, action) { case actions.UPDATE_TRANSACTION_PARAMS: const { id: txId, value } = action let { selectedAddressTxList } = metamaskState - selectedAddressTxList = selectedAddressTxList.map(tx => { + selectedAddressTxList = selectedAddressTxList.map((tx) => { if (tx.id === txId) { const newTx = Object.assign({}, tx) newTx.txParams = value diff --git a/ui/app/helpers/higher-order-components/authenticated/authenticated.container.js b/ui/app/helpers/higher-order-components/authenticated/authenticated.container.js index 8fc637332..3b67b2cfe 100644 --- a/ui/app/helpers/higher-order-components/authenticated/authenticated.container.js +++ b/ui/app/helpers/higher-order-components/authenticated/authenticated.container.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' import Authenticated from './authenticated.component' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { metamask: { isUnlocked, completedOnboarding } } = state return { diff --git a/ui/app/helpers/higher-order-components/i18n-provider.js b/ui/app/helpers/higher-order-components/i18n-provider.js index 3add2ad85..56a55d95b 100644 --- a/ui/app/helpers/higher-order-components/i18n-provider.js +++ b/ui/app/helpers/higher-order-components/i18n-provider.js @@ -49,7 +49,7 @@ I18nProvider.childContextTypes = { tOrKey: PropTypes.func, } -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { localeMessages, metamask: { currentLocale } } = state return { currentLocale, diff --git a/ui/app/helpers/higher-order-components/initialized/initialized.container.js b/ui/app/helpers/higher-order-components/initialized/initialized.container.js index 0e7f72bcb..245655962 100644 --- a/ui/app/helpers/higher-order-components/initialized/initialized.container.js +++ b/ui/app/helpers/higher-order-components/initialized/initialized.container.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' import Initialized from './initialized.component' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { metamask: { completedOnboarding } } = state return { diff --git a/ui/app/helpers/higher-order-components/metametrics/metametrics.provider.js b/ui/app/helpers/higher-order-components/metametrics/metametrics.provider.js index 5383b9a28..1cc0cfdcb 100644 --- a/ui/app/helpers/higher-order-components/metametrics/metametrics.provider.js +++ b/ui/app/helpers/higher-order-components/metametrics/metametrics.provider.js @@ -103,7 +103,7 @@ class MetaMetricsProvider extends Component { } } -const mapStateToProps = state => { +const mapStateToProps = (state) => { const txData = txDataSelector(state) || {} return { diff --git a/ui/app/helpers/higher-order-components/with-modal-props/with-modal-props.js b/ui/app/helpers/higher-order-components/with-modal-props/with-modal-props.js index aac6b5a61..b702ff24f 100644 --- a/ui/app/helpers/higher-order-components/with-modal-props/with-modal-props.js +++ b/ui/app/helpers/higher-order-components/with-modal-props/with-modal-props.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' import { hideModal } from '../../../store/actions' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { appState } = state const { props: modalProps } = appState.modal.modalState @@ -10,7 +10,7 @@ const mapStateToProps = state => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { hideModal: () => dispatch(hideModal()), } diff --git a/ui/app/helpers/higher-order-components/with-token-tracker/with-token-tracker.component.js b/ui/app/helpers/higher-order-components/with-token-tracker/with-token-tracker.component.js index 838401421..06c5006c8 100644 --- a/ui/app/helpers/higher-order-components/with-token-tracker/with-token-tracker.component.js +++ b/ui/app/helpers/higher-order-components/with-token-tracker/with-token-tracker.component.js @@ -62,10 +62,10 @@ export default function withTokenTracker (WrappedComponent) { this.tracker.updateBalances() .then(() => this.updateBalance(this.tracker.serialize())) - .catch(error => this.setState({ error: error.message })) + .catch((error) => this.setState({ error: error.message })) } - setError = error => { + setError = (error) => { this.setState({ error }) } diff --git a/ui/app/helpers/utils/common.util.js b/ui/app/helpers/utils/common.util.js index 0c02481e6..a45fdc407 100644 --- a/ui/app/helpers/utils/common.util.js +++ b/ui/app/helpers/utils/common.util.js @@ -1,5 +1,5 @@ export function camelCaseToCapitalize (str = '') { return str .replace(/([A-Z])/g, ' $1') - .replace(/^./, str => str.toUpperCase()) + .replace(/^./, (str) => str.toUpperCase()) } diff --git a/ui/app/helpers/utils/confirm-tx.util.js b/ui/app/helpers/utils/confirm-tx.util.js index 853427b31..0895cf7b0 100644 --- a/ui/app/helpers/utils/confirm-tx.util.js +++ b/ui/app/helpers/utils/confirm-tx.util.js @@ -94,7 +94,7 @@ export function getTransactionFee ({ export function formatCurrency (value, currencyCode) { const upperCaseCurrencyCode = currencyCode.toUpperCase() - return currencies.find(currency => currency.code === upperCaseCurrencyCode) + return currencies.find((currency) => currency.code === upperCaseCurrencyCode) ? currencyFormatter.format(Number(value), { code: upperCaseCurrencyCode, style: 'currency' }) : value } diff --git a/ui/app/helpers/utils/conversion-util.js b/ui/app/helpers/utils/conversion-util.js index 0c3e42a5d..b65c831af 100644 --- a/ui/app/helpers/utils/conversion-util.js +++ b/ui/app/helpers/utils/conversion-util.js @@ -40,31 +40,31 @@ const BIG_NUMBER_ETH_MULTIPLIER = new BigNumber('1') // Setter Maps const toBigNumber = { - hex: n => new BigNumber(stripHexPrefix(n), 16), - dec: n => new BigNumber(String(n), 10), - BN: n => new BigNumber(n.toString(16), 16), + hex: (n) => new BigNumber(stripHexPrefix(n), 16), + dec: (n) => new BigNumber(String(n), 10), + BN: (n) => new BigNumber(n.toString(16), 16), } const toNormalizedDenomination = { - WEI: bigNumber => bigNumber.div(BIG_NUMBER_WEI_MULTIPLIER), - GWEI: bigNumber => bigNumber.div(BIG_NUMBER_GWEI_MULTIPLIER), - ETH: bigNumber => bigNumber.div(BIG_NUMBER_ETH_MULTIPLIER), + WEI: (bigNumber) => bigNumber.div(BIG_NUMBER_WEI_MULTIPLIER), + GWEI: (bigNumber) => bigNumber.div(BIG_NUMBER_GWEI_MULTIPLIER), + ETH: (bigNumber) => bigNumber.div(BIG_NUMBER_ETH_MULTIPLIER), } const toSpecifiedDenomination = { - WEI: bigNumber => bigNumber.times(BIG_NUMBER_WEI_MULTIPLIER).round(), - GWEI: bigNumber => bigNumber.times(BIG_NUMBER_GWEI_MULTIPLIER).round(9), - ETH: bigNumber => bigNumber.times(BIG_NUMBER_ETH_MULTIPLIER).round(9), + WEI: (bigNumber) => bigNumber.times(BIG_NUMBER_WEI_MULTIPLIER).round(), + GWEI: (bigNumber) => bigNumber.times(BIG_NUMBER_GWEI_MULTIPLIER).round(9), + ETH: (bigNumber) => bigNumber.times(BIG_NUMBER_ETH_MULTIPLIER).round(9), } const baseChange = { - hex: n => n.toString(16), - dec: n => (new BigNumber(n)).toString(10), - BN: n => new BN(n.toString(16)), + hex: (n) => n.toString(16), + dec: (n) => (new BigNumber(n)).toString(10), + BN: (n) => new BN(n.toString(16)), } // Individual Setters const convert = R.invoker(1, 'times') const round = R.invoker(2, 'round')(R.__, BigNumber.ROUND_HALF_DOWN) const roundDown = R.invoker(2, 'round')(R.__, BigNumber.ROUND_DOWN) -const invertConversionRate = conversionRate => () => new BigNumber(1.0).div(conversionRate) +const invertConversionRate = (conversionRate) => () => new BigNumber(1.0).div(conversionRate) const decToBigNumberViaString = () => R.pipe(String, toBigNumber['dec']) // Predicates diff --git a/ui/app/helpers/utils/switch-direction.js b/ui/app/helpers/utils/switch-direction.js index 171ead675..2ccbfbaf0 100644 --- a/ui/app/helpers/utils/switch-direction.js +++ b/ui/app/helpers/utils/switch-direction.js @@ -8,8 +8,8 @@ const switchDirection = async (direction) => { } let updatedLink Array.from(document.getElementsByTagName('link')) - .filter(link => link.rel === 'stylesheet') - .forEach(link => { + .filter((link) => link.rel === 'stylesheet') + .forEach((link) => { if (link.title === direction && link.disabled) { link.disabled = false updatedLink = link diff --git a/ui/app/helpers/utils/token-util.js b/ui/app/helpers/utils/token-util.js index 48e76a5c5..ac34b0882 100644 --- a/ui/app/helpers/utils/token-util.js +++ b/ui/app/helpers/utils/token-util.js @@ -134,11 +134,11 @@ export function calcTokenValue (value, decimals) { } export function getTokenValue (tokenParams = []) { - const valueData = tokenParams.find(param => param.name === '_value') + const valueData = tokenParams.find((param) => param.name === '_value') return valueData && valueData.value } export function getTokenToAddress (tokenParams = []) { - const toAddressData = tokenParams.find(param => param.name === '_to') + const toAddressData = tokenParams.find((param) => param.name === '_to') return toAddressData ? toAddressData.value : tokenParams[0].value } diff --git a/ui/app/pages/add-token/add-token.component.js b/ui/app/pages/add-token/add-token.component.js index 1fa9db909..fcfb4cf8b 100644 --- a/ui/app/pages/add-token/add-token.component.js +++ b/ui/app/pages/add-token/add-token.component.js @@ -49,7 +49,7 @@ class AddToken extends Component { let selectedTokens = {} let customToken = {} - pendingTokenKeys.forEach(tokenAddress => { + pendingTokenKeys.forEach((tokenAddress) => { const token = pendingTokens[tokenAddress] const { isCustom } = token @@ -228,7 +228,7 @@ class AddToken extends Component { label={this.context.t('tokenContractAddress')} type="text" value={customAddress} - onChange={e => this.handleCustomAddressChange(e.target.value)} + onChange={(e) => this.handleCustomAddressChange(e.target.value)} error={customAddressError} fullWidth margin="normal" @@ -252,7 +252,7 @@ class AddToken extends Component { )} type="text" value={customSymbol} - onChange={e => this.handleCustomSymbolChange(e.target.value)} + onChange={(e) => this.handleCustomSymbolChange(e.target.value)} error={customSymbolError} fullWidth margin="normal" @@ -263,7 +263,7 @@ class AddToken extends Component { label={this.context.t('decimal')} type="number" value={customDecimals} - onChange={e => this.handleCustomDecimalsChange(e.target.value)} + onChange={(e) => this.handleCustomDecimalsChange(e.target.value)} error={customDecimalsError} fullWidth margin="normal" @@ -286,7 +286,7 @@ class AddToken extends Component { this.handleToggleToken(token)} + onToggleToken={(token) => this.handleToggleToken(token)} />
    diff --git a/ui/app/pages/add-token/add-token.container.js b/ui/app/pages/add-token/add-token.container.js index 779dcf451..af9334106 100644 --- a/ui/app/pages/add-token/add-token.container.js +++ b/ui/app/pages/add-token/add-token.container.js @@ -12,9 +12,9 @@ const mapStateToProps = ({ metamask }) => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { - setPendingTokens: tokens => dispatch(setPendingTokens(tokens)), + setPendingTokens: (tokens) => dispatch(setPendingTokens(tokens)), clearPendingTokens: () => dispatch(clearPendingTokens()), } } diff --git a/ui/app/pages/add-token/token-search/token-search.component.js b/ui/app/pages/add-token/token-search/token-search.component.js index eee841654..9cb3425b3 100644 --- a/ui/app/pages/add-token/token-search/token-search.component.js +++ b/ui/app/pages/add-token/token-search/token-search.component.js @@ -7,7 +7,7 @@ import TextField from '../../../components/ui/text-field' const contractList = Object.entries(contractMap) .map(([ _, tokenData]) => tokenData) - .filter(tokenData => Boolean(tokenData.erc20)) + .filter((tokenData) => Boolean(tokenData.erc20)) const fuse = new Fuse(contractList, { shouldSort: true, @@ -43,7 +43,7 @@ export default class TokenSearch extends Component { handleSearch (searchQuery) { this.setState({ searchQuery }) const fuseSearchResult = fuse.search(searchQuery) - const addressSearchResult = contractList.filter(token => { + const addressSearchResult = contractList.filter((token) => { return token.address.toLowerCase() === searchQuery.toLowerCase() }) const results = [...addressSearchResult, ...fuseSearchResult] @@ -71,7 +71,7 @@ export default class TokenSearch extends Component { placeholder={this.context.t('searchTokens')} type="text" value={searchQuery} - onChange={e => this.handleSearch(e.target.value)} + onChange={(e) => this.handleSearch(e.target.value)} error={error} fullWidth startAdornment={this.renderAdornment()} diff --git a/ui/app/pages/add-token/util.js b/ui/app/pages/add-token/util.js index 579c56cc0..b0f3bbd4c 100644 --- a/ui/app/pages/add-token/util.js +++ b/ui/app/pages/add-token/util.js @@ -5,7 +5,7 @@ export function checkExistingAddresses (address, tokenList = []) { return false } - const matchesAddress = existingToken => { + const matchesAddress = (existingToken) => { return existingToken.address.toLowerCase() === address.toLowerCase() } diff --git a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js index c3b576f25..040952cde 100644 --- a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js +++ b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js @@ -13,7 +13,7 @@ const mapStateToProps = ({ metamask }) => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { addToken: ({ address, symbol, decimals, image }) => dispatch(addToken(address, symbol, Number(decimals), image)), removeSuggestedTokens: () => dispatch(removeSuggestedTokens()), diff --git a/ui/app/pages/confirm-add-token/confirm-add-token.container.js b/ui/app/pages/confirm-add-token/confirm-add-token.container.js index 43ffd06f6..707d259e2 100644 --- a/ui/app/pages/confirm-add-token/confirm-add-token.container.js +++ b/ui/app/pages/confirm-add-token/confirm-add-token.container.js @@ -10,9 +10,9 @@ const mapStateToProps = ({ metamask }) => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { - addTokens: tokens => dispatch(addTokens(tokens)), + addTokens: (tokens) => dispatch(addTokens(tokens)), clearPendingTokens: () => dispatch(clearPendingTokens()), } } diff --git a/ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.container.js b/ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.container.js index 336ee83ea..e66dd3b60 100644 --- a/ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.container.js +++ b/ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.container.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' import ConfirmDeployContract from './confirm-deploy-contract.component' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { confirmTransaction: { txData } = {} } = state return { diff --git a/ui/app/pages/confirm-send-ether/confirm-send-ether.component.js b/ui/app/pages/confirm-send-ether/confirm-send-ether.component.js index 6bc252dbb..2fd23f45f 100644 --- a/ui/app/pages/confirm-send-ether/confirm-send-ether.component.js +++ b/ui/app/pages/confirm-send-ether/confirm-send-ether.component.js @@ -32,7 +32,7 @@ export default class ConfirmSendEther extends Component { this.handleEdit(confirmTransactionData)} + onEdit={(confirmTransactionData) => this.handleEdit(confirmTransactionData)} /> ) } diff --git a/ui/app/pages/confirm-send-ether/confirm-send-ether.container.js b/ui/app/pages/confirm-send-ether/confirm-send-ether.container.js index 713da702d..45e830d5d 100644 --- a/ui/app/pages/confirm-send-ether/confirm-send-ether.container.js +++ b/ui/app/pages/confirm-send-ether/confirm-send-ether.container.js @@ -5,7 +5,7 @@ import { updateSend } from '../../store/actions' import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck' import ConfirmSendEther from './confirm-send-ether.component' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { confirmTransaction: { txData: { txParams } = {} } } = state return { @@ -13,9 +13,9 @@ const mapStateToProps = state => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { - editTransaction: txData => { + editTransaction: (txData) => { const { id, txParams } = txData const { gas: gasLimit, diff --git a/ui/app/pages/confirm-send-token/confirm-send-token.component.js b/ui/app/pages/confirm-send-token/confirm-send-token.component.js index 361a35540..bde21a41c 100644 --- a/ui/app/pages/confirm-send-token/confirm-send-token.component.js +++ b/ui/app/pages/confirm-send-token/confirm-send-token.component.js @@ -21,7 +21,7 @@ export default class ConfirmSendToken extends Component { return ( this.handleEdit(confirmTransactionData)} + onEdit={(confirmTransactionData) => this.handleEdit(confirmTransactionData)} tokenAmount={tokenAmount} /> ) diff --git a/ui/app/pages/confirm-send-token/confirm-send-token.container.js b/ui/app/pages/confirm-send-token/confirm-send-token.container.js index db9b08c48..4673297b3 100644 --- a/ui/app/pages/confirm-send-token/confirm-send-token.container.js +++ b/ui/app/pages/confirm-send-token/confirm-send-token.container.js @@ -7,7 +7,7 @@ import { setSelectedToken, updateSend, showSendTokenPage } from '../../store/act import { conversionUtil } from '../../helpers/utils/conversion-util' import { sendTokenTokenAmountAndToAddressSelector } from '../../selectors/confirm-transaction' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { tokenAmount } = sendTokenTokenAmountAndToAddressSelector(state) return { @@ -15,7 +15,7 @@ const mapStateToProps = state => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { editTransaction: ({ txData, tokenData, tokenProps }) => { const { txParams: { to: tokenAddress, gas: gasLimit, gasPrice } = {}, id } = txData diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js index 2d6fb7249..3be76e990 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -247,8 +247,8 @@ export default class ConfirmTransactionBase extends Component { {advancedInlineGasShown ? ( updateGasAndCalculate({ ...customGas, gasPrice: newGasPrice })} - updateCustomGasLimit={newGasLimit => updateGasAndCalculate({ ...customGas, gasLimit: newGasLimit })} + updateCustomGasPrice={(newGasPrice) => updateGasAndCalculate({ ...customGas, gasPrice: newGasPrice })} + updateCustomGasLimit={(newGasLimit) => updateGasAndCalculate({ ...customGas, gasLimit: newGasLimit })} customGasPrice={customGas.gasPrice} customGasLimit={customGas.gasLimit} insufficientBalance={insufficientBalance} @@ -491,7 +491,7 @@ export default class ConfirmTransactionBase extends Component { updateCustomNonce('') }) }) - .catch(error => { + .catch((error) => { this.setState({ submitting: false, submitError: error.message, diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js index eb6a8d9c4..4ee38635e 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js @@ -38,7 +38,7 @@ const casedContractMap = Object.keys(contractMap).reduce((acc, base) => { }, {}) let customNonceValue = '' -const customNonceMerge = txData => (customNonceValue ? ({ +const customNonceMerge = (txData) => (customNonceValue ? ({ ...txData, customNonceValue, }) : txData) @@ -110,7 +110,7 @@ const mapStateToProps = (state, ownProps) => { } const currentNetworkUnapprovedTxs = Object.keys(unapprovedTxs) - .filter(key => unapprovedTxs[key].metamaskNetworkId === network) + .filter((key) => unapprovedTxs[key].metamaskNetworkId === network) .reduce((acc, key) => ({ ...acc, [key]: unapprovedTxs[key] }), {}) const unapprovedTxCount = valuesFor(currentNetworkUnapprovedTxs).length @@ -173,12 +173,12 @@ const mapStateToProps = (state, ownProps) => { } } -export const mapDispatchToProps = dispatch => { +export const mapDispatchToProps = (dispatch) => { return { tryReverseResolveAddress: (address) => { return dispatch(tryReverseResolveAddress(address)) }, - updateCustomNonce: value => { + updateCustomNonce: (value) => { customNonceValue = value dispatch(updateCustomNonce(value)) }, @@ -197,8 +197,8 @@ export const mapDispatchToProps = dispatch => { }, cancelTransaction: ({ id }) => dispatch(cancelTx({ id })), cancelAllTransactions: (txList) => dispatch(cancelTxs(txList)), - sendTransaction: txData => dispatch(updateAndApproveTx(customNonceMerge(txData))), - setMetaMetricsSendCount: val => dispatch(setMetaMetricsSendCount(val)), + sendTransaction: (txData) => dispatch(updateAndApproveTx(customNonceMerge(txData))), + setMetaMetricsSendCount: (val) => dispatch(setMetaMetricsSendCount(val)), getNextNonce: () => dispatch(getNextNonce()), } } @@ -264,7 +264,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { ...ownProps, showCustomizeGasModal: () => dispatchShowCustomizeGasModal({ txData, - onSubmit: customGas => dispatchUpdateGasAndCalculate(customGas), + onSubmit: (customGas) => dispatchUpdateGasAndCalculate(customGas), validate: validateEditGas, }), cancelAllTransactions: () => dispatchCancelAllTransactions(valuesFor(unapprovedTxs)), diff --git a/ui/app/pages/confirm-transaction/confirm-transaction.container.js b/ui/app/pages/confirm-transaction/confirm-transaction.container.js index d59a9d14e..402ea8a28 100644 --- a/ui/app/pages/confirm-transaction/confirm-transaction.container.js +++ b/ui/app/pages/confirm-transaction/confirm-transaction.container.js @@ -53,9 +53,9 @@ const mapStateToProps = (state, ownProps) => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { - setTransactionToConfirm: transactionId => { + setTransactionToConfirm: (transactionId) => { dispatch(setTransactionToConfirm(transactionId)) }, clearConfirmTransaction: () => dispatch(clearConfirmTransaction()), diff --git a/ui/app/pages/create-account/connect-hardware/connect-screen.js b/ui/app/pages/create-account/connect-hardware/connect-screen.js index 9edad9000..3464c43eb 100644 --- a/ui/app/pages/create-account/connect-hardware/connect-screen.js +++ b/ui/app/pages/create-account/connect-hardware/connect-screen.js @@ -30,7 +30,7 @@ class ConnectScreen extends Component { className={classnames('hw-connect__btn', { 'selected': this.state.selectedDevice === 'trezor', })} - onClick={_ => this.setState({ selectedDevice: 'trezor' })} + onClick={(_) => this.setState({ selectedDevice: 'trezor' })} > this.setState({ selectedDevice: 'ledger' })} + onClick={(_) => this.setState({ selectedDevice: 'ledger' })} > { + ref={(node) => { this.referenceNode = node }} > diff --git a/ui/app/pages/create-account/connect-hardware/index.js b/ui/app/pages/create-account/connect-hardware/index.js index 85c95d8d0..e5bf531fb 100644 --- a/ui/app/pages/create-account/connect-hardware/index.js +++ b/ui/app/pages/create-account/connect-hardware/index.js @@ -20,7 +20,7 @@ class ConnectHardwareForm extends Component { UNSAFE_componentWillReceiveProps (nextProps) { const { accounts } = nextProps - const newAccounts = this.state.accounts.map(a => { + const newAccounts = this.state.accounts.map((a) => { const normalizedAddress = a.address.toLowerCase() const balanceValue = accounts[normalizedAddress] && accounts[normalizedAddress].balance || null a.balance = balanceValue ? formatBalance(balanceValue, 6) : '...' @@ -35,7 +35,7 @@ class ConnectHardwareForm extends Component { } async checkIfUnlocked () { - ['trezor', 'ledger'].forEach(async device => { + ['trezor', 'ledger'].forEach(async (device) => { const unlocked = await this.props.checkHardwareStatus(device, this.props.defaultHdPaths[device]) if (unlocked) { this.setState({ unlocked: true }) @@ -69,7 +69,7 @@ class ConnectHardwareForm extends Component { showTemporaryAlert () { this.props.showAlert(this.context.t('hardwareWalletConnected')) // Autohide the alert after 5 seconds - setTimeout(_ => { + setTimeout((_) => { this.props.hideAlert() }, 5000) } @@ -77,7 +77,7 @@ class ConnectHardwareForm extends Component { getPage = (device, page, hdPath) => { this.props .connectHardware(device, page, hdPath) - .then(accounts => { + .then((accounts) => { if (accounts.length) { // If we just loaded the accounts for the first time @@ -95,13 +95,13 @@ class ConnectHardwareForm extends Component { } }) // If the page doesn't contain the selected account, let's deselect it - } else if (!accounts.filter(a => a.index.toString() === this.state.selectedAccount).length) { + } else if (!accounts.filter((a) => a.index.toString() === this.state.selectedAccount).length) { newState.selectedAccount = null } // Map accounts with balances - newState.accounts = accounts.map(account => { + newState.accounts = accounts.map((account) => { const normalizedAddress = account.address.toLowerCase() const balanceValue = this.props.accounts[normalizedAddress] && this.props.accounts[normalizedAddress].balance || null account.balance = balanceValue ? formatBalance(balanceValue, 6) : '...' @@ -111,7 +111,7 @@ class ConnectHardwareForm extends Component { this.setState(newState) } }) - .catch(e => { + .catch((e) => { const errorMessage = e.message if (errorMessage === 'Window blocked') { this.setState({ browserSupported: false, error: null }) @@ -123,14 +123,14 @@ class ConnectHardwareForm extends Component { onForgetDevice = (device) => { this.props.forgetDevice(device) - .then(_ => { + .then((_) => { this.setState({ error: null, selectedAccount: null, accounts: [], unlocked: false, }) - }).catch(e => { + }).catch((e) => { this.setState({ error: e.message }) }) } @@ -142,7 +142,7 @@ class ConnectHardwareForm extends Component { } this.props.unlockHardwareWalletAccount(this.state.selectedAccount, device) - .then(_ => { + .then((_) => { this.context.metricsEvent({ eventOpts: { category: 'Accounts', @@ -151,7 +151,7 @@ class ConnectHardwareForm extends Component { }, }) this.props.history.push(DEFAULT_ROUTE) - }).catch(e => { + }).catch((e) => { this.context.metricsEvent({ eventOpts: { category: 'Accounts', @@ -236,7 +236,7 @@ ConnectHardwareForm.propTypes = { defaultHdPaths: PropTypes.object, } -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { metamask: { network, selectedAddress }, } = state @@ -253,7 +253,7 @@ const mapStateToProps = state => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { setHardwareWalletDefaultHdPath: ({ device, path }) => { return dispatch(actions.setHardwareWalletDefaultHdPath({ device, path })) diff --git a/ui/app/pages/create-account/create-account.component.js b/ui/app/pages/create-account/create-account.component.js index a1617daa3..d532a78eb 100644 --- a/ui/app/pages/create-account/create-account.component.js +++ b/ui/app/pages/create-account/create-account.component.js @@ -14,7 +14,7 @@ import { export default class CreateAccountPage extends Component { renderTabs () { const { history, location: { pathname } } = this.props - const getClassNames = path => classnames('new-account__tabs__tab', { + const getClassNames = (path) => classnames('new-account__tabs__tab', { 'new-account__tabs__selected': matchPath(pathname, { path, exact: true, diff --git a/ui/app/pages/create-account/import-account/json.js b/ui/app/pages/create-account/import-account/json.js index 11af1b17d..c072fa563 100644 --- a/ui/app/pages/create-account/import-account/json.js +++ b/ui/app/pages/create-account/import-account/json.js @@ -123,7 +123,7 @@ class JsonImportSubview extends Component { setSelectedAddress(firstAddress) } }) - .catch(err => err && displayWarning(err.message || err)) + .catch((err) => err && displayWarning(err.message || err)) } checkInputEmpty () { @@ -145,17 +145,17 @@ JsonImportSubview.propTypes = { setSelectedAddress: PropTypes.func, } -const mapStateToProps = state => { +const mapStateToProps = (state) => { return { error: state.appState.warning, firstAddress: Object.keys(getMetaMaskAccounts(state))[0], } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { - displayWarning: warning => dispatch(actions.displayWarning(warning)), - importNewJsonAccount: options => dispatch(actions.importNewAccount('JSON File', options)), + displayWarning: (warning) => dispatch(actions.displayWarning(warning)), + importNewJsonAccount: (options) => dispatch(actions.importNewAccount('JSON File', options)), setSelectedAddress: (address) => dispatch(actions.setSelectedAddress(address)), } } diff --git a/ui/app/pages/create-account/import-account/private-key.js b/ui/app/pages/create-account/import-account/private-key.js index c42755621..403f8e2e0 100644 --- a/ui/app/pages/create-account/import-account/private-key.js +++ b/ui/app/pages/create-account/import-account/private-key.js @@ -55,7 +55,7 @@ class PrivateKeyImportView extends Component { setSelectedAddress(firstAddress) } }) - .catch(err => err && displayWarning(err.message || err)) + .catch((err) => err && displayWarning(err.message || err)) } createKeyringOnEnter = (event) => { @@ -87,7 +87,7 @@ class PrivateKeyImportView extends Component { className="new-account-import-form__input-password" type="password" id="private-key-box" - onKeyPress={e => this.createKeyringOnEnter(e)} + onKeyPress={(e) => this.createKeyringOnEnter(e)} onChange={() => this.checkInputEmpty()} ref={this.inputRef} /> diff --git a/ui/app/pages/create-account/new-account.component.js b/ui/app/pages/create-account/new-account.component.js index a9c2b5aef..d1c749f19 100644 --- a/ui/app/pages/create-account/new-account.component.js +++ b/ui/app/pages/create-account/new-account.component.js @@ -18,7 +18,7 @@ export default class NewAccountCreateForm extends Component { render () { const { newAccountName, defaultAccountName } = this.state const { history, createAccount } = this.props - const createClick = _ => { + const createClick = (_) => { createAccount(newAccountName || defaultAccountName) .then(() => { this.context.metricsEvent({ @@ -54,7 +54,7 @@ export default class NewAccountCreateForm extends Component { className="new-account-create-form__input" value={newAccountName} placeholder={defaultAccountName} - onChange={event => this.setState({ newAccountName: event.target.value })} + onChange={(event) => this.setState({ newAccountName: event.target.value })} />
    diff --git a/ui/app/pages/create-account/new-account.container.js b/ui/app/pages/create-account/new-account.container.js index 5935f81ac..93a89fe31 100644 --- a/ui/app/pages/create-account/new-account.container.js +++ b/ui/app/pages/create-account/new-account.container.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux' import * as actions from '../../store/actions' import NewAccountCreateForm from './new-account.component' -const mapStateToProps = state => { +const mapStateToProps = (state) => { const { metamask: { network, selectedAddress, identities = {} } } = state const numberOfExistingAccounts = Object.keys(identities).length const newAccountNumber = numberOfExistingAccounts + 1 @@ -14,12 +14,12 @@ const mapStateToProps = state => { } } -const mapDispatchToProps = dispatch => { +const mapDispatchToProps = (dispatch) => { return { - toCoinbase: address => dispatch(actions.buyEth({ network: '1', address, amount: 0 })), - createAccount: newAccountName => { + toCoinbase: (address) => dispatch(actions.buyEth({ network: '1', address, amount: 0 })), + createAccount: (newAccountName) => { return dispatch(actions.addNewAccount()) - .then(newAccountAddress => { + .then((newAccountAddress) => { if (newAccountName) { dispatch(actions.setAccountLabel(newAccountAddress, newAccountName)) } diff --git a/ui/app/pages/first-time-flow/create-password/create-password.component.js b/ui/app/pages/first-time-flow/create-password/create-password.component.js index 514e8d3b9..5a746d89e 100644 --- a/ui/app/pages/first-time-flow/create-password/create-password.component.js +++ b/ui/app/pages/first-time-flow/create-password/create-password.component.js @@ -36,7 +36,7 @@ export default class CreatePassword extends PureComponent { ( + render={(routeProps) => ( ( + render={(routeProps) => ( { +const mapStateToProps = (state) => { const { metamask: { isInitialized } } = state return { diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js index 2ea69f832..7ce6fcf2e 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js @@ -87,7 +87,7 @@ export default class ImportWithSeedPhrase extends PureComponent { handlePasswordChange (password) { const { t } = this.context - this.setState(state => { + this.setState((state) => { const { confirmPassword } = state let confirmPasswordError = '' let passwordError = '' @@ -111,7 +111,7 @@ export default class ImportWithSeedPhrase extends PureComponent { handleConfirmPasswordChange (confirmPassword) { const { t } = this.context - this.setState(state => { + this.setState((state) => { const { password } = state let confirmPasswordError = '' @@ -126,7 +126,7 @@ export default class ImportWithSeedPhrase extends PureComponent { }) } - handleImport = async event => { + handleImport = async (event) => { event.preventDefault() if (!this.isValid()) { @@ -206,7 +206,7 @@ export default class ImportWithSeedPhrase extends PureComponent { >
    { + onClick={(e) => { e.preventDefault() this.context.metricsEvent({ eventOpts: { @@ -236,7 +236,7 @@ export default class ImportWithSeedPhrase extends PureComponent {
    " + titleFormat(el.x) + '