MCPcopy Index your code
hub / github.com/codeceptjs/CodeceptJS / findElements

Function findElements

lib/helper/Puppeteer.js:2995–3052  ·  view source on GitHub ↗

* Find elements using Puppeteer's native element discovery methods * Note: Unlike Playwright, Puppeteer's Locator API doesn't have .all() method for multiple elements * @param {Object} matcher - Puppeteer context to search within * @param {Object|string} locator - Locator specification * @return

(matcher, locator)

Source from the content-addressed store, hash-verified

2993 * @returns {Promise<Array>} Array of ElementHandle objects
2994 */
2995async function findElements(matcher, locator) {
2996 locator = new Locator(locator, 'css')
2997
2998 // Check if locator is a role locator and call findByRole
2999 if (locator.isRole()) return findByRole.call(this, matcher, locator)
3000
3001 // Handle shadow DOM locators with >>> deep descendant combinator
3002 // { shadow: ['my-app', 'recipe-hello', 'button'] } => 'my-app >>> recipe-hello >>> button'
3003 if (locator.isShadow()) {
3004 const shadowSelector = locator.value.join(' >>> ')
3005 return matcher.$$(shadowSelector)
3006 }
3007
3008 // Use proven legacy approach - Puppeteer Locator API doesn't have .all() method
3009 if (!locator.isXPath()) return matcher.$$(locator.simplify())
3010
3011 // puppeteer version < 19.4.0 is no longer supported. This one is backward support.
3012 if (puppeteer.default?.defaultBrowserRevision) {
3013 return matcher.$$(`xpath/${locator.value}`)
3014 }
3015
3016 // For Puppeteer 24.x+, $x method was removed
3017 // Use ::-p-xpath() selector syntax
3018 // Check if matcher has $$ method (Page, Frame, or ElementHandle)
3019 if (matcher && typeof matcher.$$ === 'function') {
3020 const xpathSelector = `::-p-xpath(${locator.value})`
3021 try {
3022 return await matcher.$$(xpathSelector)
3023 } catch (e) {
3024 // XPath selector may not work on ElementHandle, fall through to evaluate method
3025 this.debug && this.debug(`XPath selector failed on ${matcher.constructor?.name}: ${e.message}`)
3026 }
3027 }
3028
3029 // ElementHandles don't support XPath directly // Search within the element by making XPath relative
3030 try {
3031 const relativeXPath = locator.value.startsWith('.//') ? locator.value : `.//${locator.value.replace(/^\/\//, '')}`
3032
3033 // Use the element as context by evaluating XPath from it
3034 const elements = await matcher.evaluateHandle((element, xpath) => {
3035 const iterator = document.evaluate(xpath, element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
3036 const results = []
3037 for (let i = 0; i < iterator.snapshotLength; i++) {
3038 results.push(iterator.snapshotItem(i))
3039 }
3040 return results
3041 }, relativeXPath)
3042
3043 // Convert JSHandle to array of ElementHandles
3044 const properties = await elements.getProperties()
3045 return Array.from(properties.values())
3046 } catch (e) {
3047 this.debug(`XPath within element failed: ${e.message}`)
3048 }
3049
3050 // Fallback: return empty array
3051 return []
3052}

Callers

nothing calls this directly

Calls 8

isRoleMethod · 0.80
isShadowMethod · 0.80
$$Method · 0.80
isXPathMethod · 0.80
debugMethod · 0.80
evaluateMethod · 0.80
pushMethod · 0.80
simplifyMethod · 0.65

Tested by

no test coverage detected