Aktualnym top odpowiedź przez tokland działa tylko na węzłach tekstowych, a nie na węzłach z innymi elementami wnętrza.
Krótka odpowiedź
To wyrażenie XPath będzie sprawdzać przycisk zawierający tekst „Tekst przycisku”:
const [button] = await page.$x("//button[contains(., 'Button text')]");
if (button) {
await button.click();
}
Aby również uszanować <div class="elements">otoczenie przycisków, użyj następującego kodu:
const [button] = await page.$x("//div[@class='elements']/button[contains(., 'Button text')]");
Wyjaśnienie
Aby wyjaśnić, dlaczego text()w niektórych przypadkach używanie węzła tekstowego ( ) jest nieprawidłowe, spójrzmy na przykład:
<div>
<button>Start End</button>
<button>Start <em>Middle</em> End</button>
</div>
Najpierw sprawdźmy wyniki przy użyciu contains(text(), 'Text'):
//button[contains(text(), 'Start')]powróci zarówno dwa węzły (prawidłowo)
//button[contains(text(), 'End')]zwróci tylko jeden węzeł (pierwszy) jako text()zwraca listę z dwoma tekstami ( Starti End), ale containssprawdzi tylko pierwszy
//button[contains(text(), 'Middle')] nie zwróci żadnych wyników, ponieważ text()nie zawiera tekstu węzłów potomnych
Oto wyrażenia XPath dla contains(., 'Text'), które działają na samym elemencie, w tym na jego węzłach podrzędnych:
//button[contains(., 'Start')]zwróci zarówno dwa przyciski
//button[contains(., 'End')]ponownie zwróci oba dwa przyciski
//button[contains(., 'Middle')] zwróci jeden (ostatni przycisk)
Dlatego w większości przypadków bardziej sensowne jest użycie w wyrażeniu XPath .zamiast text().