Click visible elements using puppeteer
Short Answer
const element = await page.waitForSelector('a.cookie-close', { visible: true });await element.click();
This uses the page.waitForSelector
function to select a visible element with the selector a.cookie-close
. After the selector is queried, the code uses elementHandle.click
to click on it.
Explanation
Only the functions page.waitForSelector
and page.waitForXPath
have an option built in that checks if an element is not only present but also visible. When used, puppeteer will check if the style attribute visibility
is not hidden
and if the element has a visible bounding box.
Making sure the element is not empty
Even if the element is visible, it might be empty (e.g. <span></span>
). If you also want the element not to be empty too, you can use the following query instead:
const element = await page.waitForSelector('SELECTOR:not(:empty)', { visible: true });
This will in addition use the pseudo selectors :empty
and :not
to make sure that the element contains a child node or text. If you want to query for a specific text inside the element, you might want to check out this answer.
Similar to Selenium, the correct answer is to also use Puppeteer's waitForSelector which can test for DOM element presence and visibility.
try { // Will throw err if element is not present and visible. await chromePage.waitForSelector("div.hello", { visible: true }); await chromePage.click("div.hello");} catch(err) { console.log(err);}
Here's a more idiomatic way wait for an element to be "displayed" before clicking. The result should be the same as to what @joquarky explained:
click() { let retries = 5; const hoverAndClick = () => { return this._element!.hover() // this._element is ElementHandle .then(() => { return this._element!.click(); }) .catch(err => { if (retries <= 0) { throw err; } retries -= 1; sleep(1000).then(hoverAndClick); }); }; return hoverAndClick();}
The slight different here is that we retry a few times in case the element is waiting for a transition, due to any of its parents hiding it.