diff --git a/.circleci/config.yml b/.circleci/config.yml index 4d9d01ee6..bc40c9a7c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -30,6 +30,15 @@ workflows: - prep-deps-npm - prep-deps-firefox - prep-build + - test-e2e-beta-chrome: + requires: + - prep-deps-npm + - prep-build + - test-e2e-beta-firefox: + requires: + - prep-deps-npm + - prep-deps-firefox + - prep-build - test-unit: requires: - prep-deps-npm @@ -57,6 +66,8 @@ workflows: - test-unit - test-e2e-chrome - test-e2e-firefox + - test-e2e-beta-chrome + - test-e2e-beta-firefox - test-integration-mascara-chrome - test-integration-mascara-firefox - test-integration-flat-chrome @@ -110,9 +121,7 @@ jobs: - checkout - run: name: Download Firefox - command: > - wget https://ftp.mozilla.org/pub/firefox/releases/58.0/linux-x86_64/en-US/firefox-58.0.tar.bz2 - && tar xjf firefox-58.0.tar.bz2 + command: ./.circleci/scripts/firefox-download.sh - save_cache: key: dependency-cache-firefox-{{ .Revision }} paths: @@ -203,15 +212,13 @@ jobs: - restore_cache: key: build-cache-{{ .Revision }} - run: - name: Test + name: test:e2e:chrome command: npm run test:e2e:chrome - store_artifacts: path: test-artifacts destination: test-artifacts test-e2e-firefox: - environment: - browsers: '["Firefox"]' docker: - image: circleci/node:8-browsers steps: @@ -220,11 +227,7 @@ jobs: key: dependency-cache-firefox-{{ .Revision }} - run: name: Install firefox - command: > - sudo rm -r /opt/firefox - && sudo mv firefox /opt/firefox58 - && sudo mv /usr/bin/firefox /usr/bin/firefox-old - && sudo ln -s /opt/firefox58/firefox /usr/bin/firefox + command: ./.circleci/scripts/firefox-install.sh - restore_cache: key: dependency-cache-{{ .Revision }} - restore_cache: @@ -236,6 +239,43 @@ jobs: path: test-artifacts destination: test-artifacts + test-e2e-beta-chrome: + docker: + - image: circleci/node:8-browsers + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ .Revision }} + - restore_cache: + key: build-cache-{{ .Revision }} + - run: + name: test:e2e:chrome:beta + command: npm run test:e2e:chrome:beta + - store_artifacts: + path: test-artifacts + destination: test-artifacts + + test-e2e-beta-firefox: + docker: + - image: circleci/node:8-browsers + steps: + - checkout + - restore_cache: + key: dependency-cache-firefox-{{ .Revision }} + - run: + name: Install firefox + command: ./.circleci/scripts/firefox-install.sh + - restore_cache: + key: dependency-cache-{{ .Revision }} + - restore_cache: + key: build-cache-{{ .Revision }} + - run: + name: test:e2e:firefox:beta + command: npm run test:e2e:firefox:beta + - store_artifacts: + path: test-artifacts + destination: test-artifacts + job-screens: docker: - image: circleci/node:8-browsers @@ -325,11 +365,7 @@ jobs: key: dependency-cache-firefox-{{ .Revision }} - run: name: Install firefox - command: > - sudo rm -r /opt/firefox - && sudo mv firefox /opt/firefox58 - && sudo mv /usr/bin/firefox /usr/bin/firefox-old - && sudo ln -s /opt/firefox58/firefox /usr/bin/firefox + command: ./.circleci/scripts/firefox-install.sh - restore_cache: key: dependency-cache-{{ .Revision }} - run: @@ -372,11 +408,7 @@ jobs: key: dependency-cache-firefox-{{ .Revision }} - run: name: Install firefox - command: > - sudo rm -r /opt/firefox - && sudo mv firefox /opt/firefox58 - && sudo mv /usr/bin/firefox /usr/bin/firefox-old - && sudo ln -s /opt/firefox58/firefox /usr/bin/firefox + command: ./.circleci/scripts/firefox-install.sh - restore_cache: key: dependency-cache-{{ .Revision }} - run: @@ -415,4 +447,3 @@ jobs: - run: name: All Tests Passed command: echo 'weew - everything passed!' - diff --git a/.circleci/scripts/firefox-download.sh b/.circleci/scripts/firefox-download.sh new file mode 100755 index 000000000..c63e8c3df --- /dev/null +++ b/.circleci/scripts/firefox-download.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +echo "Downloading firefox..." +wget https://ftp.mozilla.org/pub/firefox/releases/58.0/linux-x86_64/en-US/firefox-58.0.tar.bz2 \ +&& tar xjf firefox-58.0.tar.bz2 +echo "firefox download complete" diff --git a/.circleci/scripts/firefox-install.sh b/.circleci/scripts/firefox-install.sh new file mode 100755 index 000000000..589bcbbb5 --- /dev/null +++ b/.circleci/scripts/firefox-install.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +echo "Installing firefox..." +sudo rm -r /opt/firefox +sudo mv firefox /opt/firefox58 +sudo mv /usr/bin/firefox /usr/bin/firefox-old +sudo ln -s /opt/firefox58/firefox /usr/bin/firefox +echo "Firefox installed." diff --git a/test/e2e/beta/from-import-beta-ui.spec.js b/test/e2e/beta/from-import-beta-ui.spec.js index e07d4a99e..987ae96da 100644 --- a/test/e2e/beta/from-import-beta-ui.spec.js +++ b/test/e2e/beta/from-import-beta-ui.spec.js @@ -1,7 +1,7 @@ const path = require('path') const assert = require('assert') const webdriver = require('selenium-webdriver') -const { By, Key } = webdriver +const { By, Key, until } = webdriver const { delay, buildChromeWebDriver, @@ -14,8 +14,11 @@ const { checkBrowserForConsoleErrors, loadExtension, verboseReportOnFailure, + findElement, + findElements, } = require('./helpers') + describe('Using MetaMask with an existing account', function () { let extensionId let driver @@ -79,30 +82,33 @@ describe('Using MetaMask with an existing account', function () { }) it('use the local network', async function () { - const [networkSelector] = await driver.findElements(By.css('#network_component')) + const networkSelector = await findElement(driver, By.css('#network_component')) await networkSelector.click() await delay(regularDelayMs) - const [localhost] = await driver.findElements(By.xpath(`//li[contains(text(), 'Localhost')]`)) + const [localhost] = await findElements(driver, By.xpath(`//li[contains(text(), 'Localhost')]`)) await localhost.click() await delay(regularDelayMs) }) it('selects the new UI option', async () => { - const button = await driver.findElement(By.xpath("//p[contains(text(), 'Try Beta Version')]")) + const button = await findElement(driver, By.xpath("//p[contains(text(), 'Try Beta Version')]")) await button.click() await delay(regularDelayMs) // Close all other tabs - const [oldUi, infoPage, newUi] = await driver.getAllWindowHandles() + let [oldUi, infoPage, newUi] = await driver.getAllWindowHandles() + newUi = newUi || infoPage await driver.switchTo().window(oldUi) await driver.close() - await driver.switchTo().window(infoPage) - await driver.close() + if (infoPage !== newUi) { + await driver.switchTo().window(infoPage) + await driver.close() + } await driver.switchTo().window(newUi) await delay(regularDelayMs) - const [continueBtn] = await driver.findElements(By.css('.welcome-screen__button')) + const continueBtn = await findElement(driver, By.css('.welcome-screen__button')) await continueBtn.click() await delay(regularDelayMs) }) @@ -110,36 +116,36 @@ describe('Using MetaMask with an existing account', function () { describe('First time flow starting from an existing seed phrase', () => { it('imports a seed phrase', async () => { - const [seedPhrase] = await driver.findElements(By.xpath(`//a[contains(text(), 'Import with seed phrase')]`)) + const [seedPhrase] = await findElements(driver, By.xpath(`//a[contains(text(), 'Import with seed phrase')]`)) await seedPhrase.click() await delay(regularDelayMs) - const [seedTextArea] = await driver.findElements(By.css('textarea.import-account__secret-phrase')) + const [seedTextArea] = await findElements(driver, By.css('textarea.import-account__secret-phrase')) await seedTextArea.sendKeys(testSeedPhrase) await delay(regularDelayMs) - const [password] = await driver.findElements(By.id('password')) + const [password] = await findElements(driver, By.id('password')) await password.sendKeys('correct horse battery staple') - const [confirmPassword] = await driver.findElements(By.id('confirm-password')) + const [confirmPassword] = await findElements(driver, By.id('confirm-password')) confirmPassword.sendKeys('correct horse battery staple') - const [importButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Import')]`)) + const [importButton] = await findElements(driver, By.xpath(`//button[contains(text(), 'Import')]`)) await importButton.click() await delay(regularDelayMs) }) it('clicks through the privacy notice', async () => { - const [nextScreen] = await driver.findElements(By.css('.tou button')) + const [nextScreen] = await findElements(driver, By.css('.tou button')) await nextScreen.click() await delay(regularDelayMs) const canClickThrough = await driver.findElement(By.css('.tou button')).isEnabled() assert.equal(canClickThrough, false, 'disabled continue button') - const element = await driver.findElement(By.linkText('Attributions')) + const element = await findElement(driver, By.linkText('Attributions')) await driver.executeScript('arguments[0].scrollIntoView(true)', element) await delay(regularDelayMs) - const [acceptTos] = await driver.findElements(By.css('.tou button')) + const acceptTos = await findElement(driver, By.xpath(`//button[contains(text(), 'Accept')]`)) await acceptTos.click() await delay(regularDelayMs) }) @@ -147,11 +153,12 @@ describe('Using MetaMask with an existing account', function () { describe('Show account information', () => { it('shows the correct account address', async () => { - await driver.findElement(By.css('.wallet-view__details-button')).click() + const detailsButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Details')]`)) + detailsButton.click() await driver.findElement(By.css('.qr-wrapper')).isDisplayed() await delay(regularDelayMs) - const [address] = await driver.findElements(By.css('input.qr-ellip-address')) + const [address] = await findElements(driver, By.css('input.qr-ellip-address')) assert.equal(await address.getAttribute('value'), testAddress) await driver.executeScript("document.querySelector('.account-modal-close').click()") @@ -161,19 +168,22 @@ describe('Using MetaMask with an existing account', function () { it('shows a QR code for the account', async () => { await driver.findElement(By.css('.wallet-view__details-button')).click() await driver.findElement(By.css('.qr-wrapper')).isDisplayed() + const detailModal = await driver.findElement(By.css('span .modal')) await delay(regularDelayMs) await driver.executeScript("document.querySelector('.account-modal-close').click()") + await driver.wait(until.stalenessOf(detailModal)) await delay(regularDelayMs) }) }) describe('Log out and log back in', () => { it('logs out of the account', async () => { - await driver.findElement(By.css('.account-menu__icon')).click() + const accountIdenticon = driver.findElement(By.css('.account-menu__icon .identicon')) + accountIdenticon.click() await delay(regularDelayMs) - const [logoutButton] = await driver.findElements(By.css('.account-menu__logout-button')) + const [logoutButton] = await findElements(driver, By.css('.account-menu__logout-button')) assert.equal(await logoutButton.getText(), 'Log out') await logoutButton.click() await delay(regularDelayMs) @@ -191,23 +201,23 @@ describe('Using MetaMask with an existing account', function () { await driver.findElement(By.css('.account-menu__icon')).click() await delay(regularDelayMs) - const [createAccount] = await driver.findElements(By.xpath(`//div[contains(text(), 'Create Account')]`)) + const [createAccount] = await findElements(driver, By.xpath(`//div[contains(text(), 'Create Account')]`)) await createAccount.click() await delay(regularDelayMs) }) it('set account name', async () => { - const [accountName] = await driver.findElements(By.css('.new-account-create-form input')) + const [accountName] = await findElements(driver, By.css('.new-account-create-form input')) await accountName.sendKeys('2nd account') await delay(regularDelayMs) - const [createButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Create')]`)) + const [createButton] = await findElements(driver, By.xpath(`//button[contains(text(), 'Create')]`)) await createButton.click() await delay(regularDelayMs) }) it('should show the correct account name', async () => { - const [accountName] = await driver.findElements(By.css('.account-name')) + const [accountName] = await findElements(driver, By.css('.account-name')) assert.equal(await accountName.getText(), '2nd account') await delay(regularDelayMs) }) @@ -218,7 +228,7 @@ describe('Using MetaMask with an existing account', function () { await driver.findElement(By.css('.account-menu__icon')).click() await delay(regularDelayMs) - const [originalAccountMenuItem] = await driver.findElements(By.css('.account-menu__name')) + const [originalAccountMenuItem] = await findElements(driver, By.css('.account-menu__name')) await originalAccountMenuItem.click() await delay(regularDelayMs) }) @@ -226,41 +236,41 @@ describe('Using MetaMask with an existing account', function () { describe('Send ETH from inside MetaMask', () => { it('starts to send a transaction', async function () { - const [sendButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Send')]`)) + const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`)) await sendButton.click() await delay(regularDelayMs) - const [inputAddress] = await driver.findElements(By.css('input[placeholder="Recipient Address"]')) - const [inputAmount] = await driver.findElements(By.css('.currency-display__input')) + const inputAddress = await findElement(driver, By.css('input[placeholder="Recipient Address"]')) + const inputAmount = await findElement(driver, By.css('.currency-display__input')) await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') await inputAmount.sendKeys('1') // Set the gas limit - const [configureGas] = await driver.findElements(By.css('.send-v2__gas-fee-display button')) + const configureGas = await findElement(driver, By.css('.send-v2__gas-fee-display button')) await configureGas.click() await delay(regularDelayMs) - const [save] = await driver.findElements(By.xpath(`//button[contains(text(), 'Save')]`)) + const save = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`)) await save.click() await delay(regularDelayMs) // Continue to next screen - const [nextScreen] = await driver.findElements(By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() await delay(regularDelayMs) }) it('confirms the transaction', async function () { - const [confirmButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() await delay(regularDelayMs) }) it('finds the transaction in the transactions list', async function () { - const transactions = await driver.findElements(By.css('.tx-list-item')) + const transactions = await findElements(driver, By.css('.tx-list-item')) assert.equal(transactions.length, 1) - const txValues = await driver.findElements(By.css('.tx-list-value')) + const txValues = await findElements(driver, By.css('.tx-list-value')) assert.equal(txValues.length, 1) assert.equal(await txValues[0].getText(), '1 ETH') }) @@ -275,7 +285,7 @@ describe('Using MetaMask with an existing account', function () { await driver.switchTo().window(faucet) await delay(regularDelayMs) - const [send1eth] = await driver.findElements(By.xpath(`//button[contains(text(), '10 ether')]`)) + const send1eth = await findElement(driver, By.xpath(`//button[contains(text(), '10 ether')]`)) await send1eth.click() await delay(regularDelayMs) @@ -283,7 +293,7 @@ describe('Using MetaMask with an existing account', function () { await loadExtension(driver, extensionId) await delay(regularDelayMs) - const [confirmButton] = await driver.findElements(By.xpath(`//button[contains(text(),'Confirm')]`)) + const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() await delay(regularDelayMs) @@ -300,31 +310,31 @@ describe('Using MetaMask with an existing account', function () { describe('Add existing token using search', () => { it('clicks on the Add Token button', async () => { - const [addToken] = await driver.findElements(By.xpath(`//button[contains(text(), 'Add Token')]`)) + const addToken = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Token')]`)) await addToken.click() await delay(regularDelayMs) }) it('picks an existing token', async () => { - const [tokenSearch] = await driver.findElements(By.css('input.add-token__input')) + const tokenSearch = await findElement(driver, By.css('#search-tokens')) await tokenSearch.sendKeys('BAT') await delay(regularDelayMs) - const [token] = await driver.findElements(By.xpath("//div[contains(text(), 'BAT')]")) + const token = await findElement(driver, By.xpath("//span[contains(text(), 'BAT')]")) await token.click() await delay(regularDelayMs) - const [nextScreen] = await driver.findElements(By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() await delay(regularDelayMs) - const [addTokens] = await driver.findElements(By.xpath(`//button[contains(text(), 'Add Tokens')]`)) + const addTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Tokens')]`)) await addTokens.click() await delay(largeDelayMs) }) it('renders the balance for the new token', async () => { - const balance = await driver.findElement(By.css('.tx-view .balance-display .token-amount')) + const balance = await findElement(driver, By.css('.tx-view .balance-display .token-amount')) const tokenAmount = await balance.getText() assert.equal(tokenAmount, '0BAT') await delay(regularDelayMs) @@ -343,14 +353,14 @@ describe('Using MetaMask with an existing account', function () { tokenName, tokenDecimal, tokenSymbol, - ] = await driver.findElements(By.css('input')) + ] = await findElements(driver, By.css('.form-control')) await totalSupply.sendKeys('100') await tokenName.sendKeys('Test') await tokenDecimal.sendKeys('0') await tokenSymbol.sendKeys('TST') - const [createToken] = await driver.findElements(By.xpath(`//button[contains(text(), 'Create Token')]`)) + const createToken = await findElement(driver, By.xpath(`//button[contains(text(), 'Create Token')]`)) await createToken.click() await delay(regularDelayMs) @@ -358,7 +368,7 @@ describe('Using MetaMask with an existing account', function () { await loadExtension(driver, extensionId) await delay(regularDelayMs) - const [confirmButton] = await driver.findElements(By.xpath(`//button[contains(text(),'Confirm')]`)) + const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() await delay(regularDelayMs) @@ -373,31 +383,32 @@ describe('Using MetaMask with an existing account', function () { }) it('clicks on the Add Token button', async () => { - const [addToken] = await driver.findElements(By.xpath(`//button[contains(text(), 'Add Token')]`)) + const addToken = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Token')]`)) await addToken.click() await delay(regularDelayMs) }) it('picks the new Test token', async () => { - const [addCustomToken] = await driver.findElements(By.xpath("//div[contains(text(), 'Custom Token')]")) + const addCustomToken = await findElement(driver, By.xpath("//div[contains(text(), 'Custom Token')]")) await addCustomToken.click() await delay(regularDelayMs) - const [newTokenAddress] = await driver.findElements(By.css('.add-token__add-custom-form input')) + const newTokenAddress = await findElement(driver, By.css('#custom-address')) await newTokenAddress.sendKeys(tokenAddress) await delay(regularDelayMs) - const [nextScreen] = await driver.findElements(By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() await delay(regularDelayMs) - const [addTokens] = await driver.findElements(By.xpath(`//button[contains(text(), 'Add Tokens')]`)) + const addTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Tokens')]`)) await addTokens.click() await delay(regularDelayMs) }) it('renders the balance for the new token', async () => { - const [balance] = await driver.findElements(By.css('.tx-view .balance-display .token-amount')) + const balance = await findElement(driver, By.css('.tx-view .balance-display .token-amount')) + await driver.wait(until.elementTextIs(balance, '100TST')) const tokenAmount = await balance.getText() assert.equal(tokenAmount, '100TST') await delay(regularDelayMs) diff --git a/test/e2e/beta/helpers.js b/test/e2e/beta/helpers.js index 8307fdc50..31c41d8b7 100644 --- a/test/e2e/beta/helpers.js +++ b/test/e2e/beta/helpers.js @@ -1,11 +1,14 @@ const fs = require('fs') const mkdirp = require('mkdirp') const pify = require('pify') +const {until} = require('selenium-webdriver') module.exports = { checkBrowserForConsoleErrors, loadExtension, verboseReportOnFailure, + findElement, + findElements, } async function loadExtension (driver, extensionId) { @@ -53,3 +56,11 @@ async function verboseReportOnFailure (driver, test) { const htmlSource = await driver.getPageSource() await pify(fs.writeFile)(`${filepathBase}-dom.html`, htmlSource) } + +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) +} diff --git a/test/e2e/beta/metamask-beta-ui.spec.js b/test/e2e/beta/metamask-beta-ui.spec.js index 00863e3b3..526fa389c 100644 --- a/test/e2e/beta/metamask-beta-ui.spec.js +++ b/test/e2e/beta/metamask-beta-ui.spec.js @@ -1,7 +1,7 @@ const path = require('path') const assert = require('assert') const webdriver = require('selenium-webdriver') -const { By, Key } = webdriver +const { By, Key, until } = webdriver const { delay, buildChromeWebDriver, @@ -11,6 +11,8 @@ const { getExtensionIdFirefox, } = require('../func') const { + findElement, + findElements, checkBrowserForConsoleErrors, loadExtension, verboseReportOnFailure, @@ -22,10 +24,10 @@ describe('MetaMask', function () { let tokenAddress const testSeedPhrase = 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent' - const tinyDelayMs = 500 + const tinyDelayMs = 1000 const regularDelayMs = tinyDelayMs * 2 const largeDelayMs = regularDelayMs * 2 - const waitingNewPageDelayMs = regularDelayMs * 10 + const waitingNewPageDelayMs = regularDelayMs * 30 this.timeout(0) this.bail(true) @@ -76,30 +78,33 @@ describe('MetaMask', function () { }) it('use the local network', async function () { - const [networkSelector] = await driver.findElements(By.css('#network_component')) + const networkSelector = await findElement(driver, By.css('#network_component')) await networkSelector.click() await delay(regularDelayMs) - const [localhost] = await driver.findElements(By.xpath(`//li[contains(text(), 'Localhost')]`)) + const localhost = await findElement(driver, By.xpath(`//li[contains(text(), 'Localhost')]`)) await localhost.click() await delay(regularDelayMs) }) it('selects the new UI option', async () => { - const button = await driver.findElement(By.xpath("//p[contains(text(), 'Try Beta Version')]")) + const button = await findElement(driver, By.xpath("//p[contains(text(), 'Try Beta Version')]")) await button.click() await delay(regularDelayMs) // Close all other tabs - const [oldUi, infoPage, newUi] = await driver.getAllWindowHandles() + let [oldUi, infoPage, newUi] = await driver.getAllWindowHandles() + newUi = newUi || infoPage await driver.switchTo().window(oldUi) await driver.close() - await driver.switchTo().window(infoPage) - await driver.close() + if (infoPage !== newUi) { + await driver.switchTo().window(infoPage) + await driver.close() + } await driver.switchTo().window(newUi) await delay(regularDelayMs) - const [continueBtn] = await driver.findElements(By.css('.welcome-screen__button')) + const continueBtn = await findElement(driver, By.css('.welcome-screen__button')) await continueBtn.click() await delay(regularDelayMs) }) @@ -107,9 +112,9 @@ describe('MetaMask', function () { describe('Going through the first time flow', () => { it('accepts a secure password', async () => { - const [passwordBox] = await driver.findElements(By.css('.create-password #create-password')) - const [passwordBoxConfirm] = await driver.findElements(By.css('.create-password #confirm-password')) - const [button] = await driver.findElements(By.css('.create-password button')) + const passwordBox = await findElement(driver, By.css('.create-password #create-password')) + const passwordBoxConfirm = await findElement(driver, By.css('.create-password #confirm-password')) + const button = await findElement(driver, By.css('.create-password button')) await passwordBox.sendKeys('correct horse battery staple') await passwordBoxConfirm.sendKeys('correct horse battery staple') @@ -118,23 +123,23 @@ describe('MetaMask', function () { }) it('clicks through the unique image screen', async () => { - const [nextScreen] = await driver.findElements(By.css('.unique-image button')) + const nextScreen = await findElement(driver, By.css('.unique-image button')) await nextScreen.click() await delay(regularDelayMs) }) it('clicks through the privacy notice', async () => { - const [nextScreen] = await driver.findElements(By.css('.tou button')) + const nextScreen = await findElement(driver, By.css('.tou button')) await nextScreen.click() await delay(regularDelayMs) const canClickThrough = await driver.findElement(By.css('.tou button')).isEnabled() assert.equal(canClickThrough, false, 'disabled continue button') - const [bottomOfTos] = await driver.findElements(By.linkText('Attributions')) + const bottomOfTos = await findElement(driver, By.linkText('Attributions')) await driver.executeScript('arguments[0].scrollIntoView(true)', bottomOfTos) await delay(regularDelayMs) - const [acceptTos] = await driver.findElements(By.css('.tou button')) + const acceptTos = await findElement(driver, By.css('.tou button')) await acceptTos.click() await delay(regularDelayMs) }) @@ -142,7 +147,7 @@ describe('MetaMask', function () { let seedPhrase it('reveals the seed phrase', async () => { - const [revealSeedPhrase] = await driver.findElements(By.css('.backup-phrase__secret-blocker')) + const revealSeedPhrase = await findElement(driver, By.css('.backup-phrase__secret-blocker')) await revealSeedPhrase.click() await delay(regularDelayMs) @@ -150,7 +155,7 @@ describe('MetaMask', function () { assert.equal(seedPhrase.split(' ').length, 12) await delay(regularDelayMs) - const [nextScreen] = await driver.findElements(By.css('.backup-phrase button')) + const nextScreen = await findElement(driver, By.css('.backup-phrase button')) await nextScreen.click() await delay(regularDelayMs) }) @@ -158,62 +163,64 @@ describe('MetaMask', function () { it('can retype the seed phrase', async () => { const words = seedPhrase.split(' ') - const [word0] = await driver.findElements(By.xpath(`//button[contains(text(), '${words[0]}')]`)) + const word0 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[0]}')]`)) await word0.click() await delay(tinyDelayMs) - const [word1] = await driver.findElements(By.xpath(`//button[contains(text(), '${words[1]}')]`)) + const word1 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[1]}')]`)) await word1.click() await delay(tinyDelayMs) - const [word2] = await driver.findElements(By.xpath(`//button[contains(text(), '${words[2]}')]`)) + const word2 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[2]}')]`)) await word2.click() await delay(tinyDelayMs) - const [word3] = await driver.findElements(By.xpath(`//button[contains(text(), '${words[3]}')]`)) + const word3 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[3]}')]`)) await word3.click() await delay(tinyDelayMs) - const [word4] = await driver.findElements(By.xpath(`//button[contains(text(), '${words[4]}')]`)) + const word4 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[4]}')]`)) await word4.click() await delay(tinyDelayMs) - const [word5] = await driver.findElements(By.xpath(`//button[contains(text(), '${words[5]}')]`)) + const word5 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[5]}')]`)) await word5.click() await delay(tinyDelayMs) - const [word6] = await driver.findElements(By.xpath(`//button[contains(text(), '${words[6]}')]`)) + const word6 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[6]}')]`)) await word6.click() await delay(tinyDelayMs) - const [word7] = await driver.findElements(By.xpath(`//button[contains(text(), '${words[7]}')]`)) + const word7 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[7]}')]`)) await word7.click() await delay(tinyDelayMs) - const [word8] = await driver.findElements(By.xpath(`//button[contains(text(), '${words[8]}')]`)) + const word8 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[8]}')]`)) await word8.click() await delay(tinyDelayMs) - const [word9] = await driver.findElements(By.xpath(`//button[contains(text(), '${words[9]}')]`)) + const word9 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[9]}')]`)) await word9.click() await delay(tinyDelayMs) - const [word10] = await driver.findElements(By.xpath(`//button[contains(text(), '${words[10]}')]`)) + const word10 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[10]}')]`)) await word10.click() await delay(tinyDelayMs) - const [word11] = await driver.findElements(By.xpath(`//button[contains(text(), '${words[11]}')]`)) + const word11 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[11]}')]`)) await word11.click() await delay(tinyDelayMs) - const [confirm] = await driver.findElements(By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirm = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirm.click() await delay(regularDelayMs) }) it('clicks through the deposit modal', async () => { - const [closeModal] = await driver.findElements(By.css('.page-container__header-close')) + const buyModal = await driver.findElement(By.css('span .modal')) + const closeModal = await findElement(driver, By.css('.page-container__header-close')) await closeModal.click() + await driver.wait(until.stalenessOf(buyModal)) await delay(regularDelayMs) }) }) @@ -234,7 +241,7 @@ describe('MetaMask', function () { await driver.findElement(By.css('.account-menu__icon')).click() await delay(regularDelayMs) - const [logoutButton] = await driver.findElements(By.css('.account-menu__logout-button')) + const logoutButton = await findElement(driver, By.css('.account-menu__logout-button')) assert.equal(await logoutButton.getText(), 'Log out') await logoutButton.click() await delay(regularDelayMs) @@ -252,23 +259,23 @@ describe('MetaMask', function () { await driver.findElement(By.css('.account-menu__icon')).click() await delay(regularDelayMs) - const [createAccount] = await driver.findElements(By.xpath(`//div[contains(text(), 'Create Account')]`)) + const createAccount = await findElement(driver, By.xpath(`//div[contains(text(), 'Create Account')]`)) await createAccount.click() await delay(regularDelayMs) }) it('set account name', async () => { - const [accountName] = await driver.findElements(By.css('.new-account-create-form input')) + const accountName = await findElement(driver, By.css('.new-account-create-form input')) await accountName.sendKeys('2nd account') await delay(regularDelayMs) - const [create] = await driver.findElements(By.xpath(`//button[contains(text(), 'Create')]`)) + const create = await findElement(driver, By.xpath(`//button[contains(text(), 'Create')]`)) await create.click() await delay(regularDelayMs) }) it('should correct account name', async () => { - const [accountName] = await driver.findElements(By.css('.account-name')) + const accountName = await findElement(driver, By.css('.account-name')) assert.equal(await accountName.getText(), '2nd account') await delay(regularDelayMs) }) @@ -279,19 +286,19 @@ describe('MetaMask', function () { await driver.findElement(By.css('.account-menu__icon')).click() await delay(regularDelayMs) - const [logoutButton] = await driver.findElements(By.css('.account-menu__logout-button')) + const logoutButton = await findElement(driver, By.css('.account-menu__logout-button')) assert.equal(await logoutButton.getText(), 'Log out') await logoutButton.click() await delay(regularDelayMs) }) it('imports seed phrase', async () => { - const [restoreSeedLink] = await driver.findElements(By.css('.unlock-page__link--import')) + const restoreSeedLink = await findElement(driver, By.css('.unlock-page__link--import')) assert.equal(await restoreSeedLink.getText(), 'Import using account seed phrase') await restoreSeedLink.click() await delay(regularDelayMs) - const [seedTextArea] = await driver.findElements(By.css('textarea')) + const seedTextArea = await findElement(driver, By.css('textarea')) await seedTextArea.sendKeys(testSeedPhrase) await delay(regularDelayMs) @@ -302,7 +309,7 @@ describe('MetaMask', function () { }) it('balance renders', async () => { - const balance = await driver.findElement(By.css('.balance-display .token-amount')) + const balance = await findElement(driver, By.css('.balance-display .token-amount')) const tokenAmount = await balance.getText() assert.equal(tokenAmount, '100.000 ETH') await delay(regularDelayMs) @@ -311,41 +318,41 @@ describe('MetaMask', function () { describe('Send ETH from inside MetaMask', () => { it('starts to send a transaction', async function () { - const [sendButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Send')]`)) + const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`)) await sendButton.click() await delay(regularDelayMs) - const [inputAddress] = await driver.findElements(By.css('input[placeholder="Recipient Address"]')) - const [inputAmount] = await driver.findElements(By.css('.currency-display__input')) + const inputAddress = await findElement(driver, By.css('input[placeholder="Recipient Address"]')) + const inputAmount = await findElement(driver, By.css('.currency-display__input')) await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') await inputAmount.sendKeys('1') // Set the gas limit - const [configureGas] = await driver.findElements(By.css('.send-v2__gas-fee-display button')) + const configureGas = await findElement(driver, By.css('.send-v2__gas-fee-display button')) await configureGas.click() await delay(regularDelayMs) - const [save] = await driver.findElements(By.xpath(`//button[contains(text(), 'Save')]`)) + const save = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`)) await save.click() await delay(regularDelayMs) // Continue to next screen - const [nextScreen] = await driver.findElements(By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() await delay(regularDelayMs) }) it('confirms the transaction', async function () { - const [confirmButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() await delay(regularDelayMs) }) it('finds the transaction in the transactions list', async function () { - const transactions = await driver.findElements(By.css('.tx-list-item')) + const transactions = await findElements(driver, By.css('.tx-list-item')) assert.equal(transactions.length, 1) - const txValues = await driver.findElements(By.css('.tx-list-value')) + const txValues = await findElements(driver, By.css('.tx-list-value')) assert.equal(txValues.length, 1) assert.equal(await txValues[0].getText(), '1 ETH') }) @@ -360,7 +367,7 @@ describe('MetaMask', function () { await driver.switchTo().window(faucet) await delay(regularDelayMs) - const [send1eth] = await driver.findElements(By.xpath(`//button[contains(text(), '10 ether')]`)) + const send1eth = await findElement(driver, By.xpath(`//button[contains(text(), '10 ether')]`)) await send1eth.click() await delay(regularDelayMs) @@ -368,7 +375,7 @@ describe('MetaMask', function () { await loadExtension(driver, extensionId) await delay(regularDelayMs) - const [confirmButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() await delay(regularDelayMs) @@ -385,31 +392,32 @@ describe('MetaMask', function () { describe('Add existing token using search', () => { it('clicks on the Add Token button', async () => { - const [addToken] = await driver.findElements(By.xpath(`//button[contains(text(), 'Add Token')]`)) + const addToken = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Token')]`)) await addToken.click() await delay(regularDelayMs) }) it('can pick a token from the existing options', async () => { - const [tokenSearch] = await driver.findElements(By.css('input.add-token__input')) + const tokenSearch = await findElement(driver, By.css('#search-tokens')) await tokenSearch.sendKeys('BAT') await delay(regularDelayMs) - const [token] = await driver.findElements(By.xpath("//div[contains(text(), 'BAT')]")) + const token = await findElement(driver, By.xpath("//span[contains(text(), 'BAT')]")) await token.click() await delay(regularDelayMs) - const [nextScreen] = await driver.findElements(By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() await delay(regularDelayMs) - const [addTokens] = await driver.findElements(By.xpath(`//button[contains(text(), 'Add Tokens')]`)) + const addTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Tokens')]`)) await addTokens.click() await delay(largeDelayMs) }) it('renders the balance for the chosen token', async () => { - const balance = await driver.findElement(By.css('.tx-view .balance-display .token-amount')) + const balance = await findElement(driver, By.css('.tx-view .balance-display .token-amount')) + await driver.wait(until.elementTextIs(balance, '0BAT')) const tokenAmount = await balance.getText() assert.equal(tokenAmount, '0BAT') await delay(regularDelayMs) @@ -428,14 +436,14 @@ describe('MetaMask', function () { tokenName, tokenDecimal, tokenSymbol, - ] = await driver.findElements(By.css('input')) + ] = await findElements(driver, By.css('.form-control')) await totalSupply.sendKeys('100') await tokenName.sendKeys('Test') await tokenDecimal.sendKeys('0') await tokenSymbol.sendKeys('TST') - const [createToken] = await driver.findElements(By.xpath(`//button[contains(text(), 'Create Token')]`)) + const createToken = await findElement(driver, By.xpath(`//button[contains(text(), 'Create Token')]`)) await createToken.click() await delay(regularDelayMs) @@ -443,7 +451,7 @@ describe('MetaMask', function () { await loadExtension(driver, extensionId) await delay(regularDelayMs) - const [confirmButton] = await driver.findElements(By.xpath(`//button[contains(text(), 'Confirm')]`)) + const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() await delay(regularDelayMs) @@ -458,31 +466,32 @@ describe('MetaMask', function () { }) it('clicks on the Add Token button', async () => { - const [addToken] = await driver.findElements(By.xpath(`//button[contains(text(), 'Add Token')]`)) + const addToken = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Token')]`)) await addToken.click() await delay(regularDelayMs) }) it('picks the newly created Test token', async () => { - const [addCustomToken] = await driver.findElements(By.xpath("//div[contains(text(), 'Custom Token')]")) + const addCustomToken = await findElement(driver, By.xpath("//div[contains(text(), 'Custom Token')]")) await addCustomToken.click() await delay(regularDelayMs) - const [newTokenAddress] = await driver.findElements(By.css('.add-token__add-custom-form input')) + const newTokenAddress = await findElement(driver, By.css('#custom-address')) await newTokenAddress.sendKeys(tokenAddress) await delay(regularDelayMs) - const [nextScreen] = await driver.findElements(By.xpath(`//button[contains(text(), 'Next')]`)) + const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) await nextScreen.click() await delay(regularDelayMs) - const [addTokens] = await driver.findElements(By.xpath(`//button[contains(text(), 'Add Tokens')]`)) + const addTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Tokens')]`)) await addTokens.click() await delay(regularDelayMs) }) it('renders the balance for the new token', async () => { - const [balance] = await driver.findElements(By.css('.tx-view .balance-display .token-amount')) + const balance = await findElement(driver, By.css('.tx-view .balance-display .token-amount')) + await driver.wait(until.elementTextIs(balance, '100TST')) const tokenAmount = await balance.getText() assert.equal(tokenAmount, '100TST') await delay(regularDelayMs)