Am I having a problem performing a click action on a selector using Puppeteer, Below is my code trying to click button also there is memory leak happing. your suggestions will be appreciated.
const puppeteer = require(‘puppeteer’);
(async () => {
const browser = await puppeteer.launch({
headless: false,
defaultViewport: null,
args: [‘–start-maximized’]
})
const page = await browser.newPage()
await page.goto('https://www.nike.com/')
const winner = await Promise.race([
page.waitForSelector('[data-path="join or login"]'),
page.waitForSelector('[data-path="sign in"]')
])
await page.click(winner._remoteObject.description)
})()
Hi Matt,
I hope this message finds you well. Thank you for providing the Puppeteer code snippet, and I appreciate your efforts in addressing potential memory issues and improving the button-clicking functionality. Below is the revised code along with an explanation of the changes made:
const puppeteer = require(‘puppeteer’);
(async () => {
let browser;
try {
browser = await puppeteer.launch({
headless: false,
defaultViewport: null,
args: [‘–start-maximized’]
});
const page = await browser.newPage();
await page.goto('https://www.nike.com/');
// Use a more specific selector directly in page.click
await page.click('[data-path="join or login"], [data-path="sign in"]');
// Give the page some time to process the click event
await page.waitForTimeout(1000);
} catch (error) {
console.error('Error occurred:', error);
} finally {
// Close the browser to avoid potential memory issues
if (browser) {
await browser.close();
}
}
})();
Hi Matt,
I trust this message finds you well. I am writing in response to your query regarding the usage of { waitUntil: 'networkidle0' }
with the page.goto
function in Puppeteer,
You need to use { waitUntil: ‘networkidle0’ } with page.goto
This tells the puppeteer to wait for the network to be idle (no requests for 500ms).
const puppeteer = require(‘puppeteer’);
(async () => {
const browser = await puppeteer.launch({
headless: false,
defaultViewport: null,
args: [‘–start-maximized’]
})
const page = await browser.newPage()
// load the nike.com page and wait for it to fully load (inc A/B scripts)
await page.goto('https://www.nike.com/', { waitUntil: 'networkidle0' })
// select whichever element appears first
var el = await page.waitForSelector('[data-path="join or login"], [data-path="sign in"]', { timeout: 1000 })
// execute click
await page.click(el._remoteObject.description)
})()
Hi MattD,
I appreciate your diligence in reviewing the code for A/B testing on our website. I have made some crucial modifications to enhance the reliability and flexibility of the automation script. Let me walk you through the changes:
They are A/B testing their website, so you may land on a page with very different selectors than you received while you visited the site from your own Chrome browser.
using XPath with contains method to grab elements by text content:
const puppeteer = require(‘puppeteer’);
(async () => {
let browser;
try {
browser = await puppeteer.launch({
headless: false,
defaultViewport: null,
args: [‘–start-maximized’]
});
const page = await browser.newPage();
await page.goto('https://www.nike.com/');
// Detect both button versions using XPath and contains method
const winner = await Promise.race([
page.waitForXPath('//span[contains(text(), "Sign In")]'),
page.waitForXPath('//span[contains(text(), "Join or Login")]')
]);
// Extract the selector from JSHandle@node
const selector = await page.evaluate(el => el._remoteObject.description, winner);
// Click on the detected button
await page.click(selector);
// Give the page some time to process the click event
await page.waitForTimeout(1000);
} catch (error) {
console.error('Error occurred:', error);
} finally {
// Close the browser to avoid potential memory issues
if (browser) {
await browser.close();
}
}
})();
The changes made to your code are:
-
Using XPath with contains: Modified page.waitForXPath to use XPath with contains method to grab elements by their text content, which is more robust in the context of A/B testing.
-
Extracted selector from JSHandle@node: Used page.evaluate to extract the selector from JSHandle@node, allowing for more flexibility in clicking the detected button.
-
Added a small delay after the click: Introduced await page.waitForTimeout(1000) to give the page some time to process the click event.