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')