Risposta breve
Questa espressione XPath interrogherà un pulsante che contiene il testo "Button text":
const [button] = await page.$x("//button[contains(., 'Button text')]");
if (button) {
await button.click();
}
Per rispettare anche l' <div class="elements">
ambiente circostante i pulsanti, utilizzare il codice seguente:
const [button] = await page.$x("//div[@class='elements']/button[contains(., 'Button text')]");
Spiegazione
Per spiegare perché text()
in alcuni casi l'uso del text node ( ) è sbagliato, diamo un'occhiata a un esempio:
<div>
<button>Start End</button>
<button>Start <em>Middle</em> End</button>
</div>
Innanzitutto, controlliamo i risultati quando si utilizza contains(text(), 'Text')
:
//button[contains(text(), 'Start')]
restituirà entrambi i due nodi (come previsto)
//button[contains(text(), 'End')]
restituirà solo un nodo (il primo) come text()
restituisce una lista con due testi ( Start
e End
), macontains
controllerà solo il primo
//button[contains(text(), 'Middle')]
non restituirà alcun risultato in quanto text()
non include il testo dei nodi figli
Ecco le espressioni XPath per contains(., 'Text')
, che funziona sull'elemento stesso, inclusi i suoi nodi figlio:
//button[contains(., 'Start')]
restituirà entrambi i due pulsanti
//button[contains(., 'End')]
restituirà nuovamente entrambi i due pulsanti
//button[contains(., 'Middle')]
restituirà uno (l'ultimo pulsante)
Quindi, nella maggior parte dei casi, ha più senso usare .
invece che text()
in un'espressione XPath.