Skip to content

Instantly share code, notes, and snippets.

@tokland
Last active August 11, 2023 03:48
Show Gist options
  • Save tokland/d3bae3b6d3c1576d8700405829bbdb52 to your computer and use it in GitHub Desktop.
Save tokland/d3bae3b6d3c1576d8700405829bbdb52 to your computer and use it in GitHub Desktop.
Click link by text in Puppeteer
const puppeteer = require('puppeteer');
const escapeXpathString = str => {
const splitedQuotes = str.replace(/'/g, `', "'", '`);
return `concat('${splitedQuotes}', '')`;
};
const clickByText = async (page, text) => {
const escapedText = escapeXpathString(text);
const linkHandlers = await page.$x(`//a[contains(text(), ${escapedText})]`);
if (linkHandlers.length > 0) {
await linkHandlers[0].click();
} else {
throw new Error(`Link not found: ${text}`);
}
};
const run = async () => {
const browser = await puppeteer.launch({args: ['--no-sandbox'], headless: true});
const page = await browser.newPage();
await page.goto('https://en.wikipedia.org/wiki/List_of_The_Sandman_characters');
await clickByText(page, `Fiddler's Green`);
await page.waitForNavigation({waitUntil: 'load'});
console.log("Current page:", page.url());
return browser.close();
};
const logErrorAndExit = err => {
console.log(err);
process.exit();
};
run().catch(logErrorAndExit);
@Maxim-Mazurok
Copy link

This was easier for me to understand:

export const escapeXpathString = (str: string) => {
  const splitQuotes = str.split(`'`).join(`', "'", '`);
  return `concat('${splitQuotes}', '')`;
};

it("escapeXpathString works", () => {
  expect(escapeXpathString("test'lol'")).toEqual(
    `concat('test', "'", 'lol', "'", '', '')`
  );
});

@ggorlen
Copy link

ggorlen commented Apr 25, 2023

You don't need to use XPath for selecting by text any longer. There's page.click("::-p-text(hello world)"). See this Stack Overflow answer for more information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment