puppeteer: Puppeteer Won't Click on Element

Trying to get Puppeteer to navigate through my login page which will bring the automated test to the main page of my site. It all works until it reaches ‘waitFor(’#idSIButton9’);'. Puppeteer successfully enters the password and username but can’t seem to select the submit button(#idSIButton9). Any idea what might be going wrong here? Let me know if you guys need more info. Thanks 😃

const puppeteer = require('puppeteer');
    const { defineSupportCode } = require('cucumber')

    defineSupportCode(({ Before, Given, When, Then }) => {
        Before({ timeout: 60 * 1000 }, async function testCase() {

            this.browser = await puppeteer.launch({ headless: false });

            this.page = await this.browser.newPage();

            await this.page.setViewport({width: 1024, height: 768});

            await this.page.goto('http://localhost:3000', {waitUntil: 'networkidle2'});

            await this.page.screenshot({ path: 'test_artifacts/img/load.png', fullPage: true });

            await this.page.waitFor('button');

            await this.page.click('button');

            await this.page.waitFor('#i0116');

            await this.page.type('#i0116', 'username');

            await this.page.waitFor('#i0118');

            await this.page.type('#i0118', 'password');

            await this.page.waitFor('#idSIButton9');

            await this.page.click('#idSIButton9');

        })

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 3
  • Comments: 43 (2 by maintainers)

Commits related to this issue

Most upvoted comments

Try to set a time before clicking…

await this.page.waitFor(2000);
await this.page.click('#idSIButton9');

In my case, I’m able to use this reliably:

page.$eval(selectorStr, elem => elem.click());

I managed to get around this by first selecting the submit button, and then typing a “\n”

await page.focus(’ tr:nth-child(3) > td:nth-child(2) > input[type=“submit”]’ ) await page.keyboard.type(‘\n’);

my situation:

// not work
await page.waitForSelector(mySelector);
await page.click(mySelector);

// not work 
await page.waitForSelector(mySelector);
await page.focus(mySelector);
await page.click(mySelector);

// work
await page.$eval(mySelector, (elem) => elem.click());

Wondering why the plain page.click('selector') doesn’t work?

For me what ended up working was simulating a ‘tab’ press until I got to the button, then hitting ‘enter’:

await browserPage.keyboard.press('Tab', { browserPage }); // navigate to button await browserPage.keyboard.type('\n'); // hit enter

My journey of pain:

Element that needs to be clicked in order to make visible a popup that I then need to scrape:

<a href="#" onclick="fetchInfoByID('12345');return false;">Somewhere</a>

1st try:

await page.waitForSelector( ".someselector a", { timeout: 7000 } ); await page.click( '.someselector a' )

Got error: Node is either not clickable or not an HTMLElement

2nd try:

Becaus it is actually a list of items I have to click:

const listItems = ( await page.$$( "ul li a" ) ); for ( let item of listItems ) { await item.evaluate( i => i.click(), item ); await page.waitForSelector( "div#modal", { visible: true, timeout: 3000 } ); }

Got error: TimeoutError: waiting for selector 'div#modal'. So the link is clicked (according to puppeteer), but it doesn’t trigger the popup window that I need to scrape.

3rd try:

To make debugging easier, I contented myself with trying to just click the 1st item in the list:

await page.waitForTimeout( 2000 ); await page.click( '.someselector a' );

Works 50% of the time, plus I have a timeout of 2 sec. Obviously not ideal.

4th try:

According to above comments:

await page.$eval( ".someselector a", elem => elem.click());

Never works.

Is this lib even production ready? I’m wasting a lot of my clients money here.

I tried all solutions provided above but none worked. Then I realized that the button was outside of the visible region in my browser (not using headless puppeteer since I am testing my script and want to see if it works). I just put the focus on the element and clicked. It worked.

await page.waitForSelector(mySelector); await page.focus(mySelector); await page.click(mySelector);

Not to be a broken record, but does anyone understand why eval would work but click would not? In my case, I have two tests inside of a describe block in jest, and click works in the first but not in the second…

test('one', async () => {
  // Works fine
  await page.click('#create-button);
});

test('one', async () => {
  // Does not work
  await page.click('#edit-button');
  // but this does work
  await page.$eval('#edit-button', el => el.click());
});

version is 2.1.1

For people who are trying to click on <select> element or some other selecting element for clicking its children options, the last approach you can use is setting the tabIndex attribute on the element and using keyboard to open it:

await page.evaluate(() => document.querySelector("selector").setAttribute("tabIndex", "1"));

await page.keyboard.press("Tab");
await page.keyboard.press("Enter");
// After pressing tab and enter, you've essentially opened the selecting element.

Original Source: @ma8642’s comment

Just wanted to drop a note to explain why doing page.evaluate(() => document.querySelector(sel).click()) works but (await page.waitForSelector(sel)).click() does not.

.click() on a puppeteer ElementHandle uses synthetic mouse input to perform the click. If there is anything obscuring your element, this will not behave as you expect, while the page.evaluate... method will result in the click handler being fired (obscured element or not)

Depending on your use case, one might be more appropriate than the other! Hope this helps someone if they’re smashing their head into their desk trying to understand how these are different (as I did)

@kissu The problem noted was that simply using await page.click() was not working. Using page.$eval() was able to circumvent issues, due to implementation details inside puppeteer. I’m not sure about the current state of this issue.

We are still experiencing this issue in 4.4.0. Switching to page.$eval() works

@kissu The problem noted was that simply using await page.click() was not working. Using page.$eval() was able to circumvent issues, due to implementation details inside puppeteer. I’m not sure about the current state of this issue.

I’m having the same issue trying to click a button that is conditionally rendered (with React btw). Maybe it has something to do with the async rendering nature of React?

`const delay = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));

await delay(2000); await page.click(“Element Selector”);

working for me 2024`

How can this issue be closed? This is plenty of ridiculous bugs

Why this is closed?

Simple script which reproduces the issue:

import puppeteer from 'puppeteer';

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  await page.goto('https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set');
    
  await Promise.all([
    page.waitForNavigation(),
    page.click('#set\\.prototype\\.keys > a')
  ]);

  await browser.close();
})();

Obviously the logic of clickablePoint - https://github.com/puppeteer/puppeteer/blob/main/src/common/ElementHandle.ts#L339 must be revisited. The exact same scenario fails in chrome recorder/replay.

from https://stackoverflow.com/questions/56226990/puppeteers-page-click-is-working-on-some-links-but-not-others/56227068

Try using ignoreHTTPSErrors option set to true:

puppeteer.launch({ ignoreHTTPSErrors: true, headless: false })

I have to admit that I don’t see why something like

await page.$eval('h3', titles => titles[1].click())

is not working…

Even that one is not good neither

let selectors = await page.$$('h3')
await page.$$eval(selectors[1].click())

neither this one…

const result = await page.evaluate(async() => {
  let selectors = document.querySelectorAll('h3')
  await page.click(selectors[1])
})