mozilla / geckodriver

WebDriver for Firefox
https://firefox-source-docs.mozilla.org/testing/geckodriver/
Mozilla Public License 2.0
7.17k stars 1.52k forks source link

Can't click a zero-height <body> element with moz:webdriverClick #1096

Open juangj opened 6 years ago

juangj commented 6 years ago

System

Testcase

If you check document.body.getClientRects()[0] you can see that Firefox considers the body element to have height 0, and document.elementsFromPoint indeed does not find the body element at the center point. (Zero-height body also came up in https://github.com/mozilla/geckodriver/issues/931, which is about screenshotting a document like this one.)

In Chrome, the body element's height is instead equal to the viewport's height, so this code works as expected in Chrome. I haven't checked IEDriver.

Some users have used this "click on the body element" strategy in the past as a means of removing focus from the current active element. Not sure to what extent that's still useful, and there is a workaround available (execute JS to blur the element). There are probably some other legitimate uses for clicking <body>.

zero_click.html

<script>
  window.onload = () => {
    document.addEventListener('click', (ev) => {
      document.getElementById('d').style['background-color'] = 'red';
      document.getElementById('d').textContent = 'clicked';
    });
  };
</script>
<style>
  #d {
    position: absolute;
    width: 200px;
    height: 200px;
    background-color: yellow;
  }
</style>
<div id="d">not clicked</div>

zero_click.py

import unittest

from selenium import webdriver

def NewDriver(use_webdriver_click):
  return webdriver.Remote(
      command_executor='http://localhost:4444',
      desired_capabilities={'moz:webdriverClick': use_webdriver_click})

class NewClickTest(unittest.TestCase):

  def _do_test(self, use_webdriver_click):
    driver = NewDriver(use_webdriver_click)
    try:
      driver.get('http://localhost/zero_body.html')
      elem = driver.find_element_by_css_selector('#d')
      self.assertEqual(elem.text, 'not clicked')
      driver.find_element_by_css_selector('body').click()
      self.assertEqual(elem.text, 'clicked')
    finally:
      driver.quit()

  def test_webdriver_click(self):
    self._do_test(True)  # This test fails.

  def test_old_click(self):
    self._do_test(False)  # This test passes.

if __name__ == '__main__':
  unittest.main()

Stacktrace

Traceback (most recent call last):
  File "zero_body.py", line 24, in test_webdriver_click
    self._do_test(True)
  File "zero_body.py", line 18, in _do_test
    driver.find_element_by_css_selector('body').click()
  File "/usr/local/google/home/juangj/selenium/selenium/webdriver/remote/webelement.py", line 77, in click
    self._execute(Command.CLICK_ELEMENT)
  File "/usr/local/google/home/juangj/selenium/selenium/webdriver/remote/webelement.py", line 493, in _execute
    return self._parent.execute(command, params)
  File "/usr/local/google/home/juangj/selenium/selenium/webdriver/remote/webdriver.py", line 297, in execute
    self.error_handler.check_response(response)
  File "/usr/local/google/home/juangj/selenium/selenium/webdriver/remote/errorhandler.py", line 194, in check_response
    raise exception_class(message, screen, stacktrace)
ElementNotInteractableException: Message: Element <body> could not be scrolled into view

Trace-level log

geckodriver.log.txt

andreastt commented 6 years ago

Whilst the box bounds of the <body> and <html> elements can be zero-height, the two are considered ‘special elements’ by the CSS Backgrounds standard: their background styling gets transposed to the document canvas. The document canvas “is the infinite surface over which the document is rendered”, and is the reason why people perceive the document element to be visible.

WebDriver used to have a provision that <body> was always ‘visible’, and maybe we need to bring this back.

I also wrote about this to the mailing list a couple of years ago, before we decided to abandon all hope on defining visibility in favour of using paint order.

akostadinov commented 6 years ago

For me being able to unfocus from any element would be a nice feature. When working with expanding menus, sometimes I detect click errors due to expanded menu. So I use site specific elements to click on for the focus to be removed from the menu. It will be one less thing to worry about if it is possible to unfocus at will.

I don't necessarily need that way to be by licking on body though!

whimboo commented 6 years ago

A blur event usually happens when the user presses a key combination which moves the focus to a different element, or clicks somewhere in the page. I don't think there should be a specific command for that. What you can do is just to use execute_script and call blur() on the element.

akostadinov commented 6 years ago

@whimboo , there are possible workarounds. As far as I can tell selenium keeps mouse pointer at the place it previously was. One can for example move to another known element on the page, or move mouse to 0,0 (assuming there is nothing problematic there) but this is some sort of a workaround still.

If mouse is over a menu, will calling blur() help menu to close? Or how do I know exactly where the mouse ended after a click on a link? The new page layout can be different from current page layout so I don't know which element the mouse is over.

whimboo commented 6 years ago

@akostadinov I feel this discussion is off-topic on this issue. If there is a problem for you, please file a new issue. Thanks.

akostadinov commented 6 years ago

@whimboo , I thought that decision about necessity to click on body would be influenced by it as original issue report has listed the use case that is not working presently. I don't have any any urgent needs ATM. Excuse me if my comments were not useful.

andreastt commented 6 years ago

Let’s be very clear, we don’t have a decision about special-casing zero-height document elements until it’s been discussed by the WebDriver WG.

schandrakandi commented 6 years ago

Am facing the same issue with firefox 58.2 - Webdriver 3.9.Chrome it works but for firefox it fails

dhapolapankaj commented 6 years ago

I am facing this issue in all browser. I am working on another Project called Galen Framework for website responsive testing. I found that the height of html body is turning out to be zero. I discovered this here

This issue was intermittent and the website I am working on involves 3 iframes. Couldn't identify the root cause.