Skip to content

Commit

Permalink
[wdspec] Add WebDriver BiDi tests to check queuing of actions.
Browse files Browse the repository at this point in the history
Differential Revision: https://phabricator.services.mozilla.com/D220899

bugzilla-url: https://bugzilla.mozilla.org/show_bug.cgi?id=1915798
gecko-commit: 2c80eec70b9b2151b287eaa3de93c85b9d2ef5a7
gecko-reviewers: webdriver-reviewers, jdescottes
  • Loading branch information
whimboo authored and moz-wptsync-bot committed Oct 1, 2024
1 parent 04d2e6c commit 22623a0
Show file tree
Hide file tree
Showing 4 changed files with 284 additions and 0 deletions.
34 changes: 34 additions & 0 deletions webdriver/tests/bidi/input/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,39 @@

from webdriver.bidi.modules.script import ContextTarget


async def add_mouse_listeners(bidi_session, context, include_mousemove=True):
result = await bidi_session.script.call_function(
function_declaration="""(include_mousemove) => {
window.allEvents = { events: []};
const events = ["auxclick", "click", "mousedown", "mouseup"];
if (include_mousemove) {
events.push("mousemove");
}
function handleEvent(event) {
window.allEvents.events.push({
type: event.type,
detail: event.detail,
clientX: event.clientX,
clientY: event.clientY,
isTrusted: event.isTrusted,
button: event.button,
buttons: event.buttons,
});
};
for (const event of events) {
document.addEventListener(event, handleEvent);
}
}""",
arguments=[{"type": "boolean", "value": include_mousemove}],
await_promise=False,
target=ContextTarget(context["context"]),
)


async def get_object_from_context(bidi_session, context, object_path):
"""Return a plain JS object from a given context, accessible at the given object_path"""
events_str = await bidi_session.script.evaluate(
Expand Down Expand Up @@ -29,6 +62,7 @@ async def get_events(bidi_session, context):
# tests expect ''.
if "code" in e and e["code"] == "Unidentified":
e["code"] = ""

return events


Expand Down
1 change: 1 addition & 0 deletions webdriver/tests/bidi/input/perform_actions/invalid.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# META: timeout=long
import pytest
import pytest_asyncio

Expand Down
123 changes: 123 additions & 0 deletions webdriver/tests/bidi/input/perform_actions/queue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import asyncio
import pytest

from webdriver.bidi.modules.input import Actions

from tests.support.helpers import filter_supported_key_events
from tests.support.keys import Keys

from .. import add_mouse_listeners, get_events, get_keys_value
from ... import recursive_compare

pytestmark = pytest.mark.asyncio


async def test_parallel_key(bidi_session, top_context, setup_key_test):
actions_1 = Actions()
actions_1.add_key().send_keys("a").key_down(Keys.SHIFT)

actions_2 = Actions()
actions_2.add_key().send_keys("B").key_up(Keys.SHIFT)

# Run both actions in parallel to check that they are queued for
# sequential execution.
actions_performed = [
bidi_session.input.perform_actions(
actions=actions_1, context=top_context["context"]
),
bidi_session.input.perform_actions(
actions=actions_2, context=top_context["context"]
),
]
await asyncio.gather(*actions_performed)

expected = [
{"code": "KeyA", "key": "a", "type": "keydown"},
{"code": "KeyA", "key": "a", "type": "keypress"},
{"code": "KeyA", "key": "a", "type": "keyup"},
{"code": "ShiftLeft", "key": "Shift", "type": "keydown"},
{"code": "KeyB", "key": "B", "type": "keydown"},
{"code": "KeyB", "key": "B", "type": "keypress"},
{"code": "KeyB", "key": "B", "type": "keyup"},
{"code": "ShiftLeft", "key": "Shift", "type": "keyup"},
]

all_events = await get_events(bidi_session, top_context["context"])
(key_events, expected) = filter_supported_key_events(all_events, expected)

recursive_compare(expected, key_events)

keys_value = await get_keys_value(bidi_session, top_context["context"])
assert keys_value == "aB"


async def test_parallel_pointer(bidi_session, get_test_page, top_context):
url = get_test_page()
await bidi_session.browsing_context.navigate(
context=top_context["context"],
url=url,
wait="complete")

await add_mouse_listeners(bidi_session, top_context)

point_1 = {"x": 5, "y": 10}
point_2 = {"x": 10, "y": 20}

actions_1 = Actions()
(
actions_1.add_pointer()
.pointer_move(x=point_1["x"], y=point_1["y"])
.pointer_down(button=0)
.pointer_up(button=0)
)

actions_2 = Actions()
(
actions_2.add_pointer()
.pointer_move(x=point_2["x"], y=point_2["y"])
.pointer_down(button=0)
.pointer_up(button=0)
)

# Run both actions in parallel to check that they are queued for
# sequential execution.
actions_performed = [
bidi_session.input.perform_actions(
actions=actions_1, context=top_context["context"]
),
bidi_session.input.perform_actions(
actions=actions_2, context=top_context["context"]
),
]
await asyncio.gather(*actions_performed)

common_attributes = {
"button": 0,
"buttons": 0,
"detail": 1,
"isTrusted": True,
"clientX": point_1["x"],
"clientY": point_1["y"],
}

mouse_events = [
{"type": "mousemove"},
{"type": "mousedown", "buttons": 1},
{"type": "mouseup"},
{"type": "click"},
]

# Expected events for the first action.
expected_events_1 = [{**common_attributes, **event}
for event in mouse_events]

# Expected events for the second action.
common_attributes.update(
{"clientX": point_2["x"], "clientY": point_2["y"]})
expected_events_2 = [{**common_attributes, **event}
for event in mouse_events]

events = await get_events(bidi_session, top_context["context"])

assert events[:4] == expected_events_1
assert events[4:] == expected_events_2
126 changes: 126 additions & 0 deletions webdriver/tests/bidi/input/release_actions/queue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import asyncio
import pytest

from webdriver.bidi.modules.input import Actions

from tests.support.helpers import filter_supported_key_events
from tests.support.keys import Keys

from .. import add_mouse_listeners, get_events, get_keys_value
from ... import recursive_compare


pytestmark = pytest.mark.asyncio


async def test_parallel_key(bidi_session, top_context, setup_key_test):
actions_1 = Actions()
actions_1.add_key().key_down("a").key_down(Keys.SHIFT)

actions_2 = Actions()
actions_2.add_key().key_down("b")

# Run the first release actions in-between to check that it is queued for
# sequential execution, and the state is reset before the 2nd action.
actions_performed = [
bidi_session.input.perform_actions(
actions=actions_1, context=top_context["context"]
),
bidi_session.input.release_actions(context=top_context["context"]),
bidi_session.input.perform_actions(
actions=actions_2, context=top_context["context"]
),
bidi_session.input.release_actions(context=top_context["context"]),
]
await asyncio.gather(*actions_performed)

expected = [
{"code": "KeyA", "key": "a", "type": "keydown"},
{"code": "KeyA", "key": "a", "type": "keypress"},
{"code": "ShiftLeft", "key": "Shift", "type": "keydown"},
{"code": "ShiftLeft", "key": "Shift", "type": "keyup"},
{"code": "KeyA", "key": "a", "type": "keyup"},
{"code": "KeyB", "key": "b", "type": "keydown"},
{"code": "KeyB", "key": "b", "type": "keypress"},
{"code": "KeyB", "key": "b", "type": "keyup"},
]

all_events = await get_events(bidi_session, top_context["context"])
(key_events, expected) = filter_supported_key_events(all_events, expected)

recursive_compare(expected, key_events)

keys_value = await get_keys_value(bidi_session, top_context["context"])
assert keys_value == "ab"


async def test_parallel_pointer(bidi_session, get_test_page, top_context):
url = get_test_page()
await bidi_session.browsing_context.navigate(
context=top_context["context"],
url=url,
wait="complete")

await add_mouse_listeners(bidi_session, top_context)

point_1 = {"x": 5, "y": 10}
point_2 = {"x": 10, "y": 20}

actions_1 = Actions()
(
actions_1.add_pointer()
.pointer_move(x=point_1["x"], y=point_1["y"])
.pointer_down(button=0)
)

actions_2 = Actions()
(
actions_2.add_pointer()
.pointer_move(x=point_2["x"], y=point_2["y"])
.pointer_down(button=0)
)

# Run the first release actions in-between to check that it is queued for
# sequential execution, and the state is reset before the 2nd action.
actions_performed = [
bidi_session.input.perform_actions(
actions=actions_1, context=top_context["context"]
),
bidi_session.input.release_actions(context=top_context["context"]),
bidi_session.input.perform_actions(
actions=actions_2, context=top_context["context"]
),
bidi_session.input.release_actions(context=top_context["context"]),
]
await asyncio.gather(*actions_performed)

common_attributes = {
"button": 0,
"buttons": 0,
"detail": 1,
"isTrusted": True,
"clientX": point_1["x"],
"clientY": point_1["y"],
}

mouse_events = [
{"type": "mousemove"},
{"type": "mousedown", "buttons": 1},
{"type": "mouseup"},
{"type": "click"},
]

# Expected events for the first action.
expected_events_1 = [{**common_attributes, **event}
for event in mouse_events]

# Expected events for the second action.
common_attributes.update(
{"clientX": point_2["x"], "clientY": point_2["y"]})
expected_events_2 = [{**common_attributes, **event}
for event in mouse_events]

events = await get_events(bidi_session, top_context["context"])

assert events[:4] == expected_events_1
assert events[4:] == expected_events_2

0 comments on commit 22623a0

Please sign in to comment.