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?

Author: insolor, 2020-01-29

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