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
And its html looks like this
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
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:
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.
In this case you could for instance get al <a tags with the class="btn btn-sm"
I think is a good idea get the expected result in the console of the browser using Vainilla Javascript, and when suscess try to reach the same result with Puppeteer
Vainilla Javascript
const sizeLinks = document.querySelectorAll('a.btn.btn-sm')
sizeLinks[1].click()
Puppeteer (Full working example)
'use strict'
const puppeteer = require('puppeteer');
(async () => {
const baseUrl = 'https://en.afew-store.com/products/air-jordan-4-retro-tour-yellow-dark-blue-grey-white'
const browser = await puppeteer.launch({ headless: false }); // default is true
const page = await browser.newPage();
await page.goto(baseUrl, {
waitUntil: 'networkidle2',
});
await page.waitForTimeout(5000) // Leave extra time for complete the page load (Just to be cautious)
const sizeLinks = await page.$$('a.btn.btn-sm')
await sizeLinks[1].click()
console.log('Debugging')
//await browser.close();
//console.log(`Browser has been closed`);
//process.exit(0);
})();
Reference: