2018-03-30 02:02:40 +02:00
const path = require ( 'path' )
const fs = require ( 'fs' )
const pify = require ( 'pify' )
const mkdirp = require ( 'mkdirp' )
2018-03-30 09:09:39 +02:00
const rimraf = require ( 'rimraf' )
2018-03-30 02:02:40 +02:00
const webdriver = require ( 'selenium-webdriver' )
const endOfStream = require ( 'end-of-stream' )
2018-05-22 10:56:52 +02:00
const clipboardy = require ( 'clipboardy' )
const Ethjs = require ( 'ethjs' )
2018-03-30 02:02:40 +02:00
const GIFEncoder = require ( 'gifencoder' )
const pngFileStream = require ( 'png-file-stream' )
const sizeOfPng = require ( 'image-size/lib/types/png' )
const By = webdriver . By
2018-03-30 09:48:37 +02:00
const localesIndex = require ( '../../app/_locales/index.json' )
2018-05-30 07:13:58 +02:00
const { delay , buildChromeWebDriver , buildFirefoxWebdriver , installWebExt , getExtensionIdChrome , getExtensionIdFirefox } = require ( '../e2e/func' )
2018-05-22 10:56:52 +02:00
const eth = new Ethjs ( new Ethjs . HttpProvider ( 'http://localhost:8545' ) )
2018-03-30 02:02:40 +02:00
2018-03-30 23:39:43 +02:00
let driver
2018-05-22 10:56:52 +02:00
let screenshotCount = 0
captureAllScreens ( )
. then ( async ( ) => {
// build screenshots into gif
console . log ( 'building gif...' )
await generateGif ( )
2018-03-30 23:39:43 +02:00
2018-05-22 10:56:52 +02:00
await driver . quit ( )
process . exit ( )
} )
. catch ( async ( err ) => {
2018-03-30 23:39:43 +02:00
try {
console . error ( err )
2018-05-22 10:56:52 +02:00
verboseReportOnFailure ( { title : 'something broke' } )
2018-03-30 23:48:41 +02:00
} catch ( err ) {
console . error ( err )
2018-03-30 23:39:43 +02:00
}
2018-05-22 10:56:52 +02:00
await driver . quit ( )
2018-03-30 23:48:41 +02:00
process . exit ( 1 )
2018-03-30 23:39:43 +02:00
} )
2018-03-30 02:02:40 +02:00
2018-05-22 10:56:52 +02:00
async function captureAllScreens ( ) {
2018-03-30 09:09:39 +02:00
// common names
let button
let tabs
let element
await cleanScreenShotDir ( )
2018-03-30 02:02:40 +02:00
const extPath = path . resolve ( 'dist/chrome' )
2018-05-30 07:13:58 +02:00
driver = buildChromeWebDriver ( extPath )
const extensionId = await getExtensionIdChrome ( driver )
2018-03-30 09:09:39 +02:00
await driver . get ( ` chrome-extension:// ${ extensionId } /home.html ` )
2018-03-30 02:02:40 +02:00
await delay ( 500 )
2018-03-30 09:09:39 +02:00
tabs = await driver . getAllWindowHandles ( )
2018-03-30 02:02:40 +02:00
await driver . switchTo ( ) . window ( tabs [ 0 ] )
2018-03-31 03:14:26 +02:00
await delay ( 1000 )
2018-03-30 20:16:08 +02:00
await setProviderType ( 'localhost' )
2018-03-31 02:36:43 +02:00
await delay ( 300 )
2018-03-30 02:02:40 +02:00
// click try new ui
await driver . findElement ( By . css ( '#app-content > div > div.app-primary.from-right > div > div.flex-row.flex-center.flex-grow > p' ) ) . click ( )
await delay ( 300 )
2018-03-30 09:09:39 +02:00
// close metamask homepage and extra home.html
tabs = await driver . getAllWindowHandles ( )
2018-03-30 20:16:08 +02:00
// metamask homepage is opened on prod, not dev
if ( tabs . length > 2 ) {
await driver . switchTo ( ) . window ( tabs [ 2 ] )
driver . close ( )
}
2018-03-30 09:09:39 +02:00
await driver . switchTo ( ) . window ( tabs [ 1 ] )
driver . close ( )
await driver . switchTo ( ) . window ( tabs [ 0 ] )
2018-03-30 02:02:40 +02:00
await delay ( 300 )
2018-03-30 09:48:37 +02:00
await captureLanguageScreenShots ( 'welcome-new-ui' )
2018-03-30 09:09:39 +02:00
// setup account
await delay ( 1000 )
await driver . findElement ( By . css ( 'body' ) ) . click ( )
2018-03-30 02:02:40 +02:00
await delay ( 300 )
2018-03-30 09:48:37 +02:00
await captureLanguageScreenShots ( 'welcome' )
2018-03-30 02:02:40 +02:00
2018-03-30 09:09:39 +02:00
await driver . findElement ( By . css ( 'button' ) ) . click ( )
2018-03-30 09:48:37 +02:00
await captureLanguageScreenShots ( 'create password' )
2018-03-30 09:09:39 +02:00
2018-05-22 10:56:52 +02:00
const password = '123456789'
2018-05-13 05:53:40 +02:00
const passwordBox = await driver . findElement ( By . css ( 'input#create-password' ) )
const passwordBoxConfirm = await driver . findElement ( By . css ( 'input#confirm-password' ) )
2018-05-22 10:56:52 +02:00
passwordBox . sendKeys ( password )
passwordBoxConfirm . sendKeys ( password )
2018-03-30 09:09:39 +02:00
await delay ( 500 )
2018-03-30 09:48:37 +02:00
await captureLanguageScreenShots ( 'choose-password-filled' )
2018-03-30 02:02:40 +02:00
2018-03-30 09:09:39 +02:00
await driver . findElement ( By . css ( 'button' ) ) . click ( )
await delay ( 500 )
2018-03-30 09:48:37 +02:00
await captureLanguageScreenShots ( 'unique account image' )
2018-03-30 02:02:40 +02:00
2018-03-30 09:09:39 +02:00
await driver . findElement ( By . css ( 'button' ) ) . click ( )
await delay ( 500 )
2018-03-30 09:48:37 +02:00
await captureLanguageScreenShots ( 'privacy note' )
2018-03-30 02:02:40 +02:00
2018-03-30 09:09:39 +02:00
await driver . findElement ( By . css ( 'button' ) ) . click ( )
2018-03-30 02:02:40 +02:00
await delay ( 300 )
2018-03-30 09:48:37 +02:00
await captureLanguageScreenShots ( 'terms' )
2018-03-30 02:02:40 +02:00
await delay ( 300 )
2018-03-30 09:09:39 +02:00
element = driver . findElement ( By . linkText ( 'Attributions' ) )
2018-03-30 02:02:40 +02:00
await driver . executeScript ( 'arguments[0].scrollIntoView(true)' , element )
await delay ( 300 )
2018-03-30 09:48:37 +02:00
await captureLanguageScreenShots ( 'terms-scrolled' )
2018-03-30 02:02:40 +02:00
2018-03-30 09:09:39 +02:00
await driver . findElement ( By . css ( 'button' ) ) . click ( )
2018-03-30 02:02:40 +02:00
await delay ( 300 )
2018-03-30 09:48:37 +02:00
await captureLanguageScreenShots ( 'secret backup phrase' )
2018-03-30 02:02:40 +02:00
2018-03-30 09:09:39 +02:00
await driver . findElement ( By . css ( 'button' ) ) . click ( )
await delay ( 300 )
2018-03-30 09:48:37 +02:00
await captureLanguageScreenShots ( 'secret backup phrase' )
2018-03-30 02:02:40 +02:00
2018-03-30 09:09:39 +02:00
await driver . findElement ( By . css ( '.backup-phrase__reveal-button' ) ) . click ( )
await delay ( 300 )
2018-03-30 09:48:37 +02:00
await captureLanguageScreenShots ( 'secret backup phrase - reveal' )
2018-03-30 02:02:40 +02:00
2018-05-22 10:56:52 +02:00
const seedPhrase = await driver . findElement ( By . css ( '.backup-phrase__secret-words' ) ) . getText ( )
const seedPhraseWords = seedPhrase . split ( ' ' )
2018-03-30 09:09:39 +02:00
await driver . findElement ( By . css ( 'button' ) ) . click ( )
2018-03-30 02:02:40 +02:00
await delay ( 300 )
2018-03-30 09:48:37 +02:00
await captureLanguageScreenShots ( 'confirm secret backup phrase' )
2018-03-30 02:02:40 +02:00
2018-05-22 10:56:52 +02:00
// enter seed phrase
const seedPhraseButtons = await driver . findElements ( By . css ( '.backup-phrase__confirm-seed-options > button' ) )
const seedPhraseButtonWords = await Promise . all ( seedPhraseButtons . map ( button => button . getText ( ) ) )
for ( let targetWord of seedPhraseWords ) {
const wordIndex = seedPhraseButtonWords . indexOf ( targetWord )
if ( wordIndex === - 1 ) throw new Error ( ` Captured seed phrase word " ${ targetWord } " not in found seed phrase button options ${ seedPhraseButtonWords . join ( ' ' ) } ` )
await driver . findElement ( By . css ( ` .backup-phrase__confirm-seed-options > button:nth-child( ${ wordIndex + 1 } ) ` ) ) . click ( )
await delay ( 100 )
2018-03-30 09:48:37 +02:00
}
2018-05-22 10:56:52 +02:00
await captureLanguageScreenShots ( 'confirm secret backup phrase - words selected correctly' )
2018-03-30 09:48:37 +02:00
2018-05-22 10:56:52 +02:00
await driver . findElement ( By . css ( '.backup-phrase__content-wrapper .first-time-flow__button' ) ) . click ( )
await delay ( 300 )
await captureLanguageScreenShots ( 'metamask post-initialize greeter screen deposit ether' )
2018-03-30 20:16:08 +02:00
2018-05-22 10:56:52 +02:00
await driver . findElement ( By . css ( '.page-container__header-close' ) ) . click ( )
await delay ( 300 )
await captureLanguageScreenShots ( 'metamask account main screen' )
2018-03-30 09:48:37 +02:00
2018-05-22 10:56:52 +02:00
// account details + export private key
await driver . findElement ( By . css ( '.wallet-view__name-container > .wallet-view__details-button' ) ) . click ( )
await delay ( 300 )
await captureLanguageScreenShots ( 'metamask account detail screen' )
2018-03-30 02:02:40 +02:00
2018-05-22 10:56:52 +02:00
await driver . findElement ( By . css ( '.account-modal__button:nth-of-type(2)' ) ) . click ( )
await delay ( 300 )
await captureLanguageScreenShots ( 'metamask account detail export private key screen - initial' )
2018-03-30 09:09:39 +02:00
2018-05-22 10:56:52 +02:00
await driver . findElement ( By . css ( '.private-key-password > input' ) ) . sendKeys ( password )
await delay ( 300 )
await captureLanguageScreenShots ( 'metamask account detail export private key screen - password entered' )
2018-03-30 02:02:40 +02:00
2018-05-22 10:56:52 +02:00
await driver . findElement ( By . css ( '.btn-primary--lg.export-private-key__button' ) ) . click ( )
await delay ( 300 )
await captureLanguageScreenShots ( 'metamask account detail export private key screen - reveal key' )
2018-03-30 02:02:40 +02:00
2018-05-22 10:56:52 +02:00
await driver . findElement ( By . css ( '.export-private-key__button' ) ) . click ( )
await delay ( 300 )
await captureLanguageScreenShots ( 'metamask account detail export private key screen - done' )
2018-03-30 02:02:40 +02:00
2018-05-22 10:56:52 +02:00
// get eth from Ganache
// const viewAddressButton = await driver.findElement(By.css('.wallet-view__address'))
// await driver.actions({ bridge: true }).move({ origin: viewAddressButton }).perform()
// console.log('driver.actions', driver.actions({ bridge: true }))
// await delay(300)
// await captureLanguageScreenShots('metamask home - hover copy address')
await driver . findElement ( By . css ( '.wallet-view__address' ) ) . click ( )
await delay ( 100 )
await captureLanguageScreenShots ( 'metamask home - hover copy address' )
const primaryAddress = clipboardy . readSync ( )
await requestEther ( primaryAddress )
// wait for block polling
await delay ( 10000 )
await captureLanguageScreenShots ( 'metamask home - has ether' )
}
async function captureLanguageScreenShots ( label ) {
const nonEnglishLocales = localesIndex . filter ( localeMeta => localeMeta . code !== 'en' )
// take english shot
await captureScreenShot ( ` ${ label } (en) ` )
for ( let localeMeta of nonEnglishLocales ) {
// set locale and take shot
await setLocale ( localeMeta . code )
await delay ( 300 )
await captureScreenShot ( ` ${ label } ( ${ localeMeta . code } ) ` )
2018-03-30 02:02:40 +02:00
}
2018-05-22 10:56:52 +02:00
// return locale to english
await setLocale ( 'en' )
await delay ( 300 )
}
async function setLocale ( code ) {
await driver . executeScript ( 'window.metamask.updateCurrentLocale(arguments[0])' , code )
}
async function setProviderType ( type ) {
await driver . executeScript ( 'window.metamask.setProviderType(arguments[0])' , type )
}
2018-03-30 02:02:40 +02:00
2018-05-22 10:56:52 +02:00
async function cleanScreenShotDir ( ) {
await pify ( rimraf ) ( ` ./test-artifacts/screens/ ` )
}
async function captureScreenShot ( label ) {
const shotIndex = screenshotCount . toString ( ) . padStart ( 4 , '0' )
screenshotCount ++
const artifactDir = ` ./test-artifacts/screens/ `
await pify ( mkdirp ) ( artifactDir )
// capture screenshot
const screenshot = await driver . takeScreenshot ( )
await pify ( fs . writeFile ) ( ` ${ artifactDir } / ${ shotIndex } - ${ label } .png ` , screenshot , { encoding : 'base64' } )
}
async function generateGif ( ) {
// calculate screenshot size
const screenshot = await driver . takeScreenshot ( )
const pngBuffer = Buffer . from ( screenshot , 'base64' )
const size = sizeOfPng . calculate ( pngBuffer )
// read only the english pngs into gif
const encoder = new GIFEncoder ( size . width , size . height )
const stream = pngFileStream ( './test-artifacts/screens/* (en).png' )
. pipe ( encoder . createWriteStream ( { repeat : 0 , delay : 1000 , quality : 10 } ) )
. pipe ( fs . createWriteStream ( './test-artifacts/screens/walkthrough (en).gif' ) )
// wait for end
await pify ( endOfStream ) ( stream )
2018-03-31 00:03:49 +02:00
}
2018-03-30 23:39:43 +02:00
2018-03-31 00:03:49 +02:00
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 )
2018-03-30 02:02:40 +02:00
}
2018-05-22 10:56:52 +02:00
async function requestEther ( address ) {
const accounts = await eth . accounts ( )
await eth . sendTransaction ( { from : accounts [ 0 ] , to : address , value : 1 * 1e18 , data : '0x0' } )
}