guys so I do want to click a button, here is my code and the error that I get:
await page.goto("http://website.com", {waitUntil: 'networkidle0'});
await page.click("[type=submit]")
// ERROR
Node is either not visible or not an HTMLElement
I have even tried to wait for selector, still the same results, tried to get it with Xpath, the same resut
However, when I open the console in the same tab, even on the webdriver itself, using:
document.querySelector("[type=submit]")
// It returns this:
<button class="AnimatedForm__submitButton m-full-width" data-step="email" type="submit">
So basically the button is there but my puppeter can't find it. I can't see it to be inside an iframe. What else can it be ?
I have tried this as well:
await page.evaluate(selector=>{
return document.querySelector(['[type=submit]']).click();})
// ERROR
TypeError: Cannot read property 'click' of undefined
Here is an example of a button inside an iframe:
index.html
<!DOCTYPE html>
<html>
<body>
<iframe name="myFrame" src="frame.html"></iframe>
</body>
</html>
frame.html
<!DOCTYPE html>
<html>
<body>
<script>
function myFunction() {
document.querySelector('body').style.backgroundColor = 'red'
}
</script>
<button class="AnimatedForm__submitButton m-full-width" data-step="email" type="submit" onclick="myFunction()">
Michelle Branch - Spirit Room
</button>
</body>
</html>
If you run document.querySelector('[type=submit]') in the browser it will return the button correctly.
But why won't it work in puppeteer then?
The page means the index.html's DOM. Puppeteer can reach only elements within its normal DOM.
const page = await browser.newPage()
But not the DOM within the iframe. It will be the scope of frame.html's DOM, we can get it with page.frames() like this (e.g. by its name attribute):
const frame = page.frames().find((frame) => frame.name() === 'myFrame')
Then we can communicate with the inner button as well. E.g.:
script.js
const puppeteer = require('puppeteer')
;(async () => {
const browser = await puppeteer.launch({ headless: false })
const page = await browser.newPage()
await page.goto('.../index.html')
// await page.click('[type=submit]') // it doesn't find the element ❌
const frame = page.frames().find((frame) => frame.name() === 'myFrame')
await frame.click('[type=submit]') // it finds the element ✅
// await browser.close()
})()