¿Existe algún método (no se encontró en la API) o solución para hacer clic en el elemento con texto?
Por ejemplo, tengo html:
<div class="elements">
<button>Button text</button>
<a href=#>Href text</a>
<div>Div text</div>
</div>
Y quiero hacer clic en el elemento en el que está envuelto el texto (haga clic en el botón dentro de .elements), como:
Page.click('Button text', '.elements')
Respuestas:
La respuesta principal actual de tokland solo funciona en nodos de texto y no en nodos con otros elementos en su interior.
Respuesta corta
Esta expresión XPath consultará un botón que contiene el texto "Texto del botón":
const [button] = await page.$x("//button[contains(., 'Button text')]"); if (button) { await button.click(); }
Para respetar también el
<div class="elements">
entorno de los botones, utilice el siguiente código:const [button] = await page.$x("//div[@class='elements']/button[contains(., 'Button text')]");
Explicación
Para explicar por qué el uso del nodo de texto (
text()
) es incorrecto en algunos casos, veamos un ejemplo:<div> <button>Start End</button> <button>Start <em>Middle</em> End</button> </div>
Primero, verifiquemos los resultados al usar
contains(text(), 'Text')
://button[contains(text(), 'Start')]
devolverá ambos dos nodos (como se esperaba)//button[contains(text(), 'End')]
solo devolverá un nodo (el primero) comotext()
devuelve una lista con dos textos (Start
yEnd
), perocontains
solo comprobará el primero//button[contains(text(), 'Middle')]
volverá no hay resultados quetext()
no incluye el texto de los nodos secundariosAquí están las expresiones XPath para
contains(., 'Text')
, que funcionan en el propio elemento, incluidos sus nodos secundarios://button[contains(., 'Start')]
devolverá los dos botones//button[contains(., 'End')]
volverá a devolver ambos dos botones//button[contains(., 'Middle')]
devolverá uno (el último botón)Entonces, en la mayoría de los casos, tiene más sentido usar el en
.
lugar detext()
en una expresión XPath.fuente
//*[...]
en su lugar.Puede usar un selector XPath con page. $ X (expresión) :
Echa un vistazo a
clickByText
esta esencia para ver un ejemplo completo. Se encarga de escapar de las comillas, lo cual es un poco complicado con las expresiones XPath.fuente
//a[contains
con//*[contains
para seleccionar cualquier elemento, no solo una
elemento anchor ( ).También puede utilizar
page.evaluate()
para hacer clic en elementos obtenidos de losdocument.querySelectorAll()
que se han filtrado por contenido de texto:await page.evaluate(() => { [...document.querySelectorAll('.elements button')].find(element => element.textContent === 'Button text').click(); });
Alternativamente, puede usar
page.evaluate()
para hacer clic en un elemento en función de su contenido de texto usandodocument.evaluate()
y una expresión XPath correspondiente:await page.evaluate(() => { const xpath = '//*[@class="elements"]//button[contains(text(), "Button text")]'; const result = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null); result.iterateNext().click(); });
fuente
hizo una solución rápida para poder usar selectores avanzados de CSS como ": contiene (texto)"
así que usando esta biblioteca puedes
fuente
Aquí está mi solución:
fuente
La solucion es
fuente
No hay una sintaxis de selector css compatible para el selector de texto o una opción de combinador, mi solución para esto sería:
fuente
Hay muchas respuestas que sugieren,
contains
pero no veo ninguna motivación para esta imprecisión dado el caso de uso de OP que, según todas las apariencias, es una coincidencia exacta con una cadena de destino de"Button text"
y un elemento<button>Button text</button>
.Preferiría usar el más preciso
[text()="Button text"]
, que evita un falso positivo cuando el botón es, digamos<button>Button text and more stuff</button>
,:Esto anticipa el escenario opuesto de esta respuesta que intenta ser lo más permisiva posible.
Muchas respuestas también perdieron el
.elements
requisito de la clase para padres.fuente
Tuve que:
await this.page.$eval(this.menuSelector, elem => elem.click());
fuente