I'm trying to search inner text case insensitive using puppeteer.
I've read this: case insensitive xpath contains() possible?
For example I have this elements:
<div>
<span>Test One</span>
<span>Test Two</span>
<span>Test Three</span>
</div>
I've tried this unsuccessfully:
const element = await page.$x("//span//text()[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'two')]");
Your XPath expression is valid, but you are returning text() instead of the node itself. page.$x expects the XPath to return an element, therefore your code does not work. To return the node you need to query for the span element.
const element = await page.$x("//span[contains(translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'two')]");
Please note, that text() only works for text-only nodes. If you have mixed content (containing elements and text), you should use the string value (. instead of text()):
const element = await page.$x("//span[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'two')]");
To compare the expressions I put them below each other:
//span//text()[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'two')]
//span[contains(translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'two')
//span[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'two')]
The first one is the expression (given by you) for the text of the span node. The second one queries the node itself by using text(). The last one uses the string value to query the node.
Not as pretty, but you can use page.evaluateHandle along with a regex to find the element:
const element = await page.evaluateHandle(() =>
Array.from(document.querySelectorAll("div > span")).find(a => /test two/i.test(a.innerText))
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With