Le site la meilleure réponse actuelle by tokland ne fonctionne que sur les noeuds de texte et non sur les noeuds contenant d'autres éléments.
Réponse courte
Cette expression XPath interrogera un bouton qui contient le texte "Texte du bouton" :
const [button] = await page.$x("//button[contains(., 'Button text')]");
if (button) {
await button.click();
}
Respecter également le <div class="elements">
entourant les boutons, utilisez le code suivant :
const [button] = await page.$x("//div[@class='elements']/button[contains(., 'Button text')]");
Explication
Pour expliquer pourquoi l'utilisation du nœud de texte ( text()
) est erronée dans certains cas, voyons un exemple :
<div>
<button>Start End</button>
<button>Start <em>Middle</em> End</button>
</div>
Tout d'abord, vérifions les résultats lorsque l'on utilise contains(text(), 'Text')
:
-
//button[contains(text(), 'Start')]
retournera les deux deux nœuds (comme prévu)
-
//button[contains(text(), 'End')]
ne retournera que un (le premier) comme text()
retourne une liste avec deux textes ( Start
y End
), mais contains
ne vérifiera que le premier
-
//button[contains(text(), 'Middle')]
retournera pas de résultats comme text()
n'inclut pas le texte des noeuds enfants
Voici les expressions XPath pour contains(., 'Text')
qui travaille sur l'élément lui-même, y compris ses nœuds enfants :
-
//button[contains(., 'Start')]
retournera les deux deux boutons
-
//button[contains(., 'End')]
rendra à nouveau les deux deux boutons
-
//button[contains(., 'Middle')]
retournera un (le dernier bouton)
Ainsi, dans la plupart des cas, il est plus judicieux d'utiliser l'option .
au lieu de text()
dans une expression XPath.