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:
2026-03-06 14:42:41 -08:00
parent aeb41b42c2
commit 23eb5284fa

View File

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