4187f9b6b1
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.6 KiB
5.6 KiB
name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
| name | kind | lang | domain | version | purity | signature | description | tags | uses_functions | uses_types | returns | returns_optional | error_type | imports | params | output | tested | tests | test_file_path | file_path | |||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| cdp_select_dropdown | function | go | browser | 1.0.0 | impure | func CdpSelectDropdown(c *CDPConn, triggerSelector string, optionText string, opts CdpDropdownOpts) error | Selecciona una opcion en un DESPLEGABLE CUSTOM (combobox/listbox ARIA, react-select, MUI Select, headlessui, select2) — esos donde un <select> nativo NO aplica. Replica el patron de Playwright (que no tiene API para custom dropdowns): click REAL en el trigger (mousedown, no element.click JS), espera la apertura por polling (aria-expanded=true O [role=listbox]/[role=menu] visible O opciones con rect>0), localiza la opcion por texto normalizado (substring o exacto, case-insensitive) y hace click REAL en su centro, con verificacion suave (aria-expanded vuelve a false o Enter como fallback). Reusa CdpEvaluate, CdpClickXYHuman y CdpPressKey. |
|
|
false | error_go_core |
|
|
error si el trigger no existe, si el dropdown no abre dentro del timeout ("el dropdown no abrio"), o si la opcion no aparece ("option %q not found in dropdown"); nil si el click sobre la opcion se realizo (la verificacion de cierre es suave y no falla duro si queda ambigua) | false | functions/browser/cdp_select_dropdown.go |
Ejemplo
conn, _ := CdpConnect(9222)
CdpNavigate(conn, "https://mui.com/material-ui/react-select/")
// Combobox MUI: el trigger es el div con role=combobox; el listbox monta y
// anima al abrir. CdpSelectDropdown clica el trigger, espera a que el listbox
// este visible y entonces clica la opcion "Twenty".
err := CdpSelectDropdown(conn, "[role=combobox]", "Twenty", CdpDropdownOpts{})
if err != nil {
log.Fatal(err)
}
// react-select / headlessui: trigger por clase + match exacto + timeout amplio
// para listas que tardan en montar.
err = CdpSelectDropdown(conn, ".select__control", "España", CdpDropdownOpts{
Exact: true,
TimeoutMs: 6000,
})
// Menu tipo dropdown-menu (no listbox): las opciones son role=menuitem.
err = CdpSelectDropdown(conn, "#user-menu-btn", "Cerrar sesion", CdpDropdownOpts{
OptionRole: "menuitem",
})
Cuando usarla
Usala cuando el desplegable NO es un <select> nativo: comboboxes/listboxes ARIA,
react-select, MUI Select, headlessui, select2, Ant Design, o cualquier menu hecho
con <div>/<li> + JS donde elegir = clicar el trigger y luego clicar la opcion
del menu desplegado. Es el equivalente al patron de Playwright
click(trigger) -> getByRole('option', {name}) -> click(option), con la espera de
apertura ya resuelta. Para un <select> nativo de HTML usa CdpSelectOption (setea
select.value + dispara input/change), que es mas robusto y directo para ese
caso.
Gotchas
- Click real, no element.click(): muchos dropdowns custom escuchan
mousedown(noclick), por eso esta funcion despacha eventos de raton reales sobre el centro del bbox. Solo cae aelement.click()JS si el nodo no tiene geometria. - Animaciones de apertura: el fallo nº1 reportado en Playwright es clicar la
opcion ANTES de que el listbox monte/anime. Por eso hay polling de apertura
(
dropdownWaitOpen) que no avanza hasta que hay opciones visibles. Si tu dropdown anima muy lento, subeTimeoutMs. - Listas virtualizadas (react-window, virtuoso): solo renderizan las opciones
en viewport. Si la opcion buscada esta fuera del scroll inicial, puede que nunca
se monte y la funcion devuelva "not found" aunque exista. Mitigacion: escribe en
el combobox para filtrar (
CdpTypeText) antes de llamar a esta funcion, o haz scroll dentro del listbox primero. - Trigger vs contenedor:
triggerSelectordebe apuntar al elemento que ABRE el menu (el boton/combobox), no al[role=listbox](que no existe hasta abrir). - Match de texto: normaliza espacios y es case-insensitive; por defecto es
substring (
Exact=false). Si varias opciones comparten substring, elige la primera visible en orden de documento — usaExact=truepara desambiguar. - OptionRole: por defecto
option([role=option]). Para menus de acciones usamenuitem; para arbolestreeitem. La deteccion de apertura tambien considera[role=menu]yli[role]para cubrir patrones comunes. - Verificacion suave: tras clicar, si el dropdown sigue abierto la funcion pulsa
Entercomo fallback y devuelvenil. No falla duro si la seleccion no se puede confirmar inequivocamente pero el click se hizo — comprueba el estado resultante (texto del trigger, valor del formulario) si necesitas certeza. - iframes: opera en el documento principal (via
CdpEvaluate). Para un dropdown dentro de un iframe necesitarias el contexto del frame (no cubierto aqui).