Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Puppeteer Won't Click on Element #1805

Closed
paul-phillips-ark opened this issue Jan 15, 2018 · 43 comments
Closed

Puppeteer Won't Click on Element #1805

paul-phillips-ark opened this issue Jan 15, 2018 · 43 comments

Comments

@paul-phillips-ark
Copy link

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');

        })
@fran0254
Copy link

fran0254 commented Jan 16, 2018

Try to set a time before clicking...

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

@paul-phillips-ark
Copy link
Author

That worked. Thanks. I thought that waitFor(selector) would have achieved the same thing, but I guess not. Thanks for the answer.

@aslushnikov
Copy link
Contributor

@paul-phillips-ark it looks like the javascript code responsible for handling button clicks is not evaluated yet; the page.waitForSelector makes sure that there's an element in DOM.

@immauss
Copy link

immauss commented Sep 6, 2018

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');

@piq9117
Copy link

piq9117 commented Sep 20, 2018

@immauss' solution worked out for me. thanks!

@codetherus
Copy link

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

Thanks! This solution worked for me when no others worked.

@ekrem-aktas
Copy link

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

Thanks @immauss, your solution worked for me as well after a day of investigation!

@R-Oscar
Copy link

R-Oscar commented Dec 18, 2018

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');

Worked for me as well, although I'm wondering why is it so weird and the plain .click method is not working 🤔

@samarpanda
Copy link

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

@painkkiller
Copy link

click still doesn't work but in my case any other ways didn't worked too

@pgunsolley
Copy link

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

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

@michellocana
Copy link

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?

@haikyuu
Copy link

haikyuu commented Mar 6, 2019

@michellocana try @immauss solution. That works well (in a React app)

@kissu
Copy link

kissu commented Jul 3, 2019

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])
})

@geminiyellow
Copy link

@kissu same, 3 solutions all not working.

@salemalem
Copy link

@kissu same, 3 solutions all not working.

same, what I can do?

@kissu
Copy link

kissu commented Aug 18, 2019

@salemalem not sure what actually the eval (you create a context within a context with the need to return the result AFAIK) is for, but you can simply use await page.click('button[type="submit"]') to get a basic click. 😸

@pgunsolley
Copy link

pgunsolley commented Sep 18, 2019

@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.

@ma8642
Copy link

ma8642 commented Oct 10, 2019

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

@ezy
Copy link

ezy commented Feb 25, 2020

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 })

@timothywangdev
Copy link

timothywangdev commented Mar 24, 2020

@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

@willleahy
Copy link

willleahy commented Apr 9, 2020

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

@ezy
Copy link

ezy commented Apr 9, 2020

Given that some people are having success with await, I'm assuming it's got something to do with click being triggered before the element exists on the page?

@banderson858
Copy link

In my case, I think the click is being triggered before the button is enabled. frustrating to have to explicitly wait 300ms:
await page.waitFor(300)

@stefkwan
Copy link

stefkwan commented May 12, 2020

same with @banderson858 - adding page.waitFor(some time) works, perhaps the dom is loaded into the array let arr = page.$$(selector) but is not yet rendered on browser, so click does not work. Waiting enough time for it to render makes the click work.

@macielti
Copy link

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');

this man saved my life thank you.

@SalesforceRocks
Copy link

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);

@zoffyzhang
Copy link

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());

@stefdelec
Copy link

same situation here @zoffyzhang

@dhrubodeepbasumatary
Copy link

Try to set a time before clicking...

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

That worked man!! Thanks

@abhyuday-tripathi
Copy link

@immauss

Thanks! That worked for me

@LucasSovre
Copy link

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');

It worked for Me thanks u so much !

@nickhudkins
Copy link

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)

@Minnu279
Copy link

Minnu279 commented Dec 7, 2021

I got it worked out using I.forceClick(selector);

@yossielimelech
Copy link

Nothing is working for me. I tried everything.
I'm trying to change currency in aliexpress.com, anyone has a clue?

@paddelboot
Copy link

paddelboot commented Jun 25, 2022

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.

@abozhilov
Copy link
Contributor

abozhilov commented Jul 4, 2022

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.

abozhilov added a commit to abozhilov/puppeteer that referenced this issue Jul 5, 2022
This patch fixes page.#scrollIntoViewIfNeededso that it works with devtools protocol.
Now it blocks the main thread and waits until the scrolling action finishes.

Issues: puppeteer#8627, puppeteer#1805

BREAKING CHANGE: page.#scrollIntoViewIfNeeded throws erros which come from the internal implementation.
 - `Protocol error (DOM.scrollIntoViewIfNeeded): Node is detached from document`
 - `Protocol error (DOM.scrollIntoViewIfNeeded): Node does not have a layout object`
Also now it does work with TextNode properly and does not throw an error.
abozhilov added a commit to abozhilov/puppeteer that referenced this issue Jul 7, 2022
This patch fixes page.#scrollIntoViewIfNeeded, so that it works with devtools protocol.
Now it blocks the main thread and waits until the scrolling action finishes in Chrome.
Fallbacks to the old implementation if `DOM.scrollIntoViewIfNeeded` is not supported for Firefox.

Issues: puppeteer#8627, puppeteer#1805
abozhilov added a commit to abozhilov/puppeteer that referenced this issue Jul 7, 2022
This patch fixes page.#scrollIntoViewIfNeeded, so that it works with devtools protocol.
Now it blocks the main thread and waits until the scrolling action finishes in Chrome.
Fallbacks to the old implementation if `DOM.scrollIntoViewIfNeeded` is not supported for Firefox.

Issues: puppeteer#8627, puppeteer#1805
abozhilov added a commit to abozhilov/puppeteer that referenced this issue Jul 7, 2022
This patch fixes page.#scrollIntoViewIfNeeded, so that it works with devtools protocol.
Now it blocks the main thread and waits until the scrolling action finishes in Chrome.
Fallbacks to the old implementation if `DOM.scrollIntoViewIfNeeded` is not supported for Firefox.

Issues: puppeteer#8627, puppeteer#1805
OrKoN pushed a commit to abozhilov/puppeteer that referenced this issue Jul 8, 2022
This patch fixes page.#scrollIntoViewIfNeeded, so that it works with devtools protocol.
Now it blocks the main thread and waits until the scrolling action finishes in Chrome.
Fallbacks to the old implementation if `DOM.scrollIntoViewIfNeeded` is not supported for Firefox.

Issues: puppeteer#8627, puppeteer#1805
OrKoN pushed a commit that referenced this issue Jul 8, 2022
This patch fixes page.#scrollIntoViewIfNeeded, so that it works with devtools protocol.
Now it blocks the main thread and waits until the scrolling action finishes in Chrome.
Fallbacks to the old implementation if `DOM.scrollIntoViewIfNeeded` is not supported for Firefox.

Issues: #8627, #1805
@ManelGonzalez-ops
Copy link

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

@OrKoN
Copy link
Collaborator

OrKoN commented Oct 24, 2022

@ManelGonzalez-ops pls report a new issue with the repro if you believe you encountered the bug.

@DaBossCoda
Copy link

DaBossCoda commented Jan 12, 2023

Also came across this, had to use:

await page.$eval('button[type=submit]', el => el.click())

instead of:

await page.click('button[type=submit]')

@antertsa
Copy link

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

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

This works fine for me, but how can you do it with page.$$eval() with multiple button elemets? Please note, that when each clicks occurs. then a series of actions should take place some of them using page (which is not accessible inside eval).

@LegendaryEmoji
Copy link

LegendaryEmoji commented Feb 17, 2023

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

@eaglecodezlk1
Copy link

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

await delay(2000);
await page.click("Element Selector");

working for me 2024`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests