519c411db0
* feat: sync and update with all changes from fork * refactor: extract clipboard copy logic into custom hook * fix: correct spelling of DEFAULT_REFRESH_FREQUENCY_MS in Stamps and WalletBalance providers * refactor(ui-tests): replace fixed sleeps with condition-based waits * fix: handle null values for size and granteeCount in infoGroups * fix(lint): add newline at end of file in useClipboardCopy hook * fix(ui-tests): page.goto URL * refactor: update import paths for useClipboardCopy --------- Co-authored-by: Ferenc Sárai <sarai.ferenc@gmail.com>
158 lines
4.9 KiB
JavaScript
158 lines
4.9 KiB
JavaScript
const SLEEP_MS = 500
|
|
const SLEEP_ITERATIONS = 20
|
|
|
|
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
|
|
|
|
/**
|
|
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
|
* @param {string} selector XPath selector
|
|
*/
|
|
async function waitForElementXPath(page, selector) {
|
|
for (let i = 0; i < SLEEP_ITERATIONS; i++) {
|
|
const element = await page.evaluateHandle(selector => {
|
|
const result = document.evaluate(selector, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)
|
|
|
|
return result.singleNodeValue
|
|
}, selector)
|
|
|
|
const isNull = await page.evaluate(el => el === null, element)
|
|
|
|
if (!isNull) {
|
|
return element
|
|
}
|
|
|
|
await sleep(SLEEP_MS)
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
|
* @param {string} selector CSS selector
|
|
*/
|
|
async function waitForElementCss(page, selector) {
|
|
for (let i = 0; i < SLEEP_ITERATIONS; i++) {
|
|
const element = await page.$(selector)
|
|
|
|
if (element) {
|
|
return element
|
|
}
|
|
await sleep(SLEEP_MS)
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
|
* @param {string} elementType HTML tag name, e.g. `a`, `button`, `div`,
|
|
* @param {string} text e.g. `"Submit"`
|
|
*/
|
|
function waitForEnabledStateXPath(page, elementType, text) {
|
|
return waitForElementXPath(page, `//${elementType}[contains(., '${text}')][not(@disabled)]`)
|
|
}
|
|
|
|
/**
|
|
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
|
* @param {string} elementType HTML tag name, e.g. `a`, `button`, `div`,
|
|
* @param {string} text e.g. `"Submit"`
|
|
*/
|
|
async function clickElementWithText(page, elementType, text) {
|
|
const element = await waitForElementXPath(page, `//${elementType}[contains(., '${text}')]`)
|
|
|
|
if (!element) {
|
|
throw Error(`clickElementWithText: Could not find <${elementType}> containing "${text}"`)
|
|
}
|
|
|
|
if (element) {
|
|
await element.click()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
|
* @param {string} elementType HTML tag name, e.g. `a`, `button`, `div`,
|
|
* @param {string} text e.g. `"Submit"`
|
|
* @param {string} filePath e.g. `"test-data/text.txt"`
|
|
*/
|
|
async function clickElementWithTextAndUpload(page, elementType, text, filePath) {
|
|
const [fileChooser] = await Promise.all([page.waitForFileChooser(), clickElementWithText(page, elementType, text)])
|
|
await fileChooser.accept([filePath])
|
|
}
|
|
|
|
/**
|
|
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
|
* @param {string} elementType HTML tag name, e.g. `a`, `button`, `div`,
|
|
* @param {string} cssClass CSS class with the dot, e.g. '.MuiSelect-select'
|
|
*/
|
|
async function clickElementWithClass(page, elementType, cssClass) {
|
|
const element = await waitForElementCss(page, `${elementType}${cssClass}`)
|
|
|
|
if (!element) {
|
|
throw Error(`clickElementWithClass: Could not find <${elementType}> with class ${cssClass}`)
|
|
}
|
|
|
|
if (element) {
|
|
await element.click()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
|
* @param {string} elementType HTML tag name, e.g. `a`, `button`, `div`,
|
|
* @param {string} text e.g. `"Submit"`
|
|
*/
|
|
async function assertElementWithTextExists(page, elementType, text) {
|
|
const element = await waitForElementXPath(page, `//${elementType}[contains(., '${text}')]`)
|
|
|
|
if (!element) {
|
|
throw Error(`assertElementWithTextExists: Could not find <${elementType}> containing "${text}"`)
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
/**
|
|
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
|
* @param {string} elementType HTML tag name, e.g. `a`, `button`, `div`,
|
|
* @param {string} attribute HTML attribute, e.g. `alt` or `id`
|
|
* @param {string} value Expected value of the attribute
|
|
* @param {string} property Property to return from the queried HTML element
|
|
* @returns {Promise<string>}
|
|
*/
|
|
async function queryElementPropertyByAttribute(page, elementType, attribute, value, property) {
|
|
const element = await waitForElementXPath(page, `//${elementType}[contains(@${attribute}, "${value}")]`)
|
|
|
|
return page.evaluate((element, property) => element[property], element, property)
|
|
}
|
|
|
|
/**
|
|
* @param {puppeteer.Page} page Puppeteer Page object returned by `browser.newPage()`
|
|
* @param {string} alt `<img>` `alt` to look for
|
|
*/
|
|
function queryImgSrcByAlt(page, alt) {
|
|
return queryElementPropertyByAttribute(page, 'img', 'alt', alt, 'src')
|
|
}
|
|
|
|
module.exports = {
|
|
sleep,
|
|
Assert: {
|
|
elementWithTextExists: assertElementWithTextExists,
|
|
},
|
|
Click: {
|
|
elementWithText: clickElementWithText,
|
|
elementWithClass: clickElementWithClass,
|
|
elementWithTextAndUpload: clickElementWithTextAndUpload,
|
|
},
|
|
Query: {
|
|
elementPropertyByAttribute: queryElementPropertyByAttribute,
|
|
imgSrcByAlt: queryImgSrcByAlt,
|
|
},
|
|
Wait: {
|
|
forElementCss: waitForElementCss,
|
|
forElementXPath: waitForElementXPath,
|
|
forEnabledStateXPath: waitForEnabledStateXPath,
|
|
},
|
|
}
|