diff --git a/lib/form_filler.mjs b/lib/form_filler.mjs index ded8213..d721ebb 100644 --- a/lib/form_filler.mjs +++ b/lib/form_filler.mjs @@ -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)