How to determine the visibility of an element with Puppeteer?
According to the documentation, elementHandle.BoundingBox () returns null when the element is invisible. However, when I run tests, this answer does not suit me. The test polls a lot of items and I need details when it "crashes". How do I still get the full visibility state of an element?
0
1 answers
For myself, I solved the problem as follows. I collect the state by visibility criteria such as:
- availability in the DOM (isAvailable)
- the CSS display property is not equal to none
- the CSS visibility property is not set to hidden
- the CSS opacity property is not equal to 0
- visibility within the current viewport
The API looks like this:
const elh = await page.$( "#element" ),
result = await target( elh ).isVisible();
Example of results:
{
"isAvailable": true,
"display": "none",
"visibility": "visible",
"opacity": 1,
"isIntersecting": false
}
And finally the method code:
/**
* @param {ElementHandle} elementHandle
* @returns {Function}
*/
function target( elementHandle ) {
return {
/**
* Check if element is visible in the DOM
* @returns {Promise<Object>}
**/
isVisible: async function(){
if ( elementHandle === false ) {
return {
isAvailable: false
};
}
const isIntersectingViewport = await elementHandle.isIntersectingViewport(),
handleOpacity = await page.evaluateHandle( ( el ) =>
window.getComputedStyle( el, null ).getPropertyValue( "opacity" ), elementHandle ),
handleVisibility = await page.evaluateHandle( ( el ) =>
window.getComputedStyle( el, null ).getPropertyValue( "visibility" ), elementHandle ),
handleDisplay = await page.evaluateHandle( ( el ) =>
window.getComputedStyle( el, null ).getPropertyValue( "display" ), elementHandle ),
opacity = parseFloat( await handleOpacity.jsonValue() ),
visibility = await handleVisibility.jsonValue(),
display = await handleDisplay.jsonValue();
return {
isAvailable: true,
display,
visibility,
opacity,
isIntersecting: isIntersectingViewport
};
}
};
}
0
Author: Dmitry Sheiko, 2020-01-29 12:09:39