diff options
author | brunobar79 <brunobar79@gmail.com> | 2018-08-21 09:51:15 +0800 |
---|---|---|
committer | brunobar79 <brunobar79@gmail.com> | 2018-08-21 09:51:35 +0800 |
commit | ab7eb73ecc9e1eac8a5934a59c186e9f92a0bb32 (patch) | |
tree | d0e54e987f7ee42d21dd8a5aeb582c4a2c72e02c /test | |
parent | 6e813db47309b7773d430fecc6a467be66f6f16b (diff) | |
parent | 887cad973f25f43d2d4502ff31657f156a44b188 (diff) | |
download | tangerine-wallet-browser-ab7eb73ecc9e1eac8a5934a59c186e9f92a0bb32.tar tangerine-wallet-browser-ab7eb73ecc9e1eac8a5934a59c186e9f92a0bb32.tar.gz tangerine-wallet-browser-ab7eb73ecc9e1eac8a5934a59c186e9f92a0bb32.tar.bz2 tangerine-wallet-browser-ab7eb73ecc9e1eac8a5934a59c186e9f92a0bb32.tar.lz tangerine-wallet-browser-ab7eb73ecc9e1eac8a5934a59c186e9f92a0bb32.tar.xz tangerine-wallet-browser-ab7eb73ecc9e1eac8a5934a59c186e9f92a0bb32.tar.zst tangerine-wallet-browser-ab7eb73ecc9e1eac8a5934a59c186e9f92a0bb32.zip |
fix merge conflicts
Diffstat (limited to 'test')
-rw-r--r-- | test/e2e/beta/contract-test/contract.js | 8 | ||||
-rw-r--r-- | test/e2e/beta/contract-test/index.html | 2 | ||||
-rw-r--r-- | test/e2e/beta/from-import-beta-ui.spec.js | 14 | ||||
-rw-r--r-- | test/e2e/beta/helpers.js | 14 | ||||
-rw-r--r-- | test/e2e/beta/metamask-beta-ui.spec.js | 56 | ||||
-rw-r--r-- | test/e2e/func.js | 48 | ||||
-rw-r--r-- | test/e2e/metamask.spec.js | 66 | ||||
-rw-r--r-- | test/helper.js | 14 | ||||
-rw-r--r-- | test/lib/createTxMeta.js | 16 | ||||
-rw-r--r-- | test/unit/app/controllers/currency-controller-test.js | 3 | ||||
-rw-r--r-- | test/unit/app/controllers/detect-tokens-test.js | 53 | ||||
-rw-r--r-- | test/unit/app/controllers/metamask-controller-test.js | 175 | ||||
-rw-r--r-- | test/unit/app/controllers/network-contoller-test.js | 7 | ||||
-rw-r--r-- | test/unit/app/controllers/transactions/nonce-tracker-test.js | 9 | ||||
-rw-r--r-- | test/unit/app/controllers/transactions/pending-tx-test.js | 78 | ||||
-rw-r--r-- | test/unit/app/controllers/transactions/tx-controller-test.js | 70 | ||||
-rw-r--r-- | test/unit/config-manager-test.js | 3 | ||||
-rw-r--r-- | test/unit/localhostState.js | 21 |
18 files changed, 402 insertions, 255 deletions
diff --git a/test/e2e/beta/contract-test/contract.js b/test/e2e/beta/contract-test/contract.js index 51891ea21..39e7238ae 100644 --- a/test/e2e/beta/contract-test/contract.js +++ b/test/e2e/beta/contract-test/contract.js @@ -38,18 +38,20 @@ const transferTokens = document.getElementById('transferTokens') const approveTokens = document.getElementById('approveTokens') deployButton.addEventListener('click', async function (event) { + document.getElementById('contractStatus').innerHTML = 'Deploying' + var piggybank = await piggybankContract.new( { from: web3.eth.accounts[0], data: '0x608060405234801561001057600080fd5b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000808190555061023b806100686000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632e1a7d4d1461005c5780638da5cb5b1461009d578063d0e30db0146100f4575b600080fd5b34801561006857600080fd5b5061008760048036038101908080359060200190929190505050610112565b6040518082815260200191505060405180910390f35b3480156100a957600080fd5b506100b26101d0565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100fc6101f6565b6040518082815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561017057600080fd5b8160008082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501580156101c5573d6000803e3d6000fd5b506000549050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003460008082825401925050819055506000549050905600a165627a7a72305820f237db3ec816a52589d82512117bc85bc08d3537683ffeff9059108caf3e5d400029', gas: '4700000', }, function (e, contract) { - console.log(e, contract) + if (e) { + throw e + } if (typeof contract.address !== 'undefined') { console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash) - console.log(`contract`, contract) - document.getElementById('contractStatus').innerHTML = 'Deployed' depositButton.addEventListener('click', function (event) { diff --git a/test/e2e/beta/contract-test/index.html b/test/e2e/beta/contract-test/index.html index f6e6f44c7..0d422ef20 100644 --- a/test/e2e/beta/contract-test/index.html +++ b/test/e2e/beta/contract-test/index.html @@ -11,7 +11,7 @@ <button id="withdrawButton">Withdraw</button> </div> <div id="contractStatus" style="display: flex; font-size: 1rem;"> - Not yet deployed + Not clicked </div> </div> <div style="display: flex; flex-flow: column;"> diff --git a/test/e2e/beta/from-import-beta-ui.spec.js b/test/e2e/beta/from-import-beta-ui.spec.js index 2b271cdfe..abc684b4f 100644 --- a/test/e2e/beta/from-import-beta-ui.spec.js +++ b/test/e2e/beta/from-import-beta-ui.spec.js @@ -89,7 +89,14 @@ describe('Using MetaMask with an existing account', function () { await driver.wait(until.stalenessOf(overlay)) } catch (e) {} - const button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]")) + let button + try { + button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]")) + } catch (e) { + await loadExtension(driver, extensionId) + await delay(largeDelayMs) + button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]")) + } await button.click() await delay(regularDelayMs) @@ -359,7 +366,10 @@ describe('Using MetaMask with an existing account', function () { }) it('should open the TREZOR Connect popup', async () => { - const connectButtons = await findElements(driver, By.xpath(`//button[contains(text(), 'Connect to Trezor')]`)) + const trezorButton = await findElements(driver, By.css('.hw-connect__btn')) + await trezorButton[1].click() + await delay(regularDelayMs) + const connectButtons = await findElements(driver, By.xpath(`//button[contains(text(), 'Connect')]`)) await connectButtons[0].click() await delay(regularDelayMs) const allWindows = await driver.getAllWindowHandles() diff --git a/test/e2e/beta/helpers.js b/test/e2e/beta/helpers.js index 828f87db7..73289e526 100644 --- a/test/e2e/beta/helpers.js +++ b/test/e2e/beta/helpers.js @@ -2,8 +2,8 @@ const fs = require('fs') const mkdirp = require('mkdirp') const pify = require('pify') const assert = require('assert') -const {until} = require('selenium-webdriver') const { delay } = require('../func') +const { until } = require('selenium-webdriver') module.exports = { assertElementNotPresent, @@ -122,12 +122,14 @@ async function closeAllWindowHandlesExcept (driver, exceptions, windowHandles) { } async function assertElementNotPresent (webdriver, driver, by) { + let dataTab try { - const dataTab = await findElement(driver, by, 4000) - if (dataTab) { - assert(false, 'Data tab should not be present') - } + dataTab = await findElement(driver, by, 4000) } catch (err) { - assert(err instanceof webdriver.error.NoSuchElementError) + console.log(err) + assert(err instanceof webdriver.error.NoSuchElementError || err instanceof webdriver.error.TimeoutError) + } + if (dataTab) { + assert(false, 'Data tab should not be present') } } diff --git a/test/e2e/beta/metamask-beta-ui.spec.js b/test/e2e/beta/metamask-beta-ui.spec.js index 3ad5c2d61..aab1dc87e 100644 --- a/test/e2e/beta/metamask-beta-ui.spec.js +++ b/test/e2e/beta/metamask-beta-ui.spec.js @@ -88,7 +88,14 @@ describe('MetaMask', function () { await driver.wait(until.stalenessOf(overlay)) } catch (e) {} - const button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]")) + let button + try { + button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]")) + } catch (e) { + await loadExtension(driver, extensionId) + await delay(largeDelayMs) + button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]")) + } await button.click() await delay(regularDelayMs) @@ -345,8 +352,8 @@ describe('MetaMask', function () { const passwordInputs = await driver.findElements(By.css('input')) await delay(regularDelayMs) - passwordInputs[0].sendKeys('correct horse battery staple') - passwordInputs[1].sendKeys('correct horse battery staple') + await passwordInputs[0].sendKeys('correct horse battery staple') + await passwordInputs[1].sendKeys('correct horse battery staple') await driver.findElement(By.css('.first-time-flow__button')).click() await delay(regularDelayMs) }) @@ -438,7 +445,7 @@ describe('MetaMask', function () { await driver.switchTo().window(windowHandles[2]) await delay(regularDelayMs) - assertElementNotPresent(webdriver, driver, By.xpath(`//li[contains(text(), 'Data')]`)) + await assertElementNotPresent(webdriver, driver, By.xpath(`//li[contains(text(), 'Data')]`)) const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`), 10000) await confirmButton.click() @@ -453,6 +460,11 @@ describe('MetaMask', function () { const transactions = await findElements(driver, By.css('.tx-list-item')) assert.equal(transactions.length, 2) + await findElement(driver, By.xpath(`//span[contains(text(), 'Submitted')]`)) + + const txStatuses = await findElements(driver, By.css('.tx-list-status')) + await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) + const txValues = await findElement(driver, By.css('.tx-list-value')) await driver.wait(until.elementTextMatches(txValues, /3\sETH/), 10000) }) @@ -503,6 +515,8 @@ describe('MetaMask', function () { await confirmButton.click() await delay(regularDelayMs) + await findElement(driver, By.xpath(`//span[contains(text(), 'Submitted')]`)) + const txStatuses = await findElements(driver, By.css('.tx-list-status')) await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) @@ -511,19 +525,28 @@ describe('MetaMask', function () { await delay(regularDelayMs) }) + it('confirms a deploy contract transaction in the popup', async () => { + const windowHandles = await driver.getAllWindowHandles() + const popup = windowHandles[2] + await driver.switchTo().window(popup) + const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + await confirmButton.click() + await delay(regularDelayMs) + }) + it('calls and confirms a contract method where ETH is sent', async () => { await driver.switchTo().window(dapp) await delay(regularDelayMs) - let contractStatus = await driver.findElement(By.css('#contractStatus')) - await driver.wait(until.elementTextMatches(contractStatus, /Deployed/)) + let contractStatus = await findElement(driver, By.css('#contractStatus')) + await driver.wait(until.elementTextMatches(contractStatus, /Deployed/), 15000) const depositButton = await findElement(driver, By.css('#depositButton')) await depositButton.click() await delay(largeDelayMs) - contractStatus = await driver.findElement(By.css('#contractStatus')) - await driver.wait(until.elementTextMatches(contractStatus, /Deposit\sinitiated/)) + contractStatus = await findElement(driver, By.css('#contractStatus')) + await driver.wait(until.elementTextMatches(contractStatus, /Deposit\sinitiated/), 10000) await driver.switchTo().window(extension) await delay(largeDelayMs) @@ -539,8 +562,8 @@ describe('MetaMask', function () { await configureGas.click() await delay(regularDelayMs) - const gasModal = await driver.findElement(By.css('span .modal')) - await driver.wait(until.elementLocated(By.css('.customize-gas__title'))) + const gasModal = await findElement(driver, By.css('span .modal')) + await driver.wait(until.elementLocated(By.css('.customize-gas__title')), 10000) const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.customize-gas-input')) await gasPriceInput.clear() @@ -612,20 +635,21 @@ describe('MetaMask', function () { describe('Add a custom token from a dapp', () => { it('creates a new token', async () => { - const windowHandles = await driver.getAllWindowHandles() + let windowHandles = await driver.getAllWindowHandles() const extension = windowHandles[0] const dapp = windowHandles[1] await delay(regularDelayMs * 2) await driver.switchTo().window(dapp) - await delay(regularDelayMs) + await delay(regularDelayMs * 2) const createToken = await findElement(driver, By.xpath(`//button[contains(text(), 'Create Token')]`)) await createToken.click() - await delay(regularDelayMs) + await delay(largeDelayMs) - await driver.switchTo().window(extension) - await loadExtension(driver, extensionId) + windowHandles = await driver.getAllWindowHandles() + const popup = windowHandles[2] + await driver.switchTo().window(popup) await delay(regularDelayMs) const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) @@ -1000,4 +1024,4 @@ describe('MetaMask', function () { await delay(regularDelayMs) }) }) -}) +})
\ No newline at end of file diff --git a/test/e2e/func.js b/test/e2e/func.js index 7b1730959..13dfb82f9 100644 --- a/test/e2e/func.js +++ b/test/e2e/func.js @@ -1,14 +1,19 @@ require('chromedriver') require('geckodriver') -const fs = require('fs') +const fs = require('fs-extra') const os = require('os') const path = require('path') +const pify = require('pify') +const prependFile = pify(require('prepend-file')) const webdriver = require('selenium-webdriver') const Command = require('selenium-webdriver/lib/command').Command const By = webdriver.By module.exports = { delay, + createModifiedTestBuild, + setupBrowserAndExtension, + verboseReportOnFailure, buildChromeWebDriver, buildFirefoxWebdriver, installWebExt, @@ -20,6 +25,37 @@ function delay (time) { return new Promise(resolve => setTimeout(resolve, time)) } +async function createModifiedTestBuild ({ browser, srcPath }) { + // copy build to test-builds directory + const extPath = path.resolve(`test-builds/${browser}`) + await fs.ensureDir(extPath) + await fs.copy(srcPath, extPath) + // inject METAMASK_TEST_CONFIG setting default test network + const config = { NetworkController: { provider: { type: 'localhost' } } } + await prependFile(`${extPath}/background.js`, `window.METAMASK_TEST_CONFIG=${JSON.stringify(config)};\n`) + return { extPath } +} + +async function setupBrowserAndExtension ({ browser, extPath }) { + let driver, extensionId, extensionUri + + if (browser === 'chrome') { + driver = buildChromeWebDriver(extPath) + extensionId = await getExtensionIdChrome(driver) + extensionUri = `chrome-extension://${extensionId}/home.html` + } else if (browser === 'firefox') { + driver = buildFirefoxWebdriver() + await installWebExt(driver, extPath) + await delay(700) + extensionId = await getExtensionIdFirefox(driver) + extensionUri = `moz-extension://${extensionId}/home.html` + } else { + throw new Error(`Unknown Browser "${browser}"`) + } + + return { driver, extensionId, extensionUri } +} + function buildChromeWebDriver (extPath) { const tmpProfile = fs.mkdtempSync(path.join(os.tmpdir(), 'mm-chrome-profile')) return new webdriver.Builder() @@ -61,3 +97,13 @@ async function installWebExt (driver, extension) { return await driver.schedule(cmd, 'installWebExt(' + extension + ')') } + +async function verboseReportOnFailure ({ browser, driver, title }) { + const artifactDir = `./test-artifacts/${browser}/${title}` + const filepathBase = `${artifactDir}/test-failure` + await fs.ensureDir(artifactDir) + const screenshot = await driver.takeScreenshot() + await fs.writeFile(`${filepathBase}-screenshot.png`, screenshot, { encoding: 'base64' }) + const htmlSource = await driver.getPageSource() + await fs.writeFile(`${filepathBase}-dom.html`, htmlSource) +} diff --git a/test/e2e/metamask.spec.js b/test/e2e/metamask.spec.js index ac7600f09..38246a044 100644 --- a/test/e2e/metamask.spec.js +++ b/test/e2e/metamask.spec.js @@ -1,49 +1,41 @@ -const fs = require('fs') -const mkdirp = require('mkdirp') const path = require('path') const assert = require('assert') -const pify = require('pify') -const webdriver = require('selenium-webdriver') -const { By, Key, until } = webdriver -const { delay, buildChromeWebDriver, buildFirefoxWebdriver, installWebExt, getExtensionIdChrome, getExtensionIdFirefox } = require('./func') +const { By, Key, until } = require('selenium-webdriver') +const { delay, createModifiedTestBuild, setupBrowserAndExtension, verboseReportOnFailure } = require('./func') describe('Metamask popup page', function () { - let driver, accountAddress, tokenAddress, extensionId + const browser = process.env.SELENIUM_BROWSER + let driver, accountAddress, tokenAddress, extensionUri this.timeout(0) before(async function () { - if (process.env.SELENIUM_BROWSER === 'chrome') { - const extPath = path.resolve('dist/chrome') - driver = buildChromeWebDriver(extPath) - extensionId = await getExtensionIdChrome(driver) - await driver.get(`chrome-extension://${extensionId}/popup.html`) - - } else if (process.env.SELENIUM_BROWSER === 'firefox') { - const extPath = path.resolve('dist/firefox') - driver = buildFirefoxWebdriver() - await installWebExt(driver, extPath) - await delay(700) - extensionId = await getExtensionIdFirefox(driver) - await driver.get(`moz-extension://${extensionId}/popup.html`) - } + const srcPath = path.resolve(`dist/${browser}`) + const { extPath } = await createModifiedTestBuild({ browser, srcPath }) + const installResult = await setupBrowserAndExtension({ browser, extPath }) + driver = installResult.driver + extensionUri = installResult.extensionUri + + await driver.get(extensionUri) + await delay(300) }) afterEach(async function () { // logs command not supported in firefox // https://github.com/SeleniumHQ/selenium/issues/2910 - if (process.env.SELENIUM_BROWSER === 'chrome') { + if (browser === 'chrome') { // check for console errors const errors = await checkBrowserForConsoleErrors() if (errors.length) { const errorReports = errors.map(err => err.message) const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}` - this.test.error(new Error(errorMessage)) + console.error(new Error(errorMessage)) + } } // gather extra data if test failed if (this.currentTest.state === 'failed') { - await verboseReportOnFailure(this.currentTest) + await verboseReportOnFailure({ browser, driver, title: this.currentTest.title }) } }) @@ -54,7 +46,6 @@ describe('Metamask popup page', function () { describe('Setup', function () { it('switches to Chrome extensions list', async function () { - await delay(300) const windowHandles = await driver.getAllWindowHandles() await driver.switchTo().window(windowHandles[0]) }) @@ -98,6 +89,7 @@ describe('Metamask popup page', function () { it('allows the button to be clicked when scrolled to the bottom of TOU', async () => { const button = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div.flex-column.flex-center.flex-grow > button')) await button.click() + await delay(300) }) it('shows privacy notice', async () => { @@ -108,7 +100,6 @@ describe('Metamask popup page', function () { }) it('shows phishing notice', async () => { - await delay(300) const noticeHeader = await driver.findElement(By.css('.terms-header')).getText() assert.equal(noticeHeader, 'PHISHING WARNING', 'shows phishing warning') const element = await driver.findElement(By.css('.markdown')) @@ -295,11 +286,7 @@ describe('Metamask popup page', function () { }) it('navigates back to MetaMask popup in the tab', async function () { - if (process.env.SELENIUM_BROWSER === 'chrome') { - await driver.get(`chrome-extension://${extensionId}/popup.html`) - } else if (process.env.SELENIUM_BROWSER === 'firefox') { - await driver.get(`moz-extension://${extensionId}/popup.html`) - } + await driver.get(extensionUri) await delay(700) }) }) @@ -362,21 +349,4 @@ describe('Metamask popup page', function () { return matchedErrorObjects } - async function verboseReportOnFailure (test) { - let artifactDir - if (process.env.SELENIUM_BROWSER === 'chrome') { - artifactDir = `./test-artifacts/chrome/${test.title}` - } else if (process.env.SELENIUM_BROWSER === 'firefox') { - artifactDir = `./test-artifacts/firefox/${test.title}` - } - const filepathBase = `${artifactDir}/test-failure` - await pify(mkdirp)(artifactDir) - // capture screenshot - const screenshot = await driver.takeScreenshot() - await pify(fs.writeFile)(`${filepathBase}-screenshot.png`, screenshot, { encoding: 'base64' }) - // capture dom source - const htmlSource = await driver.getPageSource() - await pify(fs.writeFile)(`${filepathBase}-dom.html`, htmlSource) - } - }) diff --git a/test/helper.js b/test/helper.js index a3abbebf2..51f28de17 100644 --- a/test/helper.js +++ b/test/helper.js @@ -1,10 +1,21 @@ +const Ganache = require('ganache-core') +const nock = require('nock') import Enzyme from 'enzyme' import Adapter from 'enzyme-adapter-react-15' +nock.disableNetConnect() +nock.enableNetConnect('localhost') + Enzyme.configure({ adapter: new Adapter() }) // disallow promises from swallowing errors enableFailureOnUnhandledPromiseRejection() +// ganache server +const server = Ganache.server() +server.listen(8545, () => { + console.log('Ganache Testrpc is running on "http://localhost:8545"') +}) + // logging util var log = require('loglevel') log.setDefaultLevel(5) @@ -14,6 +25,9 @@ global.log = log // polyfills // +// fetch +global.fetch = require('isomorphic-fetch') + // dom require('jsdom-global')() diff --git a/test/lib/createTxMeta.js b/test/lib/createTxMeta.js new file mode 100644 index 000000000..0e88e3cfb --- /dev/null +++ b/test/lib/createTxMeta.js @@ -0,0 +1,16 @@ +const txStateHistoryHelper = require('../../app/scripts/controllers/transactions/lib/tx-state-history-helper') + +module.exports = createTxMeta + +function createTxMeta (partialMeta) { + const txMeta = Object.assign({ + status: 'unapproved', + txParams: {}, + }, partialMeta) + // initialize history + txMeta.history = [] + // capture initial snapshot of txMeta for history + const snapshot = txStateHistoryHelper.snapshotFromTxMeta(txMeta) + txMeta.history.push(snapshot) + return txMeta +} diff --git a/test/unit/app/controllers/currency-controller-test.js b/test/unit/app/controllers/currency-controller-test.js index 1941d1c43..7c4644d9f 100644 --- a/test/unit/app/controllers/currency-controller-test.js +++ b/test/unit/app/controllers/currency-controller-test.js @@ -1,6 +1,3 @@ -// polyfill fetch -global.fetch = global.fetch || require('isomorphic-fetch') - const assert = require('assert') const nock = require('nock') const CurrencyController = require('../../../../app/scripts/controllers/currency') diff --git a/test/unit/app/controllers/detect-tokens-test.js b/test/unit/app/controllers/detect-tokens-test.js index d6c3fad8a..e5539256e 100644 --- a/test/unit/app/controllers/detect-tokens-test.js +++ b/test/unit/app/controllers/detect-tokens-test.js @@ -1,4 +1,5 @@ const assert = require('assert') +const nock = require('nock') const sinon = require('sinon') const ObservableStore = require('obs-store') const DetectTokensController = require('../../../../app/scripts/controllers/detect-tokens') @@ -6,15 +7,34 @@ const NetworkController = require('../../../../app/scripts/controllers/network/n const PreferencesController = require('../../../../app/scripts/controllers/preferences') describe('DetectTokensController', () => { - const sandbox = sinon.createSandbox() - let clock, keyringMemStore, network, preferences - beforeEach(async () => { - keyringMemStore = new ObservableStore({ isUnlocked: false}) - network = new NetworkController({ provider: { type: 'mainnet' }}) - preferences = new PreferencesController({ network }) - }) - after(() => { - sandbox.restore() + const sandbox = sinon.createSandbox() + let clock, keyringMemStore, network, preferences, controller + + const noop = () => {} + + const networkControllerProviderConfig = { + getAccounts: noop, + } + + beforeEach(async () => { + + + nock('https://api.infura.io') + .get(/.*/) + .reply(200) + + keyringMemStore = new ObservableStore({ isUnlocked: false}) + network = new NetworkController() + preferences = new PreferencesController({ network }) + controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore }) + + network.initializeProvider(networkControllerProviderConfig) + + }) + + after(() => { + sandbox.restore() + nock.cleanAll() }) it('should poll on correct interval', async () => { @@ -26,7 +46,10 @@ describe('DetectTokensController', () => { it('should be called on every polling period', async () => { clock = sandbox.useFakeTimers() + const network = new NetworkController() + network.initializeProvider(networkControllerProviderConfig) network.setProviderType('mainnet') + const preferences = new PreferencesController({ network }) const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore }) controller.isOpen = true controller.isUnlocked = true @@ -44,8 +67,6 @@ describe('DetectTokensController', () => { }) it('should not check tokens while in test network', async () => { - network.setProviderType('rinkeby') - const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore }) controller.isOpen = true controller.isUnlocked = true @@ -58,7 +79,6 @@ describe('DetectTokensController', () => { }) it('should only check and add tokens while in main network', async () => { - network.setProviderType('mainnet') const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore }) controller.isOpen = true controller.isUnlocked = true @@ -75,7 +95,6 @@ describe('DetectTokensController', () => { }) it('should not detect same token while in main network', async () => { - network.setProviderType('mainnet') preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8) const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore }) controller.isOpen = true @@ -93,8 +112,6 @@ describe('DetectTokensController', () => { }) it('should trigger detect new tokens when change address', async () => { - network.setProviderType('mainnet') - const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore }) controller.isOpen = true controller.isUnlocked = true var stub = sandbox.stub(controller, 'detectNewTokens') @@ -103,8 +120,6 @@ describe('DetectTokensController', () => { }) it('should trigger detect new tokens when submit password', async () => { - network.setProviderType('mainnet') - const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore }) controller.isOpen = true controller.selectedAddress = '0x0' var stub = sandbox.stub(controller, 'detectNewTokens') @@ -113,8 +128,6 @@ describe('DetectTokensController', () => { }) it('should not trigger detect new tokens when not open or not unlocked', async () => { - network.setProviderType('mainnet') - const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore }) controller.isOpen = true controller.isUnlocked = false var stub = sandbox.stub(controller, 'detectTokenBalance') @@ -125,4 +138,4 @@ describe('DetectTokensController', () => { clock.tick(180000) sandbox.assert.notCalled(stub) }) -}) +})
\ No newline at end of file diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index 9164fe246..1fc604c9c 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -3,16 +3,22 @@ const sinon = require('sinon') const clone = require('clone') const nock = require('nock') const createThoughStream = require('through2').obj -const MetaMaskController = require('../../../../app/scripts/metamask-controller') const blacklistJSON = require('eth-phishing-detect/src/config') -const firstTimeState = require('../../../../app/scripts/first-time-state') +const MetaMaskController = require('../../../../app/scripts/metamask-controller') +const firstTimeState = require('../../../unit/localhostState') +const createTxMeta = require('../../../lib/createTxMeta') +const EthQuery = require('eth-query') const currentNetworkId = 42 const DEFAULT_LABEL = 'Account 1' +const DEFAULT_LABEL_2 = 'Account 2' const TEST_SEED = 'debris dizzy just program just float decrease vacant alarm reduce speak stadium' const TEST_ADDRESS = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc' +const TEST_ADDRESS_2 = '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b' +const TEST_ADDRESS_3 = '0xeb9e64b93097bc15f01f13eae97015c57ab64823' const TEST_SEED_ALT = 'setup olympic issue mobile velvet surge alcohol burger horse view reopen gentle' const TEST_ADDRESS_ALT = '0xc42edfcc21ed14dda456aa0756c153f7985d8813' +const CUSTOM_RPC_URL = 'http://localhost:8545' describe('MetaMaskController', function () { let metamaskController @@ -134,6 +140,9 @@ describe('MetaMaskController', function () { describe('#createNewVaultAndRestore', function () { it('should be able to call newVaultAndRestore despite a mistake.', async function () { const password = 'what-what-what' + sandbox.stub(metamaskController, 'getBalance') + metamaskController.getBalance.callsFake(() => { return Promise.resolve('0x0') }) + await metamaskController.createNewVaultAndRestore(password, TEST_SEED.slice(0, -1)).catch((e) => null) await metamaskController.createNewVaultAndRestore(password, TEST_SEED) @@ -141,6 +150,9 @@ describe('MetaMaskController', function () { }) it('should clear previous identities after vault restoration', async () => { + sandbox.stub(metamaskController, 'getBalance') + metamaskController.getBalance.callsFake(() => { return Promise.resolve('0x0') }) + await metamaskController.createNewVaultAndRestore('foobar1337', TEST_SEED) assert.deepEqual(metamaskController.getState().identities, { [TEST_ADDRESS]: { address: TEST_ADDRESS, name: DEFAULT_LABEL }, @@ -156,6 +168,54 @@ describe('MetaMaskController', function () { [TEST_ADDRESS_ALT]: { address: TEST_ADDRESS_ALT, name: DEFAULT_LABEL }, }) }) + + it('should restore any consecutive accounts with balances', async () => { + sandbox.stub(metamaskController, 'getBalance') + metamaskController.getBalance.withArgs(TEST_ADDRESS).callsFake(() => { + return Promise.resolve('0x14ced5122ce0a000') + }) + metamaskController.getBalance.withArgs(TEST_ADDRESS_2).callsFake(() => { + return Promise.resolve('0x0') + }) + metamaskController.getBalance.withArgs(TEST_ADDRESS_3).callsFake(() => { + return Promise.resolve('0x14ced5122ce0a000') + }) + + await metamaskController.createNewVaultAndRestore('foobar1337', TEST_SEED) + assert.deepEqual(metamaskController.getState().identities, { + [TEST_ADDRESS]: { address: TEST_ADDRESS, name: DEFAULT_LABEL }, + [TEST_ADDRESS_2]: { address: TEST_ADDRESS_2, name: DEFAULT_LABEL_2 }, + }) + }) + }) + + describe('#getBalance', () => { + it('should return the balance known by accountTracker', async () => { + const accounts = {} + const balance = '0x14ced5122ce0a000' + accounts[TEST_ADDRESS] = { balance: balance } + + metamaskController.accountTracker.store.putState({ accounts: accounts }) + + const gotten = await metamaskController.getBalance(TEST_ADDRESS) + + assert.equal(balance, gotten) + }) + + it('should ask the network for a balance when not known by accountTracker', async () => { + const accounts = {} + const balance = '0x14ced5122ce0a000' + const ethQuery = new EthQuery() + sinon.stub(ethQuery, 'getBalance').callsFake((account, callback) => { + callback(undefined, balance) + }) + + metamaskController.accountTracker.store.putState({ accounts: accounts }) + + const gotten = await metamaskController.getBalance(TEST_ADDRESS, ethQuery) + + assert.equal(balance, gotten) + }) }) describe('#getApi', function () { @@ -226,9 +286,9 @@ describe('MetaMaskController', function () { it('should throw if it receives an unknown device name', async function () { try { - await metamaskController.connectHardware('Some random device name', 0) + await metamaskController.connectHardware('Some random device name', 0, `m/44/0'/0'`) } catch (e) { - assert.equal(e, 'Error: MetamaskController:connectHardware - Unknown device') + assert.equal(e, 'Error: MetamaskController:getKeyringForDevice - Unknown device') } }) @@ -242,14 +302,24 @@ describe('MetaMaskController', function () { assert.equal(keyrings.length, 1) }) + it('should add the Ledger Hardware keyring', async function () { + sinon.spy(metamaskController.keyringController, 'addNewKeyring') + await metamaskController.connectHardware('ledger', 0).catch((e) => null) + const keyrings = await metamaskController.keyringController.getKeyringsByType( + 'Ledger Hardware' + ) + assert.equal(metamaskController.keyringController.addNewKeyring.getCall(0).args, 'Ledger Hardware') + assert.equal(keyrings.length, 1) + }) + }) describe('checkHardwareStatus', function () { it('should throw if it receives an unknown device name', async function () { try { - await metamaskController.checkHardwareStatus('Some random device name') + await metamaskController.checkHardwareStatus('Some random device name', `m/44/0'/0'`) } catch (e) { - assert.equal(e, 'Error: MetamaskController:checkHardwareStatus - Unknown device') + assert.equal(e, 'Error: MetamaskController:getKeyringForDevice - Unknown device') } }) @@ -265,7 +335,7 @@ describe('MetaMaskController', function () { try { await metamaskController.forgetDevice('Some random device name') } catch (e) { - assert.equal(e, 'Error: MetamaskController:forgetDevice - Unknown device') + assert.equal(e, 'Error: MetamaskController:getKeyringForDevice - Unknown device') } }) @@ -282,7 +352,7 @@ describe('MetaMaskController', function () { }) }) - describe('unlockTrezorAccount', function () { + describe('unlockHardwareWalletAccount', function () { let accountToUnlock let windowOpenStub let addNewAccountStub @@ -305,16 +375,20 @@ describe('MetaMaskController', function () { sinon.spy(metamaskController.preferencesController, 'setAddresses') sinon.spy(metamaskController.preferencesController, 'setSelectedAddress') sinon.spy(metamaskController.preferencesController, 'setAccountLabel') - await metamaskController.connectHardware('trezor', 0).catch((e) => null) - await metamaskController.unlockTrezorAccount(accountToUnlock).catch((e) => null) + await metamaskController.connectHardware('trezor', 0, `m/44/0'/0'`).catch((e) => null) + await metamaskController.unlockHardwareWalletAccount(accountToUnlock, 'trezor', `m/44/0'/0'`) }) afterEach(function () { - metamaskController.keyringController.addNewAccount.restore() window.open.restore() + metamaskController.keyringController.addNewAccount.restore() + metamaskController.keyringController.getAccounts.restore() + metamaskController.preferencesController.setAddresses.restore() + metamaskController.preferencesController.setSelectedAddress.restore() + metamaskController.preferencesController.setAccountLabel.restore() }) - it('should set accountToUnlock in the keyring', async function () { + it('should set unlockedAccount in the keyring', async function () { const keyrings = await metamaskController.keyringController.getKeyringsByType( 'Trezor Hardware' ) @@ -322,7 +396,7 @@ describe('MetaMaskController', function () { }) - it('should call keyringController.addNewAccount', async function () { + it('should call keyringController.addNewAccount', async function () { assert(metamaskController.keyringController.addNewAccount.calledOnce) }) @@ -346,29 +420,19 @@ describe('MetaMaskController', function () { }) describe('#setCustomRpc', function () { - const customRPC = 'https://custom.rpc/' let rpcTarget beforeEach(function () { - - nock('https://custom.rpc') - .post('/') - .reply(200) - - rpcTarget = metamaskController.setCustomRpc(customRPC) - }) - - afterEach(function () { - nock.cleanAll() + rpcTarget = metamaskController.setCustomRpc(CUSTOM_RPC_URL) }) it('returns custom RPC that when called', async function () { - assert.equal(await rpcTarget, customRPC) + assert.equal(await rpcTarget, CUSTOM_RPC_URL) }) it('changes the network controller rpc', function () { const networkControllerState = metamaskController.networkController.store.getState() - assert.equal(networkControllerState.provider.rpcTarget, customRPC) + assert.equal(networkControllerState.provider.rpcTarget, CUSTOM_RPC_URL) }) }) @@ -473,9 +537,10 @@ describe('MetaMaskController', function () { getNetworkstub.returns(42) metamaskController.txController.txStateManager._saveTxList([ - { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'} }, - { id: 2, status: 'rejected', metamaskNetworkId: 32, txParams: {} }, - { id: 3, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {from: '0xB09d8505E1F4EF1CeA089D47094f5DD3464083d4'} }, + 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'} }), ]) }) @@ -552,14 +617,16 @@ describe('MetaMaskController', function () { }) - describe('#newUnsignedMessage', function () { + describe('#newUnsignedMessage', () => { let msgParams, metamaskMsgs, messages, msgId const address = '0xc42edfcc21ed14dda456aa0756c153f7985d8813' const data = '0x43727970746f6b697474696573' - beforeEach(async function () { + beforeEach(async () => { + sandbox.stub(metamaskController, 'getBalance') + metamaskController.getBalance.callsFake(() => { return Promise.resolve('0x0') }) await metamaskController.createNewVaultAndRestore('foobar1337', TEST_SEED_ALT) @@ -568,7 +635,10 @@ describe('MetaMaskController', function () { 'data': data, } - metamaskController.newUnsignedMessage(msgParams, noop) + const promise = metamaskController.newUnsignedMessage(msgParams) + // handle the promise so it doesn't throw an unhandledRejection + promise.then(noop).catch(noop) + metamaskMsgs = metamaskController.messageManager.getUnapprovedMsgs() messages = metamaskController.messageManager.messages msgId = Object.keys(metamaskMsgs)[0] @@ -608,13 +678,16 @@ describe('MetaMaskController', function () { describe('#newUnsignedPersonalMessage', function () { - it('errors with no from in msgParams', function () { + it('errors with no from in msgParams', async () => { const msgParams = { 'data': data, } - metamaskController.newUnsignedPersonalMessage(msgParams, function (error) { + try { + await metamaskController.newUnsignedPersonalMessage(msgParams) + assert.fail('should have thrown') + } catch (error) { assert.equal(error.message, 'MetaMask Message Signature: from field is required.') - }) + } }) let msgParams, metamaskPersonalMsgs, personalMessages, msgId @@ -623,6 +696,8 @@ describe('MetaMaskController', function () { const data = '0x43727970746f6b697474696573' beforeEach(async function () { + sandbox.stub(metamaskController, 'getBalance') + metamaskController.getBalance.callsFake(() => { return Promise.resolve('0x0') }) await metamaskController.createNewVaultAndRestore('foobar1337', TEST_SEED_ALT) @@ -631,7 +706,10 @@ describe('MetaMaskController', function () { 'data': data, } - metamaskController.newUnsignedPersonalMessage(msgParams, noop) + const promise = metamaskController.newUnsignedPersonalMessage(msgParams) + // handle the promise so it doesn't throw an unhandledRejection + promise.then(noop).catch(noop) + metamaskPersonalMsgs = metamaskController.personalMessageManager.getUnapprovedMsgs() personalMessages = metamaskController.personalMessageManager.messages msgId = Object.keys(metamaskPersonalMsgs)[0] @@ -670,22 +748,27 @@ describe('MetaMaskController', function () { describe('#setupUntrustedCommunication', function () { let streamTest - const phishingUrl = 'decentral.market' + const phishingUrl = 'myethereumwalletntw.com' afterEach(function () { streamTest.end() }) - it('sets up phishing stream for untrusted communication ', async function () { + it('sets up phishing stream for untrusted communication ', async () => { await metamaskController.blacklistController.updatePhishingList() + console.log(blacklistJSON.blacklist.includes(phishingUrl)) + + const { promise, resolve } = deferredPromise() streamTest = createThoughStream((chunk, enc, cb) => { - assert.equal(chunk.name, 'phishing') + if (chunk.name !== 'phishing') return cb() assert.equal(chunk.data.hostname, phishingUrl) - cb() - }) - // console.log(streamTest) - metamaskController.setupUntrustedCommunication(streamTest, phishingUrl) + resolve() + cb() + }) + metamaskController.setupUntrustedCommunication(streamTest, phishingUrl) + + await promise }) }) @@ -732,3 +815,9 @@ describe('MetaMaskController', function () { }) }) + +function deferredPromise () { + let resolve + const promise = new Promise(_resolve => { resolve = _resolve }) + return { promise, resolve } +} diff --git a/test/unit/app/controllers/network-contoller-test.js b/test/unit/app/controllers/network-contoller-test.js index e16fb104e..822311931 100644 --- a/test/unit/app/controllers/network-contoller-test.js +++ b/test/unit/app/controllers/network-contoller-test.js @@ -32,9 +32,10 @@ describe('# Network Controller', function () { describe('#provider', function () { it('provider should be updatable without reassignment', function () { networkController.initializeProvider(networkControllerProviderConfig) - const proxy = networkController._proxy - proxy.setTarget({ test: true, on: () => {} }) - assert.ok(proxy.test) + const providerProxy = networkController.getProviderAndBlockTracker().provider + assert.equal(providerProxy.test, undefined) + providerProxy.setTarget({ test: true }) + assert.equal(providerProxy.test, true) }) }) describe('#getNetworkState', function () { diff --git a/test/unit/app/controllers/transactions/nonce-tracker-test.js b/test/unit/app/controllers/transactions/nonce-tracker-test.js index 6c0ac759f..51ac390e9 100644 --- a/test/unit/app/controllers/transactions/nonce-tracker-test.js +++ b/test/unit/app/controllers/transactions/nonce-tracker-test.js @@ -224,14 +224,15 @@ function generateNonceTrackerWith (pending, confirmed, providerStub = '0x0') { providerResultStub.result = providerStub const provider = { sendAsync: (_, cb) => { cb(undefined, providerResultStub) }, - _blockTracker: { - getCurrentBlock: () => '0x11b568', - }, + } + const blockTracker = { + getCurrentBlock: () => '0x11b568', + getLatestBlock: async () => '0x11b568', } return new NonceTracker({ provider, + blockTracker, getPendingTransactions, getConfirmedTransactions, }) } - diff --git a/test/unit/app/controllers/transactions/pending-tx-test.js b/test/unit/app/controllers/transactions/pending-tx-test.js index 8bf2da6f8..ba15f1953 100644 --- a/test/unit/app/controllers/transactions/pending-tx-test.js +++ b/test/unit/app/controllers/transactions/pending-tx-test.js @@ -9,6 +9,7 @@ describe('PendingTransactionTracker', function () { let pendingTxTracker, txMeta, txMetaNoHash, providerResultStub, provider, txMeta3, txList, knownErrors this.timeout(10000) + beforeEach(function () { txMeta = { id: 1, @@ -40,7 +41,10 @@ describe('PendingTransactionTracker', function () { getPendingTransactions: () => { return [] }, getCompletedTransactions: () => { return [] }, publishTransaction: () => {}, + confirmTransaction: () => {}, }) + + pendingTxTracker._getBlock = (blockNumber) => { return {number: blockNumber, transactions: []} } }) describe('_checkPendingTx state management', function () { @@ -92,58 +96,6 @@ describe('PendingTransactionTracker', function () { }) }) - describe('#checkForTxInBlock', function () { - it('should return if no pending transactions', function () { - // throw a type error if it trys to do anything on the block - // thus failing the test - const block = Proxy.revocable({}, {}).revoke() - pendingTxTracker.checkForTxInBlock(block) - }) - it('should emit \'tx:failed\' if the txMeta does not have a hash', function (done) { - const block = Proxy.revocable({}, {}).revoke() - pendingTxTracker.getPendingTransactions = () => [txMetaNoHash] - pendingTxTracker.once('tx:failed', (txId, err) => { - assert(txId, txMetaNoHash.id, 'should pass txId') - done() - }) - pendingTxTracker.checkForTxInBlock(block) - }) - it('should emit \'txConfirmed\' if the tx is in the block', function (done) { - const block = { transactions: [txMeta]} - pendingTxTracker.getPendingTransactions = () => [txMeta] - pendingTxTracker.once('tx:confirmed', (txId) => { - assert(txId, txMeta.id, 'should pass txId') - done() - }) - pendingTxTracker.once('tx:failed', (_, err) => { done(err) }) - pendingTxTracker.checkForTxInBlock(block) - }) - }) - describe('#queryPendingTxs', function () { - it('should call #_checkPendingTxs if their is no oldBlock', function (done) { - let oldBlock - const newBlock = { number: '0x01' } - pendingTxTracker._checkPendingTxs = done - pendingTxTracker.queryPendingTxs({ oldBlock, newBlock }) - }) - it('should call #_checkPendingTxs if oldBlock and the newBlock have a diff of greater then 1', function (done) { - const oldBlock = { number: '0x01' } - const newBlock = { number: '0x03' } - pendingTxTracker._checkPendingTxs = done - pendingTxTracker.queryPendingTxs({ oldBlock, newBlock }) - }) - it('should not call #_checkPendingTxs if oldBlock and the newBlock have a diff of 1 or less', function (done) { - const oldBlock = { number: '0x1' } - const newBlock = { number: '0x2' } - pendingTxTracker._checkPendingTxs = () => { - const err = new Error('should not call #_checkPendingTxs if oldBlock and the newBlock have a diff of 1 or less') - done(err) - } - pendingTxTracker.queryPendingTxs({ oldBlock, newBlock }) - done() - }) - }) - describe('#_checkPendingTx', function () { it('should emit \'tx:failed\' if the txMeta does not have a hash', function (done) { pendingTxTracker.once('tx:failed', (txId, err) => { @@ -157,16 +109,6 @@ describe('PendingTransactionTracker', function () { providerResultStub.eth_getTransactionByHash = null pendingTxTracker._checkPendingTx(txMeta) }) - - it('should emit \'txConfirmed\'', function (done) { - providerResultStub.eth_getTransactionByHash = {blockNumber: '0x01'} - pendingTxTracker.once('tx:confirmed', (txId) => { - assert(txId, txMeta.id, 'should pass txId') - done() - }) - pendingTxTracker.once('tx:failed', (_, err) => { done(err) }) - pendingTxTracker._checkPendingTx(txMeta) - }) }) describe('#_checkPendingTxs', function () { @@ -180,19 +122,19 @@ describe('PendingTransactionTracker', function () { }) }) - it('should warp all txMeta\'s in #_checkPendingTx', function (done) { + it('should warp all txMeta\'s in #updatePendingTxs', function (done) { pendingTxTracker.getPendingTransactions = () => txList pendingTxTracker._checkPendingTx = (tx) => { tx.resolve(tx) } Promise.all(txList.map((tx) => tx.processed)) .then((txCompletedList) => done()) .catch(done) - pendingTxTracker._checkPendingTxs() + pendingTxTracker.updatePendingTxs() }) }) describe('#resubmitPendingTxs', function () { - const blockStub = { number: '0x0' } + const blockNumberStub = '0x0' beforeEach(function () { const txMeta2 = txMeta3 = txMeta txList = [txMeta, txMeta2, txMeta3].map((tx) => { @@ -210,7 +152,7 @@ describe('PendingTransactionTracker', function () { Promise.all(txList.map((tx) => tx.processed)) .then((txCompletedList) => done()) .catch(done) - pendingTxTracker.resubmitPendingTxs(blockStub) + pendingTxTracker.resubmitPendingTxs(blockNumberStub) }) it('should not emit \'tx:failed\' if the txMeta throws a known txError', function (done) { knownErrors = [ @@ -237,7 +179,7 @@ describe('PendingTransactionTracker', function () { .then((txCompletedList) => done()) .catch(done) - pendingTxTracker.resubmitPendingTxs(blockStub) + pendingTxTracker.resubmitPendingTxs(blockNumberStub) }) it('should emit \'tx:warning\' if it encountered a real error', function (done) { pendingTxTracker.once('tx:warning', (txMeta, err) => { @@ -255,7 +197,7 @@ describe('PendingTransactionTracker', function () { .then((txCompletedList) => done()) .catch(done) - pendingTxTracker.resubmitPendingTxs(blockStub) + pendingTxTracker.resubmitPendingTxs(blockNumberStub) }) }) describe('#_resubmitTx', function () { diff --git a/test/unit/app/controllers/transactions/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js index 26dc7b656..5ac813b49 100644 --- a/test/unit/app/controllers/transactions/tx-controller-test.js +++ b/test/unit/app/controllers/transactions/tx-controller-test.js @@ -1,4 +1,5 @@ const assert = require('assert') +const EventEmitter = require('events') const ethUtil = require('ethereumjs-util') const EthTx = require('ethereumjs-tx') const ObservableStore = require('obs-store') @@ -22,12 +23,14 @@ describe('Transaction Controller', function () { } provider = createTestProviderTools({ scaffold: providerResultStub }).provider fromAccount = getTestAccounts()[0] - + const blockTrackerStub = new EventEmitter() + blockTrackerStub.getCurrentBlock = noop + blockTrackerStub.getLatestBlock = noop txController = new TransactionController({ provider, networkStore: new ObservableStore(currentNetworkId), txHistoryLimit: 10, - blockTracker: { getCurrentBlock: noop, on: noop, once: noop }, + blockTracker: blockTrackerStub, signTransaction: (ethTx) => new Promise((resolve) => { ethTx.sign(fromAccount.key) resolve() @@ -49,9 +52,9 @@ describe('Transaction Controller', function () { describe('#getUnapprovedTxCount', function () { it('should return the number of unapproved txs', function () { txController.txStateManager._saveTxList([ - { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} }, - { id: 2, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} }, - { id: 3, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} }, + { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] }, + { id: 2, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] }, + { id: 3, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] }, ]) const unapprovedTxCount = txController.getUnapprovedTxCount() assert.equal(unapprovedTxCount, 3, 'should be 3') @@ -61,9 +64,9 @@ describe('Transaction Controller', function () { describe('#getPendingTxCount', function () { it('should return the number of pending txs', function () { txController.txStateManager._saveTxList([ - { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {} }, - { id: 2, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {} }, - { id: 3, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {} }, + { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] }, + { id: 2, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] }, + { id: 3, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {}, history: [] }, ]) const pendingTxCount = txController.getPendingTxCount() assert.equal(pendingTxCount, 3, 'should be 3') @@ -79,15 +82,15 @@ describe('Transaction Controller', function () { 'to': '0xc684832530fcbddae4b4230a47e991ddcec2831d', } txController.txStateManager._saveTxList([ - {id: 0, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams}, - {id: 1, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams}, - {id: 2, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams}, - {id: 3, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams}, - {id: 4, status: 'rejected', metamaskNetworkId: currentNetworkId, txParams}, - {id: 5, status: 'approved', metamaskNetworkId: currentNetworkId, txParams}, - {id: 6, status: 'signed', metamaskNetworkId: currentNetworkId, txParams}, - {id: 7, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams}, - {id: 8, status: 'failed', metamaskNetworkId: currentNetworkId, txParams}, + {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: [] }, ]) }) @@ -201,24 +204,22 @@ describe('Transaction Controller', function () { }) describe('#addTxGasDefaults', function () { - it('should add the tx defaults if their are none', function (done) { + it('should add the tx defaults if their are none', async () => { const txMeta = { - 'txParams': { - 'from': '0xc684832530fcbddae4b4230a47e991ddcec2831d', - 'to': '0xc684832530fcbddae4b4230a47e991ddcec2831d', + txParams: { + from: '0xc684832530fcbddae4b4230a47e991ddcec2831d', + to: '0xc684832530fcbddae4b4230a47e991ddcec2831d', }, + history: [], } - providerResultStub.eth_gasPrice = '4a817c800' - providerResultStub.eth_getBlockByNumber = { gasLimit: '47b784' } - providerResultStub.eth_estimateGas = '5209' - txController.addTxGasDefaults(txMeta) - .then((txMetaWithDefaults) => { - assert(txMetaWithDefaults.txParams.value, '0x0', 'should have added 0x0 as the value') - assert(txMetaWithDefaults.txParams.gasPrice, 'should have added the gas price') - assert(txMetaWithDefaults.txParams.gas, 'should have added the gas field') - done() - }) - .catch(done) + providerResultStub.eth_gasPrice = '4a817c800' + providerResultStub.eth_getBlockByNumber = { gasLimit: '47b784' } + providerResultStub.eth_estimateGas = '5209' + + const txMetaWithDefaults = await txController.addTxGasDefaults(txMeta) + assert(txMetaWithDefaults.txParams.value, '0x0', 'should have added 0x0 as the value') + assert(txMetaWithDefaults.txParams.gasPrice, 'should have added the gas price') + assert(txMetaWithDefaults.txParams.gas, 'should have added the gas field') }) }) @@ -381,8 +382,9 @@ describe('Transaction Controller', function () { }) it('should publish a tx, updates the rawTx when provided a one', async function () { + const rawTx = '0x477b2e6553c917af0db0388ae3da62965ff1a184558f61b749d1266b2e6d024c' txController.txStateManager.addTx(txMeta) - await txController.publishTransaction(txMeta.id) + await txController.publishTransaction(txMeta.id, rawTx) const publishedTx = txController.txStateManager.getTx(1) assert.equal(publishedTx.hash, hash) assert.equal(publishedTx.status, 'submitted') @@ -398,7 +400,7 @@ describe('Transaction Controller', function () { data: '0x0', } txController.txStateManager._saveTxList([ - { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams }, + { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [] }, ]) txController.retryTransaction(1) .then((txMeta) => { diff --git a/test/unit/config-manager-test.js b/test/unit/config-manager-test.js index b710e2dfb..df0c549d0 100644 --- a/test/unit/config-manager-test.js +++ b/test/unit/config-manager-test.js @@ -1,6 +1,3 @@ -// polyfill fetch -global.fetch = global.fetch || require('isomorphic-fetch') - const assert = require('assert') const configManagerGen = require('../lib/mock-config-manager') diff --git a/test/unit/localhostState.js b/test/unit/localhostState.js new file mode 100644 index 000000000..f9fa157d7 --- /dev/null +++ b/test/unit/localhostState.js @@ -0,0 +1,21 @@ + +/** + * @typedef {Object} FirstTimeState + * @property {Object} config Initial configuration parameters + * @property {Object} NetworkController Network controller state + */ + +/** + * @type {FirstTimeState} + */ +const initialState = { + config: {}, + NetworkController: { + provider: { + type: 'rpc', + rpcTarget: 'http://localhost:8545', + }, + }, +} + +module.exports = initialState |