3

I'm using puppeteer to check for a specific text that appears on the webpage. My code to check is as follows:

if ((await page.waitForXPath('//span[contains(text(), "Subscription Confirmed")]',30000)) !== null) {
  chk = await page.evaluate(el => el.innerText, await page.$x('//span[contains(text(), "Subscription Confirmed")]'))
  chk = 'Success'
} else {
  // do something else
  chk = 'Failed'
}

This doesn't seem to detect the text for some reason. I have attached a screenshot of the DOM of the webpage where you can see the text - DOM. Hoping someone could help.

vsemozhebuty
  • 12,992
  • 1
  • 26
  • 26
sayan
  • 79
  • 1
  • 3
  • 12

3 Answers3

4

This worked for me in a jest test:

  await page.waitForXPath('//*[contains(text(), "SOME TEXT")]')
Raine Revere
  • 30,985
  • 5
  • 40
  • 52
3

Try the following:

if ((await page.waitForXPath('//*[contains(text(), "Subscription Confirmed")]',30000)) !== null) {
   chk = await page.evaluate(el => el.innerText, await page.$x('//*[contains(text(), "Subscription Confirmed")]'))
   chk = 'Success'
} else { 
   chk = 'Failed'
}
Igor Savinkin
  • 5,669
  • 8
  • 37
  • 69
0

You seem to have simply confused span and h1 in your selector. However, I'd like to offer a few suggestions and notes to improve upon other answers.

  • Always use booleans like true and false rather than strings "Success" and "Failed".
  • waitForXPath throws when the timeout expires, so the if is unnecessary.
  • The second argument to waitForXPath should be {timeout: 30000} rather than 30000.
  • Unless you override it elsewhere in your code, 30 seconds is the default timeout so you can omit that option.
  • Scope variables with let or const.
  • Use the return value of waitFor_ rather than re-selecting the element.
  • waitForXPath is deprecated in favor of waitForSelector("::-p-xpath(...)").

Putting these suggestions together, we have:

const xp = '::-p-xpath(//h1[contains(text(), "Subscription Confirmed")])';
const el = await page.waitForSelector(xp);
const text = await el.evaluate(el => el.textContent);

You can wrap this in a try/catch if you expect failure, or use the shorthand:

const xp = '::-p-xpath(//h1[contains(text(), "Subscription Confirmed")])';
const el = await page.waitForSelector(xp).catch(() => null);

if (el) {
  const text = await el.evaluate(el => el.textContent);
}

But we can improve this. Puppeteer now has the ::-p-text() pseudoselector which is a bit more succinct:

const el = await page.waitForSelector("h1::-p-text(Subscription Confirmed)");
const text = await el.evaluate(el => el.textContent);

Now, since you're selecting by full text and not using a substring, you basically already know the text, so there's no point in getting it!

If you want to check whether specific text exists or not and you don't want to wait for it to appear, you can use:

const exists = await page.$("h1::-p-text(Subscription Confirmed)");

if (exists) {
  // it exists
}

exists will be null if not found or the ElementHandle otherwise. This seems closer to your original intent.

See this post for a canonical resource to selecting by text in Puppeteer.

ggorlen
  • 44,755
  • 7
  • 76
  • 106