mozilla / geckodriver

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

Click on link with block child silently fails #1007

Open elliterate opened 7 years ago

elliterate commented 7 years ago

Given a link with a block-level child (i.e., display: block), clicking on it will silently fail. No JavaScript or navigation is triggered. (Clicking on the child, however, will work.)

System

Testcase

test_click_link.py

import inspect
import os.path
from unittest import TestCase, main

from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

_DIR = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))

class TestClickLink(TestCase):
    @classmethod
    def setUpClass(cls):
        capabilities = DesiredCapabilities.FIREFOX.copy()
        capabilities["marionette"] = True
        capabilities["moz:firefoxOptions"] = {"log": {"level": "trace"}}
        cls.browser = webdriver.Firefox(capabilities=capabilities)

    def setUp(self):
        self.browser.get("file://{}".format(os.path.join(_DIR, "index.html")))
        self.result = self.browser.find_element_by_id("result")

    def tearDown(self):
        self.browser.get("about:blank")

    @classmethod
    def tearDownClass(cls):
        cls.browser.quit()

    def test_click_link_without_child(self):
        link = self.browser.find_element_by_link_text("No Child")
        link.click()
        self.assertEqual(self.result.text, "Link was clicked.")

    def test_click_link_with_block_child(self):
        link = self.browser.find_element_by_link_text("Block Child")
        link.click()
        self.assertEqual(self.result.text, "Link was clicked.")

    def test_click_link_with_inline_child(self):
        link = self.browser.find_element_by_link_text("Inline Child")
        link.click()
        self.assertEqual(self.result.text, "Link was clicked.")

if __name__ == "__main__":
    main()

index.html

<html>
  <head>
    <script type="text/javascript">
      function handleClick(e) {
        e.preventDefault();
        document.querySelector("#result").innerText = "Link was clicked.";
      }
    </script>
  </head>

  <body>
    <div id="result"></div>
    <a href="#" onclick="handleClick(event)">No Child</a>
    <a href="#" onclick="handleClick(event)"><div>Block Child</div></a>
    <a href="#" onclick="handleClick(event)"><span>Inline Child</span></a>
  </body>
</html>

Stacktrace

$ python test_click_link.py
F..
======================================================================
FAIL: test_click_link_with_block_child (__main__.TestClickLink)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_click_link.py", line 39, in test_click_link_with_block_child
    self.assertEqual(self.result.text, "Link was clicked.")
AssertionError: '' != 'Link was clicked.'
+ Link was clicked.

----------------------------------------------------------------------
Ran 3 tests in 4.758s

FAILED (failures=1)

Trace-level log

geckodriver.log.txt

elliterate commented 7 years ago

This may be related to #322.

whimboo commented 6 years ago

Thank you for the detailed report. I had a look at it, and indeed is a dupe of issue #322. It's also covered by bug 1374283 for Marionette.

elliterate commented 6 years ago

@whimboo #322 was just closed because it doesn't have "a concrete description of the problem or a trace log [you] can use to debug it." Can this one be re-opened, then? While this test passes in Firefox 57.0.4 (and geckodriver 0.19.1), it now fails loudly in 58.0b14 and 59.0a1 with the following:

$ python test_click_link.py
E..
======================================================================
ERROR: test_click_link_with_block_child (__main__.TestClickLink)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_click_link.py", line 38, in test_click_link_with_block_child
    link.click()
  File "/Users/ian/.pyenv/versions/2.7.9/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py", line 78, in click
    self._execute(Command.CLICK_ELEMENT)
  File "/Users/ian/.pyenv/versions/2.7.9/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py", line 499, in _execute
    return self._parent.execute(command, params)
  File "/Users/ian/.pyenv/versions/2.7.9/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 297, in execute
    self.error_handler.check_response(response)
  File "/Users/ian/.pyenv/versions/2.7.9/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 194, in check_response
    raise exception_class(message, screen, stacktrace)
ElementNotInteractableException: Message: Element <a href="#"> could not be scrolled into view

----------------------------------------------------------------------
Ran 3 tests in 6.705s

FAILED (errors=1)

Trace-level log

geckodriver.log.2.txt

andreastt commented 6 years ago

Sounds like a fallout from the changes to make Element Click conform to the WebDriver standard, but this needs more investigation.

whimboo commented 6 years ago

The failure here happens for the following <a> node:

<a href="#" onclick="handleClick(event)"><div>Block Child</div></a>

So the <div> is completely overlaying the link here. This should be https://bugzilla.mozilla.org/show_bug.cgi?id=1374283.