testing/web-platform/tests/webdriver/tests/element_click/bubbling.py
author Henrik Skupin <mail@hskupin.info>
Tue, 24 Apr 2018 18:57:48 +0200
changeset 792546 91ef9aae32eb1e07de7c9dd7d8f51de0080e5ccc
parent 789448 9d124f189e612ef45f466456934ccc1b1a4ff824
child 826306 33f13bf47338a0d254820a416a16389528c0b9df
permissions -rw-r--r--
Bug 1455568 - [wdspec] Use shared command function for each WebDriver command. Tests for a specific command have to use a shared function for each of the included tests of a module to avoid redefinition of the same code. In a follow-up patch those shared methods could even be separated out as fixtures for each of the sub folders. MozReview-Commit-ID: 11lAp7J8IoZ

from tests.support.asserts import assert_success
from tests.support.inline import inline


def element_click(session, element):
    return session.transport.send(
        "POST", "/session/{session_id}/element/{element_id}/click".format(
            session_id=session.session_id,
            element_id=element.id))


def test_click_event_bubbles_to_parents(session):
    session.url = inline("""
        <style>
        body * {
          margin: 10px;
          padding: 10px;
          border: 1px solid blue;
        }
        </style>

        <div id=three>THREE
          <div id=two>TWO
            <div id=one>ONE</div>
          </div>
        </div>

        <script>
        window.clicks = [];

        var elements = document.querySelectorAll("div");
        for (var level = 0; level < elements.length; level++) {
          elements[level].addEventListener("click", function(clickEvent) {
            window.clicks.push(clickEvent.currentTarget);
          });
        }
        </script>
        """)
    three, two, one = session.find.css("div")
    one.click()

    clicks = session.execute_script("return window.clicks")
    assert one in clicks
    assert two in clicks
    assert three in clicks


def test_spin_event_loop(session):
    """
    Wait until the user agent event loop has spun enough times to
    process the DOM events generated by clicking.
    """
    session.url = inline("""
        <style>
        body * {
          margin: 10px;
          padding: 10px;
          border: 1px solid blue;
        }
        </style>

        <div id=three>THREE
          <div id=two>TWO
            <div id=one>ONE</div>
          </div>
        </div>

        <script>
        window.delayedClicks = [];

        var elements = document.querySelectorAll("div");
        for (var level = 0; level < elements.length; level++) {
          elements[level].addEventListener("click", function(clickEvent) {
            var target = clickEvent.currentTarget;
            setTimeout(function() { window.delayedClicks.push(target); }, 100);
          });
        }
        </script>
        """)
    three, two, one = session.find.css("div")
    one.click()

    delayed_clicks = session.execute_script("return window.delayedClicks")
    assert one in delayed_clicks
    assert two in delayed_clicks
    assert three in delayed_clicks


def test_element_disappears_during_click(session):
    """
    When an element in the event bubbling order disappears (its CSS
    display style is set to "none") during a click, Gecko and Blink
    exhibit different behaviour.  Whilst Chrome fires a "click"
    DOM event on <body>, Firefox does not.

    A WebDriver implementation may choose to wait for this event to let
    the event loops spin enough times to let click events propagate,
    so this is a corner case test that Firefox does not hang indefinitely.
    """
    session.url = inline("""
        <style>
        #over,
        #under {
          position: absolute;
          top: 8px;
          left: 8px;
          width: 100px;
          height: 100px;
        }

        #over {
          background: blue;
          opacity: .5;
        }
        #under {
          background: yellow;
        }

        #log {
          margin-top: 120px;
        }
        </style>

        <body id="body">
          <div id=under></div>
          <div id=over></div>

           <div id=log></div>
        </body>

        <script>
        let under = document.querySelector("#under");
        let over = document.querySelector("#over");
        let body = document.querySelector("body");
        let log = document.querySelector("#log");

        function logEvent({type, target, currentTarget}) {
          log.innerHTML += "<p></p>";
          log.lastElementChild.textContent =
              `${type} in ${target.id} (handled by ${currentTarget.id})`;
        }

        for (let ev of ["click", "mousedown", "mouseup"]) {
          under.addEventListener(ev, logEvent);
          over.addEventListener(ev, logEvent);
          body.addEventListener(ev, logEvent);
        }

        over.addEventListener("mousedown", function(mousedownEvent) {
          over.style.display = "none";
        });
        </script>
        """)
    over = session.find.css("#over", all=False)

    # should not time out
    response = element_click(session, over)
    assert_success(response)