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 ( Start
i End
), ale contains
sprawdzi 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()
.