I'm using Selenium WebDriver with the Chrome driver on OS X, implementing in Python.
I'm trying to write a test that verifies if a variety of HTML elements are completely on the screen (for example, I have a tag cloud, and because of my poor implementation, sometimes some of the words slip off the edges of the browser window, so they are half-visible).
driver.find_element_by_css_selector("div.someclass").is_displayed()
, which is the only solution I can find documented elsewhere, doesn't seem to work; that returns True even if the element is partially visible.
Is there a way that I can check the entire element (including padding etc.) is visible within the standard browser viewport?
I'm implementing in Python, so Python-flavored answers would be most useful.
Another way to check if an element is hidden is to use the window. getComputedStyle() method. It will return the display property value of the object. We can check if the string is equal to none meaning the element is hidden and do something.
The best method I have found so far is the jQuery appear plugin. Works like a charm. Mimics a custom "appear" event, which fires when an element scrolls into view or otherwise becomes visible to the user.
Elements are considered visible if they consume space in the document. Visible elements have a width or height that is greater than zero.
You could acquire the element's position and size as well as the window's current X/Y offsets (position) and size to determine whether or not the element is completely in view.
With this information, you can conclude that, in order for the element to be completely within the window, the following must be true:
First, get the element's location and size. The location
property will give you the coordinates of the top-left corner of the element in the canvas. The size
property will give you the width and height of the element.
elem = driver.find_element_by_id('square100x100')
elem_left_bound = elem.location.get('x')
elem_top_bound = elem.location.get('y')
elem_width = elem.size.get('width')
elem_height = elem.size.get('height')
You can determine if the current window view meets this criteria by getting the X/Y offsets (position) and the size of the window.
You can get the offsets by executing some javascript. The following should work for all compliant browsers. I personally tested in Chrome, Firefox, and Safari. I know IE will probably need a little massaging.
win_upper_bound = driver.execute_script('return window.pageYOffset')
win_left_bound = driver.execute_script('return window.pageXOffset')
win_width = driver.execute_script('return document.documentElement.clientWidth')
win_height = driver.execute_script('return document.documentElement.clientHeight')
With the above, we've determined the size and position of the element as well as the size and position of the viewing window. From this data, we can now do some calculations to tell if the element is in view.
def element_completely_viewable(driver, elem):
elem_left_bound = elem.location.get('x')
elem_top_bound = elem.location.get('y')
elem_width = elem.size.get('width')
elem_height = elem.size.get('height')
elem_right_bound = elem_left_bound + elem_width
elem_lower_bound = elem_top_bound + elem_height
win_upper_bound = driver.execute_script('return window.pageYOffset')
win_left_bound = driver.execute_script('return window.pageXOffset')
win_width = driver.execute_script('return document.documentElement.clientWidth')
win_height = driver.execute_script('return document.documentElement.clientHeight')
win_right_bound = win_left_bound + win_width
win_lower_bound = win_upper_bound + win_height
return all((win_left_bound <= elem_left_bound,
win_right_bound >= elem_right_bound,
win_upper_bound <= elem_top_bound,
win_lower_bound >= elem_lower_bound)
)
This will also include padding and borders on an element, but not margins. If you want margins to be factored in, you'll want to get the value of the relevant CSS properties.
Additionally, you may want to check other things like opacity, whether it's displayed, z-index, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With