Fix snapshot evaluate: scope queries to container element, handle Page fallback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -329,14 +329,10 @@ Answer:`;
|
||||
* Returns a plain JSON object describing every field, avoiding per-element CDP round-trips.
|
||||
*/
|
||||
async _snapshotFields(container) {
|
||||
return await container.evaluate((extractLabelSrc, checkRequiredSrc, normalizeLegendSrc) => {
|
||||
// Reconstruct functions inside browser context
|
||||
const extractLabel = new Function('node', `
|
||||
${extractLabelSrc}
|
||||
return extractLabel(node);
|
||||
`);
|
||||
// Can't pass functions directly — inline the logic instead
|
||||
// We'll inline extractLabel and checkRequired logic directly
|
||||
return await container.evaluate((rootOrUndefined) => {
|
||||
// When container is an ElementHandle, root is the element.
|
||||
// When container is a Page, root is undefined — use document.
|
||||
const root = rootOrUndefined || document;
|
||||
|
||||
function _extractLabel(node) {
|
||||
const id = node.id;
|
||||
@@ -419,7 +415,7 @@ Answer:`;
|
||||
};
|
||||
|
||||
// Resume radios
|
||||
const resumeInputs = document.querySelectorAll('input[type="radio"][aria-label*="resume"], input[type="radio"][aria-label*="Resume"]');
|
||||
const resumeInputs = root.querySelectorAll('input[type="radio"][aria-label*="resume"], input[type="radio"][aria-label*="Resume"]');
|
||||
let resumeChecked = false;
|
||||
resumeInputs.forEach((r, i) => {
|
||||
if (r.checked) resumeChecked = true;
|
||||
@@ -428,10 +424,10 @@ Answer:`;
|
||||
result.resumeChecked = resumeChecked;
|
||||
|
||||
// File input
|
||||
result.hasFileInput = !!document.querySelector('input[type="file"]');
|
||||
result.hasFileInput = !!root.querySelector('input[type="file"]');
|
||||
|
||||
// Text / number / url / email / tel inputs
|
||||
const inputEls = document.querySelectorAll('input[type="text"], input[type="number"], input[type="url"], input[type="email"], input[type="tel"]');
|
||||
const inputEls = root.querySelectorAll('input[type="text"], input[type="number"], input[type="url"], input[type="email"], input[type="tel"]');
|
||||
inputEls.forEach((inp, i) => {
|
||||
if (!isVisible(inp)) return;
|
||||
const label = _extractLabel(inp);
|
||||
@@ -442,7 +438,7 @@ Answer:`;
|
||||
});
|
||||
|
||||
// Textareas
|
||||
const taEls = document.querySelectorAll('textarea');
|
||||
const taEls = root.querySelectorAll('textarea');
|
||||
taEls.forEach((ta, i) => {
|
||||
if (!isVisible(ta)) return;
|
||||
const label = _extractLabel(ta);
|
||||
@@ -452,7 +448,7 @@ Answer:`;
|
||||
});
|
||||
|
||||
// Fieldsets
|
||||
const fsEls = document.querySelectorAll('fieldset');
|
||||
const fsEls = root.querySelectorAll('fieldset');
|
||||
fsEls.forEach((fs, i) => {
|
||||
const legend = fs.querySelector('legend');
|
||||
if (!legend) return;
|
||||
@@ -489,7 +485,7 @@ Answer:`;
|
||||
});
|
||||
|
||||
// Selects (standalone, not inside fieldsets we already handle)
|
||||
const selEls = document.querySelectorAll('select');
|
||||
const selEls = root.querySelectorAll('select');
|
||||
selEls.forEach((sel, i) => {
|
||||
if (!isVisible(sel)) return;
|
||||
const label = _extractLabel(sel);
|
||||
@@ -507,7 +503,7 @@ Answer:`;
|
||||
});
|
||||
|
||||
// Checkboxes (standalone)
|
||||
const cbEls = document.querySelectorAll('input[type="checkbox"]');
|
||||
const cbEls = root.querySelectorAll('input[type="checkbox"]');
|
||||
cbEls.forEach((cb, i) => {
|
||||
if (!isVisible(cb)) return;
|
||||
// Skip if inside a fieldset with a legend (handled in fieldsets section)
|
||||
|
||||
Reference in New Issue
Block a user