Selenium: Python Selenium element.is_displayed returning true even when element is not visible on the page

Created on 12 Sep 2017  Â·  9Comments  Â·  Source: SeleniumHQ/selenium

Meta -

OS:
Linux Ubuntu 16.04
Selenium Version:
3.4.3
Browser:
Chrome

Browser Version:
60.0.3112.113

Expected Behavior -

I am testing the functionality of a hamburger nav that displays a menu sidebar when clicked. The menu is hidden by setting transform:TranslateX to -17rem via css. Before clicking hamburger icon, the x property of the menu sidebar is -272 (not visible, not displayed). The actual starting and ending pixels of the element are -272 (left edge) to 0 (right edge). After clicking, the x property is 0 (you can see the menu on the page). The actual starting and ending pixels of the element are 0 (left edge) to 272 (right edge).

When I use the element.is_displayed() method before clicking, the method returns True even though the element is clearly, definitely not visible on the page.
The expected behavior is that before clicking the hamburger icon to open the menu sidebar, the element.is_displayed() returns False

Actual Behavior -

element.is_displayed() returns True even though element is not visible

Steps to reproduce -

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

options = webdriver.ChromeOptions()
options.add_argument('--ignore-certificate-errors')
options.add_argument("--test-type")
options.binary_location = "/usr/bin/google-chrome"
driver = webdriver.Chrome(chrome_options=options)
driver.get("http://www.wesh.com")

#disable flex ad
driver.execute_script("""
        setInterval(function() {
            var $flex = document.querySelector("#ad-flex");
            //$flex.style.display = "none";
            $flex && $flex.parentNode && $flex.parentNode.removeChild($flex);
        }, 1);
        """)

#get menu sidebar, which is not visible initially unless you click the hamburger nav icon
sidebar = driver.find_element_by_css_selector("nav.sidepanel")
hamburger_nav = driver.find_element_by_css_selector("a.header-button.header-sidepanel-button")       

sidebar_visible_before = sidebar.is_displayed()
hamburger_nav.click()
time.sleep(.5)  
sidebar_visible_after = sidebar.is_displayed()

print("visible before click", sidebar_visible_before)
print("visible after click", sidebar_visible_after)
driver.quit()
A-needs decision R-awaiting answer

Most helpful comment

Probably another method is needed - one to tell whether element is displayed on the page at all. And one is_visible to tell whether the user can see it.

All 9 comments

I just changed the driver to Firefox and am getting the same results, fyi.

At present, it's a kind of deliberate decision, no Selenium driver checks element position and elements overlapping when "calculating" visibility.

The source for element.is_displayed() is documented with """Whether the element is visible to a user.""" In this example, because the element begins and ends outside of the viewport (-272px to 0 / left to right edge) it's clearly not visible to the user and fits the documentation on the source[https://seleniumhq.github.io/selenium/docs/api/py/_modules/selenium/webdriver/remote/webelement.html#WebElement.is_displayed]. I don't think it's a question of the element being overlapped with another element in this example ... its position is such that it's not part of the viewport - maybe you can add code to check if the elements right edge < window.x, elements bottom edge < window.y, etc?

Probably another method is needed - one to tell whether element is displayed on the page at all. And one is_visible to tell whether the user can see it.

Can we get this issue a bit more traction? I has 11 upvotes...

Pull requests are always welcome!
MM

Sent from my iPhone

On Apr 29, 2020, at 5:36 PM, Crt Mori notifications@github.com wrote:


Can we get this issue a bit more traction? I has 11 upvotes...

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.

Assuming this issue is still relevant, here is some information I found...

The W3C WebDriver spec does not define explicitly how to determine if an element is visible or not. It recommends how the implementation could be done, check the description here.

From the link above:

The approach recommended to implementors to ascertain an element’s visibility was originally developed by the Selenium project, and is based on crude approximations about an element's nature and relationship in the tree. An element is in general to be considered visible if any part of it is drawn on the canvas within the boundaries of the viewport.
The element displayed algorithm is a boolean state where true signifies that the element is displayed and false signifies that the element is not displayed. To compute the state on element, invoke the Call(bot.dom.isShown, null, element). If doing so does not produce an error, return the return value from this function call. Otherwise return an error with error code unknown error.

So probably that call (if it is the implementation chosen one by the driver) is returning true. Could you try it with the element and see what it returns?

In the end, it is not something in the Python bindings but more what the driver is returning.

I'll close this since the issue went stale and no more comments from the community were received.

Just because nobody jumped on trying, I do not think this issue should be closed. I think naturally anyone writing a test case would assume that is_displayed method actually confirms that user can see it, not that it is hidden outside of the viewport and just "displayed" in code.

Was this page helpful?
0 / 5 - 0 ratings