puppeteer: how to wait until an element is visible?
Note, All the answers submitted until today are incorrect
Because it answer for an element if Exist or Located but NOT
Visible or Displayed
The right answer is to check an element size or visibility using page.waitFor()
or page.waitForFunction()
, see explaination below.
// wait until present on the DOM
// await page.waitForSelector( css_selector );
// wait until "display"-ed
await page.waitForFunction("document.querySelector('.btnNext') && document.querySelector('.btnNext').clientHeight != 0");
// or wait until "visibility" not hidden
await page.waitForFunction("document.querySelector('.btnNext') && document.querySelector('.btnNext').style.visibility != 'hidden'");
const btnNext = await page.$('.btnNext');
await btnNext.click();
Explanation
The element that Exist on the DOM of page not always Visible if has CSS property display:none
or visibility:hidden
that why using page.waitForSelector(selector)
is not good idea, let see the different in the snippet below.
function isExist(selector) {
let el = document.querySelector(selector);
let exist = el.length != 0 ? 'Exist!' : 'Not Exist!';
console.log(selector + ' is ' + exist)
}
function isVisible(selector) {
let el = document.querySelector(selector).clientHeight;
let visible = el != 0 ? 'Visible, ' + el : 'Not Visible, ' + el;
console.log(selector + ' is ' + visible + 'px')
}
isExist('#idA');
isVisible('#idA');
console.log('=============================')
isExist('#idB')
isVisible('#idB')
.bd {border: solid 2px blue;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="bd">
<div id="idA" style="display:none">#idA, hidden element</div>
</div>
<br>
<div class="bd">
<div id="idB">#idB, visible element</div>
</div>
on the snippet above the function isExist()
is simulate
page.waitForSelector('#myId');
and we can see while running isExist()
for both element #idA
an #idB
is return exist.
But when running isVisible()
the #idA
is not visible or dislayed.
And here other objects to check if an element is displayed or using CSS property display
.
scrollWidth
scrollHeight
offsetTop
offsetWidth
offsetHeight
offsetLeft
clientWidth
clientHeight
for style visibility
check with not hidden
.
note: I'm not good in Javascript or English, feel free to improve this answer.
If you want to ensure the element is actually visible, you have to use
page.waitForSelector('#myId', {visible: true})
Otherwise you are just looking for the element in the DOM and not checking for visibility.
I think you can use page.waitForSelector(selector[, options])
function for that purpose.
const puppeteer = require('puppeteer');
puppeteer.launch().then(async browser => {
const page = await browser.newPage();
page
.waitForSelector('#myId')
.then(() => console.log('got it'));
browser.close();
});
To check the options avaible, please see the github link.