Created
November 8, 2021 14:15
-
-
Save mattzeunert/c0e56d442f49f36c1469523cc0a34af3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const puppeteer = require('puppeteer'); | |
const { startFlow } = require('lighthouse/lighthouse-core/fraggle-rock/api.js'); | |
const fs = require("fs"); | |
(async () => { | |
const browser = await puppeteer.launch({ headless: false }); | |
const page = await browser.newPage(); | |
const flow = await startFlow(page, { | |
name: 'Go to homepage', | |
configContext: { | |
settingsOverrides: { | |
screenEmulation: { | |
mobile: false, | |
width: 1350, | |
height: 940, | |
deviceScaleFactor: 1, | |
disabled: false, | |
}, | |
formFactor: "desktop", | |
}, | |
}, | |
}); | |
async function waitForSelectors(selectors, frame) { | |
for (const selector of selectors) { | |
try { | |
return await waitForSelector(selector, frame); | |
} catch (err) { | |
console.error(err); | |
} | |
} | |
throw new Error('Could not find element for selectors: ' + JSON.stringify(selectors)); | |
} | |
async function waitForSelector(selector, frame) { | |
if (selector instanceof Array) { | |
let element = null; | |
for (const part of selector) { | |
if (!element) { | |
element = await frame.waitForSelector(part); | |
} else { | |
element = await element.$(part); | |
} | |
if (!element) { | |
throw new Error('Could not find element: ' + part); | |
} | |
element = (await element.evaluateHandle(el => el.shadowRoot ? el.shadowRoot : el)).asElement(); | |
} | |
if (!element) { | |
throw new Error('Could not find element: ' + selector.join('|')); | |
} | |
return element; | |
} | |
const element = await frame.waitForSelector(selector); | |
if (!element) { | |
throw new Error('Could not find element: ' + selector); | |
} | |
return element; | |
} | |
async function waitForElement(step, frame) { | |
const count = step.count || 1; | |
const operator = step.operator || '>='; | |
const comp = { | |
'==': (a, b) => a === b, | |
'>=': (a, b) => a >= b, | |
'<=': (a, b) => a <= b, | |
}; | |
const compFn = comp[operator]; | |
await waitForFunction(async () => { | |
const elements = await querySelectorsAll(step.selectors, frame); | |
return compFn(elements.length, count); | |
}); | |
} | |
async function querySelectorsAll(selectors, frame) { | |
for (const selector of selectors) { | |
const result = await querySelectorAll(selector, frame); | |
if (result.length) { | |
return result; | |
} | |
} | |
return []; | |
} | |
async function querySelectorAll(selector, frame) { | |
if (selector instanceof Array) { | |
let elements = []; | |
let i = 0; | |
for (const part of selector) { | |
if (i === 0) { | |
elements = await frame.$$(part); | |
} else { | |
const tmpElements = elements; | |
elements = []; | |
for (const el of tmpElements) { | |
elements.push(...(await el.$$(part))); | |
} | |
} | |
if (elements.length === 0) { | |
return []; | |
} | |
const tmpElements = []; | |
for (const el of elements) { | |
const newEl = (await el.evaluateHandle(el => el.shadowRoot ? el.shadowRoot : el)).asElement(); | |
if (newEl) { | |
tmpElements.push(newEl); | |
} | |
} | |
elements = tmpElements; | |
i++; | |
} | |
return elements; | |
} | |
const element = await frame.$$(selector); | |
if (!element) { | |
throw new Error('Could not find element: ' + selector); | |
} | |
return element; | |
} | |
async function waitForFunction(fn) { | |
let isActive = true; | |
setTimeout(() => { | |
isActive = false; | |
}, 5000); | |
while (isActive) { | |
const result = await fn(); | |
if (result) { | |
return; | |
} | |
await new Promise(resolve => setTimeout(resolve, 100)); | |
} | |
throw new Error('Timed out'); | |
} | |
{ | |
const targetPage = page; | |
await targetPage.setViewport({"width":1350,"height":940}) | |
} | |
{ | |
await flow.navigate("https://github.com/") | |
const targetPage = page; | |
const promises = []; | |
promises.push(targetPage.waitForNavigation()); | |
await targetPage.goto('https://github.com/'); | |
await Promise.all(promises); | |
} | |
{ | |
await flow.startTimespan({stepName: 'Enter search term'}); | |
const targetPage = page; | |
const element = await waitForSelectors([["aria/Search GitHub"],["body > div.position-relative.js-header-wrapper > header > div > div.HeaderMenu.HeaderMenu--logged-out.position-fixed.top-0.right-0.bottom-0.height-fit.position-lg-relative.d-lg-flex.flex-justify-between.flex-items-center.flex-auto > div.d-lg-flex.flex-items-center.px-3.px-lg-0.text-center.text-lg-left > div.d-lg-flex.min-width-0.mb-3.mb-lg-0 > div > div > form > label > input.form-control.input-sm.header-search-input.jump-to-field.js-jump-to-field.js-site-search-focus.js-navigation-enable.jump-to-field-active.jump-to-dropdown-visible"]], targetPage); | |
await element.click({ offset: { x: 74.5, y: 24} }); | |
} | |
{ | |
const targetPage = page; | |
const element = await waitForSelectors([["aria/Search GitHub"],["body > div.position-relative.js-header-wrapper > header > div > div.HeaderMenu.HeaderMenu--logged-out.position-fixed.top-0.right-0.bottom-0.height-fit.position-lg-relative.d-lg-flex.flex-justify-between.flex-items-center.flex-auto > div.d-lg-flex.flex-items-center.px-3.px-lg-0.text-center.text-lg-left > div.d-lg-flex.min-width-0.mb-3.mb-lg-0 > div > div > form > label > input.form-control.input-sm.header-search-input.jump-to-field.js-jump-to-field.js-site-search-focus.js-navigation-enable.jump-to-field-active.jump-to-dropdown-visible"]], targetPage); | |
const type = await element.evaluate(el => el.type); | |
if (["textarea","select-one","text","url","tel","search","password","number","email"].includes(type)) { | |
await element.type('react'); | |
} else { | |
await element.focus(); | |
await element.evaluate((el, value) => { | |
el.value = value; | |
el.dispatchEvent(new Event('input', { bubbles: true })); | |
el.dispatchEvent(new Event('change', { bubbles: true })); | |
}, "react"); | |
} | |
await flow.endTimespan(); | |
await flow.snapshot({stepName: "Search term entered"}) | |
} | |
{ | |
await flow.startTimespan({stepName: 'Go to search result'}); | |
const targetPage = page; | |
const promises = []; | |
promises.push(targetPage.waitForNavigation()); | |
const element = await waitForSelectors([["aria/react"],["#jump-to-suggestion-search-global > a > div.jump-to-suggestion-name.js-jump-to-suggestion-name.flex-auto.overflow-hidden.text-left.no-wrap.css-truncate.css-truncate-target"]], targetPage); | |
await element.click({ offset: { x: 41.5, y: 4} }); | |
await Promise.all(promises); | |
} | |
{ | |
const targetPage = page; | |
const promises = []; | |
promises.push(targetPage.waitForNavigation()); | |
const element = await waitForSelectors([["aria/facebook/react"],["#js-pjax-container > div > div.col-12.col-md-9.float-left.px-2.pt-3.pt-md-0.codesearch-results > div > ul > li:nth-child(1) > div.mt-n1.flex-auto > div.d-flex > div > a"]], targetPage); | |
await element.click({ offset: { x: 62.5, y: 12.21875} }); | |
await Promise.all(promises); | |
await flow.endTimespan(); | |
await flow.snapshot({stepName: "Search result page"}) | |
} | |
const report = flow.generateReport(); | |
fs.writeFileSync('report.html', report); | |
await browser.close(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment