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.