I got following Problem. If I run this code I get this error message and I cant seem to fix it.
Uncaught Error Error: Evaluation failed: TypeError: Cannot read properties of undefined (reading 'click') at _evaluateInternal (c:\Users\Name\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:221:19) at processTicksAndRejections (node:internal/process/task_queues:96:5)
const puppeteer = require('puppeteer');
const url = "https://www.zalando.de/nike-sportswear-blazer-mid-77-sneaker-high-ni115n001-a13.html";
async function initBrowser() {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto(url);
await page.screenshot({ path: 'example.png' });
return page;
}
async function addToCart(page) {
await page.$eval('span[]', element => element.click());
await page.$$eval('.example', elements => {
const element = elements.find(element => element.innerHTML === '39');
element.click();
});
await page.$eval('button[]', element => element.click());
}
async function checkout() {
const page = await initBrowser();
await addToCart(page);
}
checkout();
CodePudding user response:
You are doing
await page.$$eval('.example')
Not sure if there is any element example
and .find
is not guaranteed to return any value. Always do if
check
const element = elements.find(element => element.innerHTML === '39');
if (element){
element.click();
}
MDN on find - The find()
method returns the first element in the provided array that satisfies the provided testing function. If no values satisfy the testing function, undefined
is returned.
CodePudding user response:
This one was pretty tricky. I'm not sure why, but there are some strange visibility and event handling characteristics on the page, so I basically "brute forced" it by trying both trusted and untrusted events for clicks and selection.
For the picker trigger (size select dropdown), I used an untrusted event. Selecting the size worked best with a trusted event, and adding to cart worked with a trusted event. These might not be hard-and-fast rules, so I might have missed something, but the code below should capture a screenshot of the item in the cart.
I was also finding that the cookie banner seems to throw off the dropdown. Waiting and dismissing it improved the reliability of the script, but I eventually commented it out for speed and because it might not be necessary. I didn't do enough runs to say for sure, though, so it's left in the code below.
Here's the code:
const puppeteer = require("puppeteer"); // ^13.5.1
let browser;
(async () => {
browser = await puppeteer.launch({headless: true});
const [page] = await browser.pages();
const ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36";
await page.setExtraHTTPHeaders({"Accept-Language": "en-US,en;q=0.9"});
await page.setUserAgent(ua);
const url = "https://www.zalando.de/nike-sportswear-blazer-mid-77-sneaker-high-ni115n001-a13.html";
await page.goto(url, {waitUntil: "domcontentloaded"});
// optionally accept the cookie banner
//const cookie = await page.waitForSelector("#uc-btn-accept-banner");
//await cookie.evaluate(el => el.click());
const picker = await page.waitForSelector("#picker-trigger");
await picker.evaluate(el => el.click());
await page.waitForFunction(() =>
[...document.querySelectorAll(".fOd40J._0xLoFW.JT3_zV.FCIprz.LyRfpJ")]
.find(el => el.innerText === "39")
);
const size = await page.evaluateHandle(() =>
[...document.querySelectorAll(".fOd40J._0xLoFW.JT3_zV.FCIprz.LyRfpJ")]
.find(el => el.innerText === "39")
);
await size.click();
await page.click(".U4aOaA > .DJxzzA");
await page.evaluate(() => window.scrollTo(0, 0));
await page.waitForFunction(() =>
document.querySelector('a[title="Your bag"]')?.textContent.startsWith("1")
);
await page.goto("https://en.zalando.de/cart/");
await page.screenshot({path: "testing-in-bag.png"});
})()
.catch(err => console.error(err))
.finally(() => browser?.close())
;