* Find a single element using Puppeteer's native element discovery methods * Note: Puppeteer Locator API doesn't have .first() method like Playwright * @param {Object} matcher - Puppeteer context to search within * @param {Object|string} locator - Locator specification * @returns {Promise<Object
(matcher, locator)
| 3059 | * @returns {Promise<Object>} Single ElementHandle object |
| 3060 | */ |
| 3061 | async function findElement(matcher, locator) { |
| 3062 | locator = new Locator(locator, 'css') |
| 3063 | |
| 3064 | // Check if locator is a role locator and call findByRole |
| 3065 | if (locator.isRole()) { |
| 3066 | const elements = await findByRole.call(this, matcher, locator) |
| 3067 | return elements[0] |
| 3068 | } |
| 3069 | |
| 3070 | // Handle shadow DOM locators with >>> deep descendant combinator |
| 3071 | if (locator.isShadow()) { |
| 3072 | const shadowSelector = locator.value.join(' >>> ') |
| 3073 | const elements = await matcher.$$(shadowSelector) |
| 3074 | return elements[0] |
| 3075 | } |
| 3076 | |
| 3077 | // Use proven legacy approach - Puppeteer Locator API doesn't have .first() method |
| 3078 | if (!locator.isXPath()) { |
| 3079 | const elements = await matcher.$$(locator.simplify()) |
| 3080 | return elements[0] |
| 3081 | } |
| 3082 | // puppeteer version < 19.4.0 is no longer supported. This one is backward support. |
| 3083 | if (puppeteer.default?.defaultBrowserRevision) { |
| 3084 | const elements = await matcher.$$(`xpath/${locator.value}`) |
| 3085 | return elements[0] |
| 3086 | } |
| 3087 | // For Puppeteer 24.x+, $x method was removed - use ::-p-xpath() selector |
| 3088 | const elements = await matcher.$$(`::-p-xpath(${locator.value})`) |
| 3089 | return elements[0] |
| 3090 | } |
| 3091 | |
| 3092 | async function proceedClick(locator, context = null, options = {}) { |
| 3093 | let matcher = await this.context |