From 27cfb6aa51f139dcc3bf3334be3c35b0e123407b Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 13 Jan 2020 11:07:32 -0400 Subject: [PATCH] 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')