Files
fn_registry/functions/browser/cdp_find_by_role.md
T
Egutierrez 4187f9b6b1 feat(browser): actionability + dropdowns + fill + role locator (estilo Playwright)
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>
2026-06-16 20:49:37 +02:00

3.8 KiB

name, kind, lang, domain, version, purity, signature, description, tags, params, output, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, file_path
name kind lang domain version purity signature description tags params output uses_functions uses_types returns returns_optional error_type imports tested tests test_file_path file_path
cdp_find_by_role function go browser 1.0.0 impure func CdpFindByRole(c *CDPConn, role string, opts CdpFindByRoleOpts) (ref int, count int, err error) Localiza el primer elemento por su ROLE ARIA + accessible name (estilo getByRole de Playwright) reusando el AX tree (Accessibility.getFullAXTree). Devuelve el backendDOMNodeId (#ref) del primer match y el total de matches para detectar ambiguedad.
browser
name desc
c Conexion CDP viva (*CDPConn) del pool. nil => error.
name desc
role Rol ARIA exacto a matchear (ej 'button', 'link', 'textbox', 'checkbox').
name desc
opts CdpFindByRoleOpts: Name (accessible name, vacio = no filtra), Exact (igualdad en vez de substring), Regex (Name como expresion regular RE2), CaseSensitive (default false).
(ref int, count int, err error): ref = backendDOMNodeId del primer match (#ref para CdpClickRef/CdpHoverRef); count = total de matches (>1 = ambiguo); err si conexion nula, role vacio, regex invalida, fallo CDP o 0 matches.
false error_go_core
false
functions/browser/cdp_find_by_role.go

Ejemplo

c, _ := browser.CdpConnect(9333) // conexion CDP del pool
ref, count, err := browser.CdpFindByRole(c, "button", browser.CdpFindByRoleOpts{
    Name: "Aceptar", // substring del accessible name, case-insensitive
})
if err != nil {
    log.Fatal(err) // ej: no element with role "button" and name "Aceptar"
}
if count > 1 {
    log.Printf("aviso: %d botones matchean 'Aceptar', usando el primero", count)
}
// ref es el mismo #ref que produce page_perceive: alimentarlo a CdpClickRef.
_ = browser.CdpClickRef(c, ref, browser.MouseHumanOpts{})

// Match exacto + case-sensitive:
ref, _, _ = browser.CdpFindByRole(c, "link", browser.CdpFindByRoleOpts{
    Name: "Iniciar sesion", Exact: true, CaseSensitive: true,
})

// Match por regex (ej "Eliminar 3 elementos" / "Eliminar 12 elementos"):
ref, _, _ = browser.CdpFindByRole(c, "button", browser.CdpFindByRoleOpts{
    Name: `^Eliminar \d+ elementos$`, Regex: true,
})

Cuando usarla

Cuando necesites localizar un control de forma robusta a cambios de DOM/CSS: el rol ARIA + accessible name sobreviven a refactors de markup y clases CSS que romperian un selector nth-of-type. Es el patron primario que recomienda Playwright (getByRole) para encontrar elementos accionables (botones, links, inputs). Combina el ref devuelto directamente con cdp_click_ref / cdp_hover_ref para actuar sin pasar por un selector fragil. Revisa count antes de actuar: si es >1 la busqueda es ambigua y conviene refinar (Name mas especifico, Exact, o Regex anclada).

Gotchas

  • El name que se matchea es el accessible name computado por el motor de accesibilidad de Chrome (deriva de aria-label, label asociado, contenido, alt, title segun la spec ARIA), no el innerText del elemento. Si buscas por el texto visible literal, usa cdp_find_ref_by_text en su lugar.
  • count > 1 => ambiguedad: se devuelve el primer match en orden del AX tree, que no siempre es el visualmente primero ni el que quieres. Refina la busqueda.
  • El role se compara por igualdad exacta del rol ARIA: "button" no matchea "menuitem" aunque ambos sean clicables. Mira el outline de page_perceive / cdp_get_ax_outline para ver el rol real que Chrome asigna a cada nodo.
  • Nodos ignored del AX tree se descartan. Si el elemento esta oculto (aria-hidden, display:none) puede no aparecer y dar 0 matches.
  • El ref es un backendDOMNodeId: estable mientras el nodo viva, pero si el DOM muta entre el find y el click el ref puede quedar obsoleto.