Merge pull request #3805 from MetaMask/ci-screens
CI - capture screenshotsfeature/default_network_editable
commit
40c3edb754
@ -0,0 +1,52 @@ |
|||||||
|
#!/usr/bin/env node
|
||||||
|
const request = require('request-promise') |
||||||
|
const { version } = require('../dist/chrome/manifest.json') |
||||||
|
|
||||||
|
const GITHUB_COMMENT_TOKEN = process.env.GITHUB_COMMENT_TOKEN |
||||||
|
console.log('GITHUB_COMMENT_TOKEN', GITHUB_COMMENT_TOKEN) |
||||||
|
const CIRCLE_PULL_REQUEST = process.env.CIRCLE_PULL_REQUEST |
||||||
|
console.log('CIRCLE_PULL_REQUEST', CIRCLE_PULL_REQUEST) |
||||||
|
const CIRCLE_SHA1 = process.env.CIRCLE_SHA1 |
||||||
|
console.log('CIRCLE_SHA1', CIRCLE_SHA1) |
||||||
|
const CIRCLE_BUILD_NUM = process.env.CIRCLE_BUILD_NUM |
||||||
|
console.log('CIRCLE_BUILD_NUM', CIRCLE_BUILD_NUM) |
||||||
|
|
||||||
|
const CIRCLE_PR_NUMBER = CIRCLE_PULL_REQUEST.split('/').pop() |
||||||
|
const SHORT_SHA1 = CIRCLE_SHA1.slice(0,7) |
||||||
|
const BUILD_LINK_BASE = `https://${CIRCLE_BUILD_NUM}-42009758-gh.circle-artifacts.com/0` |
||||||
|
|
||||||
|
const MASCARA = `${BUILD_LINK_BASE}/builds/mascara/home.html` |
||||||
|
const CHROME = `${BUILD_LINK_BASE}/builds/metamask-chrome-${version}.zip` |
||||||
|
const FIREFOX = `${BUILD_LINK_BASE}/builds/metamask-firefox-${version}.zip` |
||||||
|
const EDGE = `${BUILD_LINK_BASE}/builds/metamask-edge-${version}.zip` |
||||||
|
const OPERA = `${BUILD_LINK_BASE}/builds/metamask-opera-${version}.zip` |
||||||
|
const WALKTHROUGH = `${BUILD_LINK_BASE}/test-artifacts/screens/walkthrough%20%28en%29.gif` |
||||||
|
|
||||||
|
const commentBody = ` |
||||||
|
<details> |
||||||
|
<summary> |
||||||
|
Builds ready [${SHORT_SHA1}]: |
||||||
|
<a href="${MASCARA}">mascara</a>, |
||||||
|
<a href="${CHROME}">chrome</a>, |
||||||
|
<a href="${FIREFOX}">firefox</a>, |
||||||
|
<a href="${EDGE}">edge</a>, |
||||||
|
<a href="${OPERA}">opera</a> |
||||||
|
</summary> |
||||||
|
<image src="${WALKTHROUGH}"> |
||||||
|
</details> |
||||||
|
` |
||||||
|
|
||||||
|
const JSON_PAYLOAD = JSON.stringify({ body: commentBody }) |
||||||
|
const POST_COMMENT_URI = `https://api.github.com/repos/metamask/metamask-extension/issues/${CIRCLE_PR_NUMBER}/comments` |
||||||
|
console.log(`Announcement:\n${commentBody}`) |
||||||
|
console.log(`Posting to: ${POST_COMMENT_URI}`) |
||||||
|
|
||||||
|
request({ |
||||||
|
method: 'POST', |
||||||
|
uri: POST_COMMENT_URI, |
||||||
|
body: JSON_PAYLOAD, |
||||||
|
headers: { |
||||||
|
'User-Agent': 'metamaskbot', |
||||||
|
'Authorization': `token ${GITHUB_COMMENT_TOKEN}`, |
||||||
|
}, |
||||||
|
}) |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,18 @@ |
|||||||
|
require('chromedriver') |
||||||
|
const webdriver = require('selenium-webdriver') |
||||||
|
|
||||||
|
exports.delay = function delay (time) { |
||||||
|
return new Promise(resolve => setTimeout(resolve, time)) |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
exports.buildWebDriver = function buildWebDriver (extPath) { |
||||||
|
return new webdriver.Builder() |
||||||
|
.withCapabilities({ |
||||||
|
chromeOptions: { |
||||||
|
args: [`load-extension=${extPath}`], |
||||||
|
}, |
||||||
|
}) |
||||||
|
.forBrowser('chrome') |
||||||
|
.build() |
||||||
|
} |
@ -0,0 +1,230 @@ |
|||||||
|
const path = require('path') |
||||||
|
const fs = require('fs') |
||||||
|
const pify = require('pify') |
||||||
|
const mkdirp = require('mkdirp') |
||||||
|
const rimraf = require('rimraf') |
||||||
|
const webdriver = require('selenium-webdriver') |
||||||
|
const endOfStream = require('end-of-stream') |
||||||
|
const GIFEncoder = require('gifencoder') |
||||||
|
const pngFileStream = require('png-file-stream') |
||||||
|
const sizeOfPng = require('image-size/lib/types/png') |
||||||
|
const By = webdriver.By |
||||||
|
const { delay, buildWebDriver } = require('./func') |
||||||
|
const localesIndex = require('../../app/_locales/index.json') |
||||||
|
|
||||||
|
let driver |
||||||
|
|
||||||
|
captureAllScreens().catch((err) => { |
||||||
|
try { |
||||||
|
console.error(err) |
||||||
|
verboseReportOnFailure() |
||||||
|
driver.quit() |
||||||
|
} catch (err) { |
||||||
|
console.error(err) |
||||||
|
} |
||||||
|
process.exit(1) |
||||||
|
}) |
||||||
|
|
||||||
|
async function captureAllScreens() { |
||||||
|
let screenshotCount = 0 |
||||||
|
|
||||||
|
// common names
|
||||||
|
let button |
||||||
|
let tabs |
||||||
|
let element |
||||||
|
|
||||||
|
await cleanScreenShotDir() |
||||||
|
|
||||||
|
// setup selenium and install extension
|
||||||
|
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}/home.html`) |
||||||
|
await delay(500) |
||||||
|
tabs = await driver.getAllWindowHandles() |
||||||
|
await driver.switchTo().window(tabs[0]) |
||||||
|
await delay(1000) |
||||||
|
await setProviderType('localhost') |
||||||
|
await delay(300) |
||||||
|
|
||||||
|
// 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) |
||||||
|
|
||||||
|
// close metamask homepage and extra home.html
|
||||||
|
tabs = await driver.getAllWindowHandles() |
||||||
|
// metamask homepage is opened on prod, not dev
|
||||||
|
if (tabs.length > 2) { |
||||||
|
await driver.switchTo().window(tabs[2]) |
||||||
|
driver.close() |
||||||
|
} |
||||||
|
await driver.switchTo().window(tabs[1]) |
||||||
|
driver.close() |
||||||
|
await driver.switchTo().window(tabs[0]) |
||||||
|
await delay(300) |
||||||
|
await captureLanguageScreenShots('welcome-new-ui') |
||||||
|
|
||||||
|
// setup account
|
||||||
|
await delay(1000) |
||||||
|
await driver.findElement(By.css('body')).click() |
||||||
|
await delay(300) |
||||||
|
await captureLanguageScreenShots('welcome') |
||||||
|
|
||||||
|
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)')) |
||||||
|
passwordBox.sendKeys('123456789') |
||||||
|
passwordBoxConfirm.sendKeys('123456789') |
||||||
|
await delay(500) |
||||||
|
await captureLanguageScreenShots('choose-password-filled') |
||||||
|
|
||||||
|
await driver.findElement(By.css('button')).click() |
||||||
|
await delay(500) |
||||||
|
await captureLanguageScreenShots('unique account image') |
||||||
|
|
||||||
|
await driver.findElement(By.css('button')).click() |
||||||
|
await delay(500) |
||||||
|
await captureLanguageScreenShots('privacy note') |
||||||
|
|
||||||
|
await driver.findElement(By.css('button')).click() |
||||||
|
await delay(300) |
||||||
|
await captureLanguageScreenShots('terms') |
||||||
|
|
||||||
|
await delay(300) |
||||||
|
element = driver.findElement(By.linkText('Attributions')) |
||||||
|
await driver.executeScript('arguments[0].scrollIntoView(true)', element) |
||||||
|
await delay(300) |
||||||
|
await captureLanguageScreenShots('terms-scrolled') |
||||||
|
|
||||||
|
await driver.findElement(By.css('button')).click() |
||||||
|
await delay(300) |
||||||
|
await captureLanguageScreenShots('secret backup phrase') |
||||||
|
|
||||||
|
await driver.findElement(By.css('button')).click() |
||||||
|
await delay(300) |
||||||
|
await captureLanguageScreenShots('secret backup phrase') |
||||||
|
|
||||||
|
await driver.findElement(By.css('.backup-phrase__reveal-button')).click() |
||||||
|
await delay(300) |
||||||
|
await captureLanguageScreenShots('secret backup phrase - reveal') |
||||||
|
|
||||||
|
await driver.findElement(By.css('button')).click() |
||||||
|
await delay(300) |
||||||
|
await captureLanguageScreenShots('confirm secret backup phrase') |
||||||
|
|
||||||
|
// finish up
|
||||||
|
console.log('building gif...') |
||||||
|
await generateGif() |
||||||
|
await driver.quit() |
||||||
|
return |
||||||
|
|
||||||
|
//
|
||||||
|
// await button.click()
|
||||||
|
// await delay(700)
|
||||||
|
// this.seedPhase = await driver.findElement(By.css('.twelve-word-phrase')).getText()
|
||||||
|
// await captureScreenShot('seed phrase')
|
||||||
|
//
|
||||||
|
// const continueAfterSeedPhrase = await driver.findElement(By.css('button'))
|
||||||
|
// await continueAfterSeedPhrase.click()
|
||||||
|
// await delay(300)
|
||||||
|
// await captureScreenShot('main screen')
|
||||||
|
//
|
||||||
|
// await driver.findElement(By.css('.sandwich-expando')).click()
|
||||||
|
// await delay(500)
|
||||||
|
// await captureScreenShot('menu')
|
||||||
|
|
||||||
|
// await driver.findElement(By.css('#app-content > div > div:nth-child(3) > span > div > li:nth-child(3)')).click()
|
||||||
|
// await captureScreenShot('main screen')
|
||||||
|
// 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 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})`) |
||||||
|
} |
||||||
|
// 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) |
||||||
|
} |
||||||
|
|
||||||
|
// cleanup
|
||||||
|
await driver.quit() |
||||||
|
|
||||||
|
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) |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
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) |
||||||
|
} |
Loading…
Reference in new issue