diff options
Diffstat (limited to 'test/e2e')
-rw-r--r-- | test/e2e/chrome/metamask.spec.js | 314 | ||||
-rw-r--r-- | test/e2e/firefox/metamask.spec.js | 323 | ||||
-rw-r--r-- | test/e2e/func.js | 8 | ||||
-rw-r--r-- | test/e2e/metamask.spec.js | 145 |
4 files changed, 643 insertions, 147 deletions
diff --git a/test/e2e/chrome/metamask.spec.js b/test/e2e/chrome/metamask.spec.js new file mode 100644 index 000000000..b17d4c818 --- /dev/null +++ b/test/e2e/chrome/metamask.spec.js @@ -0,0 +1,314 @@ +const fs = require('fs') +const mkdirp = require('mkdirp') +const path = require('path') +const assert = require('assert') +const pify = require('pify') +const webdriver = require('selenium-webdriver') +const until = require('selenium-webdriver/lib/until') +const By = webdriver.By +const { delay, buildChromeWebDriver } = require('../func') + +describe('Metamask popup page', function () { + let driver, accountAddress, tokenAddress, extensionId + + this.timeout(0) + + before(async function () { + const extPath = path.resolve('dist/chrome') + driver = buildChromeWebDriver(extPath) + await driver.get('chrome://extensions') + await delay(500) + }) + + afterEach(async function () { + if (this.currentTest.state === 'failed') { + await verboseReportOnFailure(this.currentTest) + } + }) + + after(async function () { + await driver.quit() + }) + + describe('Setup', function () { + + it('switches to Chrome extensions list', async function () { + const tabs = await driver.getAllWindowHandles() + await driver.switchTo().window(tabs[0]) + await delay(300) + }) + + it(`selects MetaMask's extension id and opens it in the current tab`, async function () { + extensionId = await getExtensionId() + await driver.get(`chrome-extension://${extensionId}/popup.html`) + await delay(500) + }) + + it('sets provider type to localhost', async function () { + await driver.wait(until.elementLocated(By.css('#app-content')), 300) + await setProviderType('localhost') + }) + }) + + describe('Account Creation', () => { + + it('matches MetaMask title', async () => { + const title = await driver.getTitle() + assert.equal(title, 'MetaMask', 'title matches MetaMask') + }) + + it('shows privacy notice', async () => { + await driver.wait(async () => { + const privacyHeader = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div.flex-column.flex-center.flex-grow > h3')).getText() + assert.equal(privacyHeader, 'PRIVACY NOTICE', 'shows privacy notice') + return privacyHeader === 'PRIVACY NOTICE' + }, 300) + await driver.findElement(By.css('button')).click() + }) + + it('show terms of use', async () => { + await driver.wait(async () => { + const terms = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div.flex-column.flex-center.flex-grow > h3')).getText() + assert.equal(terms, 'TERMS OF USE', 'shows terms of use') + return terms === 'TERMS OF USE' + }) + }) + + it('checks if the TOU button is disabled', async () => { + const button = await driver.findElement(By.css('button')).isEnabled() + assert.equal(button, false, 'disabled continue button') + const element = await driver.findElement(By.linkText('Attributions')) + await driver.executeScript('arguments[0].scrollIntoView(true)', element) + await delay(300) + }) + + it('allows the button to be clicked when scrolled to the bottom of TOU', async () => { + const button = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div.flex-column.flex-center.flex-grow > button')) + const buttonEnabled = await button.isEnabled() + assert.equal(buttonEnabled, true, 'enabled continue button') + await button.click() + }) + + it('accepts password with length of eight', async () => { + const passwordBox = await driver.findElement(By.id('password-box')) + const passwordBoxConfirm = await driver.findElement(By.id('password-box-confirm')) + const button = await driver.findElements(By.css('button')) + + await passwordBox.sendKeys('123456789') + await passwordBoxConfirm.sendKeys('123456789') + await button[0].click() + await delay(500) + }) + + it('shows value was created and seed phrase', async () => { + await delay(300) + const seedPhrase = await driver.findElement(By.css('.twelve-word-phrase')).getText() + assert.equal(seedPhrase.split(' ').length, 12) + const continueAfterSeedPhrase = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > button:nth-child(4)')) + assert.equal(await continueAfterSeedPhrase.getText(), `I'VE COPIED IT SOMEWHERE SAFE`) + await continueAfterSeedPhrase.click() + await delay(300) + }) + + it('shows account address', async function () { + accountAddress = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > div > div:nth-child(1) > flex-column > div.flex-row > div')).getText() + }) + + it('logs out of the vault', async () => { + await driver.findElement(By.css('.sandwich-expando')).click() + await delay(500) + const logoutButton = await driver.findElement(By.css('#app-content > div > div:nth-child(3) > span > div > li:nth-child(3)')) + assert.equal(await logoutButton.getText(), 'Log Out') + await logoutButton.click() + }) + + it('accepts account password after lock', async () => { + await delay(500) + await driver.findElement(By.id('password-box')).sendKeys('123456789') + await driver.findElement(By.css('button')).click() + await delay(500) + }) + + it('shows QR code option', async () => { + await delay(300) + await driver.findElement(By.css('.fa-ellipsis-h')).click() + await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div > div:nth-child(1) > flex-column > div.name-label > div > span > i > div > div > li:nth-child(3)')).click() + await delay(300) + }) + + it('checks QR code address is the same as account details address', async () => { + const QRaccountAddress = await driver.findElement(By.css('.ellip-address')).getText() + assert.equal(accountAddress.toLowerCase(), QRaccountAddress) + await driver.findElement(By.css('.fa-arrow-left')).click() + await delay(500) + }) + }) + + describe('Import Ganache seed phrase', function () { + it('logs out', async function () { + await driver.findElement(By.css('.sandwich-expando')).click() + await delay(200) + const logOut = await driver.findElement(By.css('#app-content > div > div:nth-child(3) > span > div > li:nth-child(3)')) + assert.equal(await logOut.getText(), 'Log Out') + await logOut.click() + await delay(300) + }) + + it('restores from seed phrase', async function () { + const restoreSeedLink = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > div.flex-row.flex-center.flex-grow > p')) + assert.equal(await restoreSeedLink.getText(), 'Restore from seed phrase') + await restoreSeedLink.click() + await delay(100) + }) + + it('adds seed phrase', async function () { + const testSeedPhrase = 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent' + const seedTextArea = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > textarea')) + await seedTextArea.sendKeys(testSeedPhrase) + + await driver.findElement(By.id('password-box')).sendKeys('123456789') + await driver.findElement(By.id('password-box-confirm')).sendKeys('123456789') + await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > div > button:nth-child(2)')).click() + await delay(500) + }) + + it('balance renders', async function () { + await delay(200) + const balance = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div > div.flex-row > div.ether-balance.ether-balance-amount > div > div > div:nth-child(1) > div:nth-child(1)')) + assert.equal(await balance.getText(), '100.000') + await delay(200) + }) + + it('sends transaction', async function () { + const sendButton = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div > div.flex-row > button:nth-child(4)')) + assert.equal(await sendButton.getText(), 'SEND') + await sendButton.click() + await delay(200) + }) + + it('adds recipient address and amount', async function () { + const sendTranscationScreen = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > h3:nth-child(2)')).getText() + assert.equal(sendTranscationScreen, 'SEND TRANSACTION') + const inputAddress = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section:nth-child(3) > div > input')) + const inputAmmount = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section:nth-child(4) > input')) + await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') + await inputAmmount.sendKeys('10') + await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section:nth-child(4) > button')).click() + await delay(300) + }) + + it('confirms transaction', async function () { + await delay(300) + await driver.findElement(By.css('#pending-tx-form > div.flex-row.flex-space-around.conf-buttons > input')).click() + await delay(500) + }) + + it('finds the transaction in the transactions list', async function () { + const tranasactionAmount = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > section > section > div > div > div > div.ether-balance.ether-balance-amount > div > div > div > div:nth-child(1)')) + assert.equal(await tranasactionAmount.getText(), '10.0') + }) + }) + + describe('Token Factory', function () { + + it('navigates to token factory', async function () { + await driver.get('http://tokenfactory.surge.sh/') + }) + + it('navigates to create token contract link', async function () { + const createToken = await driver.findElement(By.css('#bs-example-navbar-collapse-1 > ul > li:nth-child(3) > a')) + await createToken.click() + }) + + it('adds input for token', async function () { + const totalSupply = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(5) > input')) + const tokenName = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(6) > input')) + const tokenDecimal = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(7) > input')) + const tokenSymbol = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(8) > input')) + const createToken = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > button')) + + await totalSupply.sendKeys('100') + await tokenName.sendKeys('Test') + await tokenDecimal.sendKeys('0') + await tokenSymbol.sendKeys('TST') + await createToken.click() + await delay(1000) + }) + + it('confirms transaction in MetaMask popup', async function () { + const windowHandles = await driver.getAllWindowHandles() + await driver.switchTo().window(windowHandles[windowHandles.length - 1]) + const metamaskSubmit = await driver.findElement(By.css('#pending-tx-form > div.flex-row.flex-space-around.conf-buttons > input')) + await metamaskSubmit.click() + await delay(1000) + }) + + it('switches back to Token Factory to grab the token contract address', async function () { + const windowHandles = await driver.getAllWindowHandles() + await driver.switchTo().window(windowHandles[0]) + const tokenContactAddress = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > span:nth-child(3)')) + tokenAddress = await tokenContactAddress.getText() + await delay(500) + }) + + it('navigates back to MetaMask popup in the tab', async function () { + await driver.get(`chrome-extension://${extensionId}/popup.html`) + await delay(700) + }) + }) + + describe('Add Token', function () { + it('switches to the add token screen', async function () { + const tokensTab = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section > div > div.inactiveForm.pointer')) + assert.equal(await tokensTab.getText(), 'TOKENS') + await tokensTab.click() + await delay(300) + }) + + it('navigates to the add token screen', async function () { + const addTokenButton = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section > div.full-flex-height > div > button')) + assert.equal(await addTokenButton.getText(), 'ADD TOKEN') + await addTokenButton.click() + }) + + it('checks add token screen rendered', async function () { + const addTokenScreen = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div.section-title.flex-row.flex-center > h2')) + assert.equal(await addTokenScreen.getText(), 'ADD TOKEN') + }) + + it('adds token parameters', async function () { + const tokenContractAddress = await driver.findElement(By.css('#token-address')) + await tokenContractAddress.sendKeys(tokenAddress) + await delay(300) + await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div.flex-column.flex-justify-center.flex-grow.select-none > div > button')).click() + await delay(100) + }) + + it('checks the token balance', async function () { + const tokenBalance = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > section > div.full-flex-height > ol > li:nth-child(2) > h3')) + assert.equal(await tokenBalance.getText(), '100 TST') + }) + }) + + async function getExtensionId () { + const extension = await driver.executeScript('return document.querySelector("extensions-manager").shadowRoot.querySelector("extensions-view-manager extensions-item-list").shadowRoot.querySelector("extensions-item:nth-child(2)").getAttribute("id")') + return extension + } + + async function setProviderType (type) { + await driver.executeScript('window.metamask.setProviderType(arguments[0])', type) + } + + async function verboseReportOnFailure (test) { + const artifactDir = `./test-artifacts/chrome/${test.title}` + const filepathBase = `${artifactDir}/test-failure` + await pify(mkdirp)(artifactDir) + // capture screenshot + const screenshot = await driver.takeScreenshot() + await pify(fs.writeFile)(`${filepathBase}-screenshot.png`, screenshot, { encoding: 'base64' }) + // capture dom source + const htmlSource = await driver.getPageSource() + await pify(fs.writeFile)(`${filepathBase}-dom.html`, htmlSource) + } + +}) diff --git a/test/e2e/firefox/metamask.spec.js b/test/e2e/firefox/metamask.spec.js new file mode 100644 index 000000000..c75b1a9b5 --- /dev/null +++ b/test/e2e/firefox/metamask.spec.js @@ -0,0 +1,323 @@ +const fs = require('fs') +const mkdirp = require('mkdirp') +const path = require('path') +const assert = require('assert') +const pify = require('pify') +const webdriver = require('selenium-webdriver') +const Command = require('selenium-webdriver/lib/command').Command +const By = webdriver.By +const { delay, buildFirefoxWebdriver } = require('../func') + +describe('', function () { + let driver, accountAddress, tokenAddress, extensionId + + this.timeout(0) + + before(async function () { + const extPath = path.resolve('dist/firefox') + driver = buildFirefoxWebdriver() + installWebExt(driver, extPath) + await delay(700) + }) + + afterEach(async function () { + if (this.currentTest.state === 'failed') { + await verboseReportOnFailure(this.currentTest) + } + }) + + after(async function () { + await driver.quit() + }) + + describe('Setup', function () { + + it('switches to Firefox addon list', async function () { + await driver.get('about:debugging#addons') + await delay(1000) + }) + + it(`selects MetaMask's extension id and opens it in the current tab`, async function () { + const tabs = await driver.getAllWindowHandles() + await driver.switchTo().window(tabs[0]) + extensionId = await driver.findElement(By.css('dd.addon-target-info-content:nth-child(6) > span:nth-child(1)')).getText() + await driver.get(`moz-extension://${extensionId}/popup.html`) + await delay(500) + }) + + it('sets provider type to localhost', async function () { + await setProviderType('localhost') + await delay(300) + }) + }) + + describe('Account Creation', () => { + + it('matches MetaMask title', async () => { + const title = await driver.getTitle() + assert.equal(title, 'MetaMask', 'title matches MetaMask') + }) + + it('shows privacy notice', async () => { + await delay(300) + const privacy = await driver.findElement(By.css('.terms-header')).getText() + assert.equal(privacy, 'PRIVACY NOTICE', 'shows privacy notice') + await driver.findElement(By.css('button')).click() + await delay(300) + }) + + it('show terms of use', async () => { + await delay(300) + const terms = await driver.findElement(By.css('.terms-header')).getText() + assert.equal(terms, 'TERMS OF USE', 'shows terms of use') + await delay(300) + }) + + it('checks if the TOU button is disabled', async () => { + const button = await driver.findElement(By.css('button')).isEnabled() + assert.equal(button, false, 'disabled continue button') + const element = await driver.findElement(By.linkText('Attributions')) + await driver.executeScript('arguments[0].scrollIntoView(true)', element) + await delay(300) + }) + + it('allows the button to be clicked when scrolled to the bottom of TOU', async () => { + const button = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div.flex-column.flex-center.flex-grow > button')) + await delay(300) + const buttonEnabled = await button.isEnabled() + assert.equal(buttonEnabled, true, 'enabled continue button') + await delay(200) + await button.click() + }) + + it('accepts password with length of eight', async () => { + const passwordBox = await driver.findElement(By.id('password-box')) + const passwordBoxConfirm = await driver.findElement(By.id('password-box-confirm')) + const button = await driver.findElements(By.css('button')) + + await passwordBox.sendKeys('123456789') + await passwordBoxConfirm.sendKeys('123456789') + await button[0].click() + await delay(500) + }) + + it('shows value was created and seed phrase', async () => { + await delay(300) + const seedPhrase = await driver.findElement(By.css('.twelve-word-phrase')).getText() + assert.equal(seedPhrase.split(' ').length, 12) + const continueAfterSeedPhrase = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > button:nth-child(4)')) + assert.equal(await continueAfterSeedPhrase.getText(), `I'VE COPIED IT SOMEWHERE SAFE`) + await continueAfterSeedPhrase.click() + await delay(300) + }) + + it('shows account address', async function () { + accountAddress = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > div > div:nth-child(1) > flex-column > div.flex-row > div')).getText() + }) + + it('logs out of the vault', async () => { + await driver.findElement(By.css('.sandwich-expando')).click() + await delay(500) + const logoutButton = await driver.findElement(By.css('#app-content > div > div:nth-child(3) > span > div > li:nth-child(3)')) + assert.equal(await logoutButton.getText(), 'Log Out') + await logoutButton.click() + }) + + it('accepts account password after lock', async () => { + await delay(500) + await driver.findElement(By.id('password-box')).sendKeys('123456789') + await driver.findElement(By.id('password-box')).sendKeys(webdriver.Key.ENTER) + await delay(500) + }) + + it('shows QR code option', async () => { + await delay(300) + await driver.findElement(By.css('.fa-ellipsis-h')).click() + await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div > div:nth-child(1) > flex-column > div.name-label > div > span > i > div > div > li:nth-child(3)')).click() + await delay(300) + }) + + it('checks QR code address is the same as account details address', async () => { + const QRaccountAddress = await driver.findElement(By.css('.ellip-address')).getText() + assert.equal(accountAddress.toLowerCase(), QRaccountAddress) + await driver.findElement(By.css('.fa-arrow-left')).click() + await delay(500) + }) + }) + + describe('Import Ganache seed phrase', function () { + it('logs out', async function () { + await driver.findElement(By.css('.sandwich-expando')).click() + await delay(200) + const logOut = await driver.findElement(By.css('#app-content > div > div:nth-child(3) > span > div > li:nth-child(3)')) + assert.equal(await logOut.getText(), 'Log Out') + await logOut.click() + await delay(300) + }) + + it('restores from seed phrase', async function () { + const restoreSeedLink = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > div.flex-row.flex-center.flex-grow > p')) + assert.equal(await restoreSeedLink.getText(), 'Restore from seed phrase') + await restoreSeedLink.click() + await delay(100) + }) + + it('adds seed phrase', async function () { + const testSeedPhrase = 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent' + const seedTextArea = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > textarea')) + await seedTextArea.sendKeys(testSeedPhrase) + + await driver.findElement(By.id('password-box')).sendKeys('123456789') + await driver.findElement(By.id('password-box-confirm')).sendKeys('123456789') + await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > div > button:nth-child(2)')).click() + await delay(500) + }) + + it('balance renders', async function () { + await delay(200) + const balance = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div > div.flex-row > div.ether-balance.ether-balance-amount > div > div > div:nth-child(1) > div:nth-child(1)')) + assert.equal(await balance.getText(), '100.000') + await delay(200) + }) + + it('sends transaction', async function () { + const sendButton = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div > div.flex-row > button:nth-child(4)')) + assert.equal(await sendButton.getText(), 'SEND') + await sendButton.click() + await delay(200) + }) + + it('adds recipient address and amount', async function () { + const sendTranscationScreen = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > h3:nth-child(2)')).getText() + assert.equal(sendTranscationScreen, 'SEND TRANSACTION') + const inputAddress = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section:nth-child(3) > div > input')) + const inputAmmount = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section:nth-child(4) > input')) + await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') + await inputAmmount.sendKeys('10') + await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section:nth-child(4) > button')).click() + await delay(300) + }) + + it('confirms transaction', async function () { + await delay(300) + await driver.findElement(By.css('#pending-tx-form > div.flex-row.flex-space-around.conf-buttons > input')).click() + await delay(500) + }) + + it('finds the transaction in the transactions list', async function () { + const tranasactionAmount = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > section > section > div > div > div > div.ether-balance.ether-balance-amount > div > div > div > div:nth-child(1)')) + assert.equal(await tranasactionAmount.getText(), '10.0') + }) + }) + + describe('Token Factory', function () { + + it('navigates to token factory', async function () { + await driver.get('http://tokenfactory.surge.sh/') + }) + + it('navigates to create token contract link', async function () { + const createToken = await driver.findElement(By.css('#bs-example-navbar-collapse-1 > ul > li:nth-child(3) > a')) + await createToken.click() + }) + + it('adds input for token', async function () { + const totalSupply = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(5) > input')) + const tokenName = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(6) > input')) + const tokenDecimal = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(7) > input')) + const tokenSymbol = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(8) > input')) + const createToken = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > button')) + + await totalSupply.sendKeys('100') + await tokenName.sendKeys('Test') + await tokenDecimal.sendKeys('0') + await tokenSymbol.sendKeys('TST') + await createToken.click() + await delay(1000) + }) + + // There is an issue with blank confirmation window, but the button is still there and the driver is able to clicked (?.?) + it('confirms transaction in MetaMask popup', async function () { + const windowHandles = await driver.getAllWindowHandles() + await driver.switchTo().window(windowHandles[windowHandles.length - 1]) + const metamaskSubmit = await driver.findElement(By.css('#pending-tx-form > div.flex-row.flex-space-around.conf-buttons > input')) + await metamaskSubmit.click() + await delay(1000) + }) + + it('switches back to Token Factory to grab the token contract address', async function () { + const windowHandles = await driver.getAllWindowHandles() + await driver.switchTo().window(windowHandles[0]) + const tokenContactAddress = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > span:nth-child(3)')) + tokenAddress = await tokenContactAddress.getText() + await delay(500) + }) + + it('navigates back to MetaMask popup in the tab', async function () { + await driver.get(`moz-extension://${extensionId}/popup.html`) + await delay(700) + }) + }) + + describe('Add Token', function () { + it('switches to the add token screen', async function () { + const tokensTab = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section > div > div.inactiveForm.pointer')) + assert.equal(await tokensTab.getText(), 'TOKENS') + await tokensTab.click() + await delay(300) + }) + + it('navigates to the add token screen', async function () { + const addTokenButton = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section > div.full-flex-height > div > button')) + assert.equal(await addTokenButton.getText(), 'ADD TOKEN') + await addTokenButton.click() + }) + + it('checks add token screen rendered', async function () { + const addTokenScreen = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div.section-title.flex-row.flex-center > h2')) + assert.equal(await addTokenScreen.getText(), 'ADD TOKEN') + }) + + it('adds token parameters', async function () { + const tokenContractAddress = await driver.findElement(By.css('#token-address')) + await tokenContractAddress.sendKeys(tokenAddress) + await delay(300) + await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div.flex-column.flex-justify-center.flex-grow.select-none > div > button')).click() + await delay(100) + }) + + it('checks the token balance', async function () { + const tokenBalance = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > section > div.full-flex-height > ol > li:nth-child(2) > h3')) + assert.equal(await tokenBalance.getText(), '100 TST') + }) + }) + + async function setProviderType(type) { + await driver.executeScript('window.metamask.setProviderType(arguments[0])', type) + } + + async function verboseReportOnFailure(test) { + const artifactDir = `./test-artifacts/firefox/${test.title}` + const filepathBase = `${artifactDir}/test-failure` + await pify(mkdirp)(artifactDir) + // capture screenshot + const screenshot = await driver.takeScreenshot() + await pify(fs.writeFile)(`${filepathBase}-screenshot.png`, screenshot, { encoding: 'base64' }) + // capture dom source + const htmlSource = await driver.getPageSource() + await pify(fs.writeFile)(`${filepathBase}-dom.html`, htmlSource) + } + +}) + +async function installWebExt (driver, extension) { + const cmd = await new Command('moz-install-web-ext') + .setParameter('path', path.resolve(extension)) + .setParameter('temporary', true) + + await driver.getExecutor() + .defineCommand(cmd.getName(), 'POST', '/session/:sessionId/moz/addon/install') + + return await driver.schedule(cmd, 'installWebExt(' + extension + ')') +} + diff --git a/test/e2e/func.js b/test/e2e/func.js index 733225565..4ad0ea615 100644 --- a/test/e2e/func.js +++ b/test/e2e/func.js @@ -1,4 +1,5 @@ require('chromedriver') +require('geckodriver') const webdriver = require('selenium-webdriver') exports.delay = function delay (time) { @@ -6,13 +7,16 @@ exports.delay = function delay (time) { } -exports.buildWebDriver = function buildWebDriver (extPath) { +exports.buildChromeWebDriver = function buildChromeWebDriver (extPath) { return new webdriver.Builder() .withCapabilities({ chromeOptions: { args: [`load-extension=${extPath}`], }, }) - .forBrowser('chrome') .build() } + +exports.buildFirefoxWebdriver = function buildFirefoxWebdriver (extPath) { + return new webdriver.Builder().build() +} diff --git a/test/e2e/metamask.spec.js b/test/e2e/metamask.spec.js deleted file mode 100644 index e0ff2a57e..000000000 --- a/test/e2e/metamask.spec.js +++ /dev/null @@ -1,145 +0,0 @@ -const fs = require('fs') -const mkdirp = require('mkdirp') -const path = require('path') -const assert = require('assert') -const pify = require('pify') -const webdriver = require('selenium-webdriver') -const By = webdriver.By -const { delay, buildWebDriver } = require('./func') - -describe('Metamask popup page', function () { - let driver - this.seedPhase - this.accountAddress - this.timeout(0) - - before(async function () { - const extPath = path.resolve('dist/chrome') - driver = buildWebDriver(extPath) - await driver.get('chrome://extensions-frame') - const elems = await driver.findElements(By.css('.extension-list-item-wrapper')) - const extensionId = await elems[1].getAttribute('id') - await driver.get(`chrome-extension://${extensionId}/popup.html`) - await delay(500) - }) - - afterEach(async function () { - if (this.currentTest.state === 'failed') { - await verboseReportOnFailure(this.currentTest) - } - }) - - after(async function () { - await driver.quit() - }) - - describe('#onboarding', () => { - it('should open Metamask.io', async function () { - const tabs = await driver.getAllWindowHandles() - await driver.switchTo().window(tabs[0]) - await delay(300) - await setProviderType('localhost') - await delay(300) - }) - - it('should match title', async () => { - const title = await driver.getTitle() - assert.equal(title, 'MetaMask', 'title matches MetaMask') - }) - - it('should show privacy notice', async () => { - const privacy = await driver.findElement(By.css('.terms-header')).getText() - assert.equal(privacy, 'PRIVACY NOTICE', 'shows privacy notice') - driver.findElement(By.css('button')).click() - await delay(300) - }) - - it('should show terms of use', async () => { - await delay(300) - const terms = await driver.findElement(By.css('.terms-header')).getText() - assert.equal(terms, 'TERMS OF USE', 'shows terms of use') - await delay(300) - }) - - it('should be unable to continue without scolling throught the terms of use', async () => { - const button = await driver.findElement(By.css('button')).isEnabled() - assert.equal(button, false, 'disabled continue button') - const element = driver.findElement(By.linkText( - 'Attributions' - )) - await driver.executeScript('arguments[0].scrollIntoView(true)', element) - await delay(300) - }) - - it('should be able to continue when scrolled to the bottom of terms of use', async () => { - const button = await driver.findElement(By.css('button')) - const buttonEnabled = await button.isEnabled() - await delay(500) - assert.equal(buttonEnabled, true, 'enabled continue button') - await button.click() - await delay(300) - }) - - it('should accept password with length of eight', async () => { - const passwordBox = await driver.findElement(By.id('password-box')) - const passwordBoxConfirm = await driver.findElement(By.id('password-box-confirm')) - const button = driver.findElement(By.css('button')) - - passwordBox.sendKeys('123456789') - passwordBoxConfirm.sendKeys('123456789') - await delay(500) - await button.click() - }) - - it('should show value was created and seed phrase', async () => { - await delay(700) - this.seedPhase = await driver.findElement(By.css('.twelve-word-phrase')).getText() - const continueAfterSeedPhrase = await driver.findElement(By.css('button')) - await continueAfterSeedPhrase.click() - await delay(300) - }) - - it('should show lock account', async () => { - await driver.findElement(By.css('.sandwich-expando')).click() - await delay(500) - await driver.findElement(By.css('#app-content > div > div:nth-child(3) > span > div > li:nth-child(3)')).click() - }) - - it('should accept account password after lock', async () => { - await delay(500) - await driver.findElement(By.id('password-box')).sendKeys('123456789') - await driver.findElement(By.css('button')).click() - await delay(500) - }) - - it('should show QR code option', async () => { - await delay(300) - await driver.findElement(By.css('.fa-ellipsis-h')).click() - await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div > div:nth-child(1) > flex-column > div.name-label > div > span > i > div > div > li:nth-child(3)')).click() - await delay(300) - }) - - it('should show the account address', async () => { - this.accountAddress = await driver.findElement(By.css('.ellip-address')).getText() - await driver.findElement(By.css('.fa-arrow-left')).click() - await delay(500) - }) - }) - - async function setProviderType(type) { - await driver.executeScript('window.metamask.setProviderType(arguments[0])', type) - } - - async function verboseReportOnFailure(test) { - const artifactDir = `./test-artifacts/${test.title}` - const filepathBase = `${artifactDir}/test-failure` - await pify(mkdirp)(artifactDir) - // capture screenshot - const screenshot = await driver.takeScreenshot() - await pify(fs.writeFile)(`${filepathBase}-screenshot.png`, screenshot, { encoding: 'base64' }) - // capture dom source - const htmlSource = await driver.getPageSource() - await pify(fs.writeFile)(`${filepathBase}-dom.html`, htmlSource) - } - -}) |