Skip to content

Commit

Permalink
Wait until element is clickable before clicking in e2e tests (MetaMas…
Browse files Browse the repository at this point in the history
…k#7823)

* Wait until element is clickable before clicking in e2e tests

A new `findClickableElement` has been added to the webdriver to allow
finding an element and blocking until it's both visible and enabled.
This is now used by the pre-existing `clickElement` method as well.

All cases where something is clicked in the e2e tests have been
updated to use one of these methods, to ensure we don't run into
intermittent failures when loading screens take longer than usual.
  • Loading branch information
Gudahtt committed Jan 15, 2020
1 parent c53a40c commit be08cfe
Show file tree
Hide file tree
Showing 12 changed files with 347 additions and 646 deletions.
69 changes: 23 additions & 46 deletions test/e2e/address-book.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,61 +55,51 @@ describe('MetaMask', function () {
describe('Going through the first time flow', () => {
it('clicks the continue button on the welcome screen', async () => {
await driver.findElement(By.css('.welcome-page__header'))
const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`))
await welcomeScreenBtn.click()
await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`))
await driver.delay(largeDelayMs)
})

it('clicks the "Create New Wallet" option', async () => {
const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`))
await customRpcButton.click()
await driver.clickElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`))
await driver.delay(largeDelayMs)
})

it('clicks the "No thanks" option on the metametrics opt-in screen', async () => {
const optOutButton = await driver.findElement(By.css('.btn-default'))
await optOutButton.click()
await driver.clickElement(By.css('.btn-default'))
await driver.delay(largeDelayMs)
})

it('accepts a secure password', async () => {
const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password'))
const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password'))
const button = await driver.findElement(By.css('.first-time-flow__form button'))

await passwordBox.sendKeys('correct horse battery staple')
await passwordBoxConfirm.sendKeys('correct horse battery staple')

const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox'))
await tosCheckBox.click()

await button.click()
await driver.clickElement(By.css('.first-time-flow__checkbox'))
await driver.clickElement(By.css('.first-time-flow__form button'))
await driver.delay(regularDelayMs)
})

let seedPhrase

it('reveals the seed phrase', async () => {
const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button')
const revealSeedPhraseButton = await driver.findElement(byRevealButton, 10000)
await revealSeedPhraseButton.click()
await driver.clickElement(byRevealButton)
await driver.delay(regularDelayMs)

const revealedSeedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words'))
seedPhrase = await revealedSeedPhrase.getText()
assert.equal(seedPhrase.split(' ').length, 12)
await driver.delay(regularDelayMs)

const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`))
await nextScreen.click()
await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.next.message}')]`))
await driver.delay(regularDelayMs)
})

async function clickWordAndWait (word) {
const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]`
const word0 = await driver.findElement(By.xpath(xpath))

await word0.click()
await driver.clickElement(By.xpath(xpath))
await driver.delay(tinyDelayMs)
}

Expand All @@ -120,33 +110,30 @@ describe('MetaMask', function () {
await clickWordAndWait(word)
}

const confirm = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`))
await confirm.click()
await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`))
await driver.delay(regularDelayMs)
})

it('clicks through the success screen', async () => {
await driver.findElement(By.xpath(`//div[contains(text(), 'Congratulations')]`))
const doneButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`))
await doneButton.click()
await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`))
await driver.delay(regularDelayMs)
})
})

describe('Import seed phrase', () => {
it('logs out of the vault', async () => {
const accountMenu = await driver.findElement(By.css('.account-menu__icon'))
await accountMenu.click()
await driver.clickElement(By.css('.account-menu__icon'))
await driver.delay(regularDelayMs)

const logoutButton = await driver.findElement(By.css('.account-menu__logout-button'))
const logoutButton = await driver.findClickableElement(By.css('.account-menu__logout-button'))
assert.equal(await logoutButton.getText(), 'Log out')
await logoutButton.click()
await driver.delay(regularDelayMs)
})

it('imports seed phrase', async () => {
const restoreSeedLink = await driver.findElement(By.css('.unlock-page__link--import'))
const restoreSeedLink = await driver.findClickableElement(By.css('.unlock-page__link--import'))
assert.equal(await restoreSeedLink.getText(), 'Import using account seed phrase')
await restoreSeedLink.click()
await driver.delay(regularDelayMs)
Expand All @@ -160,8 +147,7 @@ describe('MetaMask', function () {

await passwordInputs[0].sendKeys('correct horse battery staple')
await passwordInputs[1].sendKeys('correct horse battery staple')
const restoreButton = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.restore.message}')]`))
await restoreButton.click()
await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.restore.message}')]`))
await driver.delay(regularDelayMs)
})

Expand All @@ -174,24 +160,21 @@ describe('MetaMask', function () {

describe('Adds an entry to the address book and sends eth to that address', () => {
it('starts a send transaction', async function () {
const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`))
await sendButton.click()
await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`))
await driver.delay(regularDelayMs)

const inputAddress = await driver.findElement(By.css('input[placeholder="Search, public address (0x), or ENS"]'))
await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970')
await driver.delay(regularDelayMs)

const addToAddressBookButton = await driver.findElement(By.css('.dialog.send__dialog.dialog--message'))
await addToAddressBookButton.click()
await driver.clickElement(By.css('.dialog.send__dialog.dialog--message'))

const addressBookAddModal = await driver.findElement(By.css('span .modal'))
await driver.findElement(By.css('.add-to-address-book-modal'))
const addressBookInput = await driver.findElement(By.css('.add-to-address-book-modal__input'))
await addressBookInput.sendKeys('Test Name 1')
await driver.delay(tinyDelayMs)
const addressBookSaveButton = await driver.findElement(By.css('.add-to-address-book-modal__footer .btn-primary'))
await addressBookSaveButton.click()
await driver.clickElement(By.css('.add-to-address-book-modal__footer .btn-primary'))

await driver.wait(until.stalenessOf(addressBookAddModal))

Expand All @@ -203,14 +186,12 @@ describe('MetaMask', function () {
await driver.delay(regularDelayMs)

// Continue to next screen
const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`))
await nextScreen.click()
await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`))
await driver.delay(regularDelayMs)
})

it('confirms the transaction', async function () {
const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`))
await confirmButton.click()
await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`))
await driver.delay(largeDelayMs * 2)
})

Expand All @@ -227,31 +208,27 @@ describe('MetaMask', function () {

describe('Sends to an address book entry', () => {
it('starts a send transaction by clicking address book entry', async function () {
const sendButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Send')]`))
await sendButton.click()
await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`))
await driver.delay(regularDelayMs)

const recipientRow = await driver.findElement(By.css('.send__select-recipient-wrapper__group-item'))
const recipientRowTitle = await driver.findElement(By.css('.send__select-recipient-wrapper__group-item__title'))
const recipientRowTitleString = await recipientRowTitle.getText()
assert.equal(recipientRowTitleString, 'Test Name 1')

await recipientRow.click()
await driver.clickElement(By.css('.send__select-recipient-wrapper__group-item'))

await driver.delay(regularDelayMs)
const inputAmount = await driver.findElement(By.css('.unit-input__input'))
await inputAmount.sendKeys('2')
await driver.delay(regularDelayMs)

// Continue to next screen
const nextScreen = await driver.findElement(By.xpath(`//button[contains(text(), 'Next')]`))
await nextScreen.click()
await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`))
await driver.delay(regularDelayMs)
})

it('confirms the transaction', async function () {
const confirmButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Confirm')]`))
await confirmButton.click()
await driver.clickElement(By.xpath(`//button[contains(text(), 'Confirm')]`))
await driver.delay(largeDelayMs * 2)
})

Expand Down
40 changes: 13 additions & 27 deletions test/e2e/ethereum-on.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,45 +54,37 @@ describe('MetaMask', function () {
describe('Going through the first time flow, but skipping the seed phrase challenge', () => {
it('clicks the continue button on the welcome screen', async () => {
await driver.findElement(By.css('.welcome-page__header'))
const welcomeScreenBtn = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`))
await welcomeScreenBtn.click()
await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`))
await driver.delay(largeDelayMs)
})

it('clicks the "Create New Wallet" option', async () => {
const customRpcButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`))
await customRpcButton.click()
await driver.clickElement(By.xpath(`//button[contains(text(), 'Create a Wallet')]`))
await driver.delay(largeDelayMs)
})

it('clicks the "No thanks" option on the metametrics opt-in screen', async () => {
const optOutButton = await driver.findElement(By.css('.btn-default'))
await optOutButton.click()
await driver.clickElement(By.css('.btn-default'))
await driver.delay(largeDelayMs)
})

it('accepts a secure password', async () => {
const passwordBox = await driver.findElement(By.css('.first-time-flow__form #create-password'))
const passwordBoxConfirm = await driver.findElement(By.css('.first-time-flow__form #confirm-password'))
const button = await driver.findElement(By.css('.first-time-flow__form button'))

await passwordBox.sendKeys('correct horse battery staple')
await passwordBoxConfirm.sendKeys('correct horse battery staple')

const tosCheckBox = await driver.findElement(By.css('.first-time-flow__checkbox'))
await tosCheckBox.click()

await button.click()
await driver.clickElement(By.css('.first-time-flow__checkbox'))
await driver.clickElement(By.css('.first-time-flow__form button'))
await driver.delay(largeDelayMs)
})

it('skips the seed phrase challenge', async () => {
const button = await driver.findElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`))
await button.click()
await driver.clickElement(By.xpath(`//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`))
await driver.delay(regularDelayMs)

const detailsButton = await driver.findElement(By.css('.account-details__details-button'))
await detailsButton.click()
await driver.clickElement(By.css('.account-details__details-button'))
await driver.delay(regularDelayMs)
})

Expand All @@ -101,8 +93,7 @@ describe('MetaMask', function () {
publicAddress = await addressInput.getAttribute('value')
const accountModal = await driver.findElement(By.css('span .modal'))

const accountModalClose = await driver.findElement(By.css('.account-modal-close'))
await accountModalClose.click()
await driver.clickElement(By.css('.account-modal-close'))

await driver.wait(until.stalenessOf(accountModal))
await driver.delay(regularDelayMs)
Expand All @@ -119,8 +110,7 @@ describe('MetaMask', function () {
await driver.openNewPage('http://127.0.0.1:8080/')
await driver.delay(regularDelayMs)

const connectButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Connect')]`))
await connectButton.click()
await driver.clickElement(By.xpath(`//button[contains(text(), 'Connect')]`))

await driver.delay(regularDelayMs)

Expand All @@ -135,11 +125,9 @@ describe('MetaMask', function () {

await driver.delay(regularDelayMs)

const accountButton = await driver.findElement(By.css('.permissions-connect-choose-account__account'))
await accountButton.click()
await driver.clickElement(By.css('.permissions-connect-choose-account__account'))

const submitButton = await driver.findElement(By.xpath(`//button[contains(text(), 'Submit')]`))
await submitButton.click()
await driver.clickElement(By.xpath(`//button[contains(text(), 'Submit')]`))

await driver.waitUntilXWindowHandles(2)
await driver.switchToWindow(dapp)
Expand All @@ -155,12 +143,10 @@ describe('MetaMask', function () {
it('changes the network', async () => {
await driver.switchToWindow(extension)

const networkDropdown = await driver.findElement(By.css('.network-name'))
await networkDropdown.click()
await driver.clickElement(By.css('.network-name'))
await driver.delay(regularDelayMs)

const ropstenButton = await driver.findElement(By.xpath(`//span[contains(text(), 'Ropsten')]`))
await ropstenButton.click()
await driver.clickElement(By.xpath(`//span[contains(text(), 'Ropsten')]`))
await driver.delay(largeDelayMs)
})

Expand Down
Loading

0 comments on commit be08cfe

Please sign in to comment.