aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/e2e/chrome/metamask.spec.js314
-rw-r--r--test/e2e/firefox/metamask.spec.js323
-rw-r--r--test/e2e/func.js8
-rw-r--r--test/e2e/metamask.spec.js145
-rw-r--r--test/integration/lib/mascara-first-time.js32
-rw-r--r--test/integration/lib/tx-list-items.js4
-rw-r--r--test/screens/new-ui.js7
-rw-r--r--test/unit/tx-controller-test.js30
8 files changed, 700 insertions, 163 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)
- }
-
-})
diff --git a/test/integration/lib/mascara-first-time.js b/test/integration/lib/mascara-first-time.js
index 5e07ab0b4..f43a30c74 100644
--- a/test/integration/lib/mascara-first-time.js
+++ b/test/integration/lib/mascara-first-time.js
@@ -1,5 +1,4 @@
const PASSWORD = 'password123'
-const reactTriggerChange = require('react-trigger-change')
const {
timeout,
findAsync,
@@ -11,6 +10,11 @@ async function runFirstTimeUsageTest (assert, done) {
const app = await queryAsync($, '#app-content')
+ // Used to set values on TextField input component
+ const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
+ window.HTMLInputElement.prototype, 'value'
+ ).set
+
await skipNotices(app)
const welcomeButton = (await findAsync(app, '.welcome-screen__button'))[0]
@@ -21,12 +25,14 @@ async function runFirstTimeUsageTest (assert, done) {
assert.equal(title, 'Create Password', 'create password screen')
// enter password
- const pwBox = (await findAsync(app, '.first-time-flow__input'))[0]
- const confBox = (await findAsync(app, '.first-time-flow__input'))[1]
- pwBox.value = PASSWORD
- confBox.value = PASSWORD
- reactTriggerChange(pwBox)
- reactTriggerChange(confBox)
+ const pwBox = (await findAsync(app, '#create-password'))[0]
+ const confBox = (await findAsync(app, '#confirm-password'))[0]
+
+ nativeInputValueSetter.call(pwBox, PASSWORD)
+ pwBox.dispatchEvent(new Event('input', { bubbles: true}))
+
+ nativeInputValueSetter.call(confBox, PASSWORD)
+ confBox.dispatchEvent(new Event('input', { bubbles: true}))
// Create Password
const createButton = (await findAsync(app, 'button.first-time-flow__button'))[0]
@@ -71,10 +77,16 @@ async function runFirstTimeUsageTest (assert, done) {
assert.ok(lock, 'Lock menu item found')
lock.click()
- const pwBox2 = (await findAsync(app, '#password-box'))[0]
- pwBox2.value = PASSWORD
+ await timeout(1000)
+
+ const pwBox2 = (await findAsync(app, '#password'))[0]
+ pwBox2.focus()
+ await timeout(1000)
+
+ nativeInputValueSetter.call(pwBox2, PASSWORD)
+ pwBox2.dispatchEvent(new Event('input', { bubbles: true}))
- const createButton2 = (await findAsync(app, 'button.primary'))[0]
+ const createButton2 = (await findAsync(app, 'button[type="submit"]'))[0]
createButton2.click()
const detail2 = (await findAsync(app, '.wallet-view'))[0]
diff --git a/test/integration/lib/tx-list-items.js b/test/integration/lib/tx-list-items.js
index 0c0c5a77f..4856b3852 100644
--- a/test/integration/lib/tx-list-items.js
+++ b/test/integration/lib/tx-list-items.js
@@ -21,7 +21,7 @@ async function runTxListItemsTest(assert, done) {
selectState.val('tx list items')
reactTriggerChange(selectState[0])
- const metamaskLogo = await queryAsync($, '.left-menu-wrapper')
+ const metamaskLogo = await queryAsync($, '.app-header__logo-container')
assert.ok(metamaskLogo[0], 'metamask logo present')
metamaskLogo[0].click()
@@ -46,7 +46,7 @@ async function runTxListItemsTest(assert, done) {
const failedTx = txListItems[4]
const failedTxRenderedStatus = await findAsync($(failedTx), '.tx-list-status')
assert.equal(failedTxRenderedStatus[0].textContent, 'Failed', 'failedTx has correct label')
-
+
const shapeShiftTx = txListItems[5]
const shapeShiftTxStatus = await findAsync($(shapeShiftTx), '.flex-column div:eq(1)')
assert.equal(shapeShiftTxStatus[0].textContent, 'No deposits received', 'shapeShiftTx has correct status')
diff --git a/test/screens/new-ui.js b/test/screens/new-ui.js
index 91b3a9633..6a8822eb3 100644
--- a/test/screens/new-ui.js
+++ b/test/screens/new-ui.js
@@ -39,8 +39,7 @@ async function captureAllScreens() {
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')
+ const extensionId = await driver.executeScript('return document.querySelector("extensions-manager").shadowRoot.querySelector("extensions-view-manager extensions-item-list").shadowRoot.querySelector("#container > div.items-container > extensions-item:nth-child(2)").getAttribute("id")')
await driver.get(`chrome-extension://${extensionId}/home.html`)
await delay(500)
tabs = await driver.getAllWindowHandles()
@@ -75,8 +74,8 @@ async function captureAllScreens() {
await driver.findElement(By.css('button')).click()
await captureLanguageScreenShots('create password')
- const passwordBox = await driver.findElement(By.css('input[type=password]:nth-of-type(1)'))
- const passwordBoxConfirm = await driver.findElement(By.css('input[type=password]:nth-of-type(2)'))
+ const passwordBox = await driver.findElement(By.css('input#create-password'))
+ const passwordBoxConfirm = await driver.findElement(By.css('input#confirm-password'))
passwordBox.sendKeys('123456789')
passwordBoxConfirm.sendKeys('123456789')
await delay(500)
diff --git a/test/unit/tx-controller-test.js b/test/unit/tx-controller-test.js
index 0b5c7226a..ddd921652 100644
--- a/test/unit/tx-controller-test.js
+++ b/test/unit/tx-controller-test.js
@@ -40,6 +40,36 @@ describe('Transaction Controller', function () {
txController.nonceTracker.getNonceLock = () => Promise.resolve({ nextNonce: 0, releaseLock: noop })
})
+ describe('#isNonceTaken', function () {
+ it('should return true', function (done) {
+ txController.txStateManager._saveTxList([
+ { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {nonce: 0, from: '0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'} },
+ { id: 2, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {nonce: 0, from: '0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'} },
+ { id: 3, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {nonce: 0, from: '0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'} },
+ ])
+ txController.isNonceTaken({txParams: {nonce:0, from:'0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'}})
+ .then((isNonceTaken) => {
+ assert(isNonceTaken)
+ done()
+ }).catch(done)
+
+ })
+ it('should return false', function (done) {
+ txController.txStateManager._saveTxList([
+ { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {nonce: 0, from: '0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'} },
+ { id: 2, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {nonce: 0, from: '0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'} },
+ { id: 3, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {nonce: 0, from: '0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'} },
+ ])
+
+ txController.isNonceTaken({txParams: {nonce:0, from:'0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'}})
+ .then((isNonceTaken) => {
+ assert(!isNonceTaken)
+ done()
+ }).catch(done)
+
+ })
+ })
+
describe('#getState', function () {
it('should return a state object with the right keys and datat types', function () {
const exposedState = txController.getState()