Created
November 6, 2021 13:48
-
-
Save mattzeunert/ae8d0eeedb16d9b3d80c9112f5a9676a to your computer and use it in GitHub Desktop.
Chrome DevTools User Flow Recording for GitHub Search
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'); | |
(async () => { | |
const browser = await puppeteer.launch(); | |
const page = await browser.newPage(); | |
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":1135,"height":338}) | |
} | |
{ | |
const targetPage = page; | |
const promises = []; | |
promises.push(targetPage.waitForNavigation()); | |
await targetPage.goto('https://github.com/'); | |
await Promise.all(promises); | |
} | |
{ | |
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"); | |
} | |
} | |
{ | |
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 browser.close(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment