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) como text()
devuelve una lista con dos textos ( Start
y End
), pero contains
solo comprobará el primero
//button[contains(text(), 'Middle')]
volverá no hay resultados que text()
no incluye el texto de los nodos secundarios
Aquí 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 de text()
en una expresión XPath.