Tras estudiar el código de Playwright (sources/playwright), 4 primitivas nuevas y
1 endurecida para que la interacción web sea fiable:
- cdp_wait_actionable: visible + stable (2 rAF) + enabled + hit-test (elementFromPoint
cruzando shadow DOM) + retry backoff + scroll cycling. Devuelve el punto validado.
Réplica de _retryAction/_checkElementIsStable/expectHitTarget de Playwright.
- cdp_select_dropdown: desplegables custom (combobox/MUI/select2/headlessui): click real
en trigger -> espera apertura (aria-expanded/[role=option] visible) -> click real en
la opción. Resuelve el fallo nº1: clicar antes de que monte el listbox.
- cdp_select_option (endurecida v1.1.0): valida <select> real, match value/label
normalizado/índice, option.selected para multiple, eventos input{composed}+change.
- cdp_fill: escribir fiable en inputs React/Vue: focus -> select-all -> Input.insertText
(sin native value setter, como Playwright); native setter solo para inputs especiales.
- cdp_find_by_role: localizar por rol ARIA + accessible name (estilo getByRole),
reutilizando el AX tree de cdp_get_ax_outline.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.1 KiB
name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, params, output, file_path
| name | kind | lang | domain | version | purity | signature | description | tags | uses_functions | uses_types | returns | returns_optional | error_type | imports | tested | tests | test_file_path | params | output | file_path | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| cdp_fill | function | go | browser | 1.0.0 | impure | func CdpFill(c *CDPConn, backendNodeID int, value string) error | Rellena un campo de texto de forma robusta estilo Playwright, fiable con inputs controlados por frameworks (React/Vue). Valida visible+enabled+editable, enfoca el nodo, y según el tipo: para text/textarea/email/search/url/tel/password/number/contenteditable selecciona el valor previo y lo reemplaza con Input.insertText (eventos input/beforeinput confiables del motor — React/Vue reconcilian solos); para inputs especiales (color/date/time/range/week/month/datetime-local) fija el.value y dispara input{bubbles,composed}+change{bubbles}. Verifica que el.value===value al final. backendNodeID es el #ref del AX outline. Variante por selector: CdpFillSelector. Reemplaza el patrón frágil focus+type que concatena al valor existente. |
|
false | error_go_core | false |
|
nil si el campo quedó con el valor pedido; error si la conexión es nil, el nodo no es editable (readonly/disabled/oculto), el tipo de input no se puede rellenar, o la verificación final (el.value===value) falla. | functions/browser/cdp_fill.go |
Ejemplo
// Tras un page_perceive que devuelve un <input> React con #ref=4521:
conn, _ := CdpConnect(9222)
// Por #ref del AX outline (camino habitual del bucle percibir→actuar):
if err := CdpFill(conn, 4521, "ada@example.com"); err != nil {
log.Fatal(err)
}
// Por selector CSS estable (resuelve a backendNodeID y delega en CdpFill):
if err := CdpFillSelector(conn, "input[name='email']", "ada@example.com"); err != nil {
log.Fatal(err)
}
// Vaciar un campo:
_ = CdpFillSelector(conn, "#search", "")
// Input especial (date): ruta setvalue + eventos input/change:
_ = CdpFillSelector(conn, "input[type='date']", "2026-06-16")
Cuando usarla
Cuando necesites rellenar inputs de formularios controlados por React/Vue/otros frameworks de forma fiable. Es el reemplazo del patrón DOM.focus + CdpTypeText/CdpInsertText que concatena al valor existente y a menudo deja el estado del framework desincronizado (el value del DOM cambia pero el estado de React no, o al revés). CdpFill selecciona y reemplaza el contenido entero y, al usar Input.insertText (no el native value setter), emite los eventos input/beforeinput confiables que hacen que el framework reconcilie su estado. Úsala para login, registro, búsquedas y cualquier campo donde el patrón focus+type falle o duplique texto. Para teclear carácter a carácter simulando un humano (sitios con detección por pulsación o autocompletes estrictos) sigue prefiriendo CdpTypeRef (camino human).
Gotchas
- El
#refes un backendDOMNodeId, no el nodeId efímero del AX tree. Si la página recargó o navegó tras el snapshot, el ref puede estar muerto — re-percibir (page_perceive) antes de actuar. - contenteditable: la ruta needsinput inserta el valor seleccionando todo el contenido, pero la verificación final no es fiable para contenteditable (el motor normaliza el HTML). Por eso para contenteditable
CdpFillno falla por verificación; confía en queInput.insertTextcuajó. Si necesitas garantía dura del contenido, léelo aparte conCdpEvaluate. - Inputs especiales (color/date/time/datetime-local/month/range/week) van por la ruta setvalue: fijan
el.valuey disparaninput{bubbles,composed}+change{bubbles}. Algunos frameworks que escuchan eventos de teclado en estos inputs pueden no reaccionar — es el mismo trade-off que hace Playwright. - input[type=number]: el valor debe ser numérico (
isNaNlo rechaza con error claro). Espacios se recortan. - Frameworks y el evento nativo: la clave de la robustez es NO usar el "native value setter" (
Object.getOwnPropertyDescriptor(...).set). React parchea el setter devaluey se confunde si lo invocas a mano;Input.insertTextdel motor emite los eventos que React intercepta correctamente. Si una versión muy vieja de un framework custom no reacciona, cae aCdpTypeRef(char por char). - No hace scroll humanizado:
DOM.focushace scroll-into-view del nodo, pero si el input está dentro de un contenedor con scroll propio y oculto, valida visible y puede fallar con "elemento no visible". En ese caso hazCdpClickRef(que hacescrollIntoViewIfNeeded) antes. - value=="" borra el campo enviando
Deletesobre la selección previa (noInput.insertTextcon cadena vacía, que sería no-op). Esto dispara los eventos de borrado que el framework espera.