Skip to content
Advertisement

Node JS Puppeteer click on a li element without name or id

I’m trying to click on a li element which for some reason works as a size selector on a certain website. It looks like this

size selector

And its html looks like this

enter image description here

Each <li> represents one size option, I’ve tried some stuff but none of it works.

my first attempt was using xpath:

const [size_button] = await page.$x(`//*[contains(., '${data[ii][1]}')]`); // doesn't work
await size_button.click();

I also tried a regular click action:

await page.click(`li[data-original-title="Größe in EU: ${data[ii][1]}"]`); // the array contains a specific size, eg. 40.5 like in the li data-original-title field

None of this worked, and I’m wondering if it is even possible to click on such a element with puppeteer…

If anyone would like to examine the page, the link is here

Advertisement

Answer

This is a bit tricky. Your selector is working OK, as is the click event, but I suspect that event does nothing but call e.preventDefault() to prevent navigation to the anchor’s href.

The highlight showing the size was selected is actually applied by a mousedown event in the <a>‘s parent <li>, and it seems the child event hasn’t been applied or doesn’t bubble using your .click method:

image showing browser console element tree with the li element's mousedown event circled to indicate it's the important event OP wants to trigger

You can trigger this as follows:

const puppeteer = require("puppeteer"); // ^13.5.1

let browser;
(async () => {
  browser = await puppeteer.launch({headless: false});
  const [page] = await browser.pages();
  await page.setRequestInterception(true);
  page.on("request", req => {
    req.resourceType() === "image" ? req.abort() : req.continue();
  });
  const url = "https://en.afew-store.com/products/air-jordan-4-retro-tour-yellow-dark-blue-grey-white";
  await page.goto(url, {waitUntil: "domcontentloaded"});
  const size = "8.5";
  const xp = `//a[contains(@class, "btn-sm") and text()="${size}"]`;
  const sizeButton = await page.waitForXPath(xp);
  await sizeButton.evaluate(btn => {
    btn.closest("li").dispatchEvent(new Event("mousedown"));
    //  ^--- .parentNode is also possible instead of .closest("li")
  });
  await page.waitForTimeout(10000);
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close())
;

The final timeout gives you a chance to look at the page and see that size 8.5 was highlighted.

Note that I’ve made your xpath selector more precise to avoid false positives.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement