| import pytest |
| |
| from webdriver.bidi.modules.input import Actions, get_element_origin |
| |
| from tests.support.asserts import assert_move_to_coordinates |
| from tests.support.helpers import filter_dict |
| |
| from .. import get_events |
| from . import get_element_rect, get_inview_center_bidi |
| |
| pytestmark = pytest.mark.asyncio |
| |
| |
| async def test_click_at_coordinates(bidi_session, top_context, load_static_test_page): |
| await load_static_test_page(page="test_actions.html") |
| |
| div_point = { |
| "x": 82, |
| "y": 187, |
| } |
| actions = Actions() |
| ( |
| actions.add_pointer() |
| .pointer_move(x=div_point["x"], y=div_point["y"], duration=1000) |
| .pointer_down(button=0) |
| .pointer_up(button=0) |
| ) |
| await bidi_session.input.perform_actions( |
| actions=actions, context=top_context["context"] |
| ) |
| |
| events = await get_events(bidi_session, top_context["context"]) |
| |
| assert len(events) == 4 |
| assert_move_to_coordinates(div_point, "outer", events) |
| |
| for e in events: |
| if e["type"] != "mousedown": |
| assert e["buttons"] == 0 |
| assert e["button"] == 0 |
| |
| expected = [ |
| {"type": "mousedown", "buttons": 1}, |
| {"type": "mouseup", "buttons": 0}, |
| {"type": "click", "buttons": 0}, |
| ] |
| filtered_events = [filter_dict(e, expected[0]) for e in events] |
| assert expected == filtered_events[1:] |
| |
| |
| async def test_context_menu_at_coordinates( |
| bidi_session, top_context, load_static_test_page |
| ): |
| await load_static_test_page(page="test_actions.html") |
| |
| div_point = { |
| "x": 82, |
| "y": 187, |
| } |
| |
| actions = Actions() |
| ( |
| actions.add_pointer() |
| .pointer_move(x=div_point["x"], y=div_point["y"]) |
| .pointer_down(button=2) |
| .pointer_up(button=2) |
| ) |
| await bidi_session.input.perform_actions( |
| actions=actions, context=top_context["context"] |
| ) |
| |
| events = await get_events(bidi_session, top_context["context"]) |
| assert len(events) == 4 |
| |
| expected = [ |
| {"type": "mousedown", "button": 2}, |
| {"type": "contextmenu", "button": 2}, |
| ] |
| filtered_events = [filter_dict(e, expected[0]) for e in events] |
| mousedown_contextmenu_events = [ |
| x for x in filtered_events if x["type"] in ["mousedown", "contextmenu"] |
| ] |
| assert expected == mousedown_contextmenu_events |
| |
| |
| async def test_click_element_center( |
| bidi_session, top_context, get_element, load_static_test_page |
| ): |
| await load_static_test_page(page="test_actions.html") |
| |
| outer = await get_element("#outer") |
| center = await get_inview_center_bidi( |
| bidi_session, context=top_context, element=outer |
| ) |
| |
| actions = Actions() |
| ( |
| actions.add_pointer() |
| .pointer_move(x=0, y=0, origin=get_element_origin(outer)) |
| .pointer_down(button=0) |
| .pointer_up(button=0) |
| ) |
| |
| await bidi_session.input.perform_actions( |
| actions=actions, context=top_context["context"] |
| ) |
| |
| events = await get_events(bidi_session, top_context["context"]) |
| assert len(events) == 4 |
| |
| event_types = [e["type"] for e in events] |
| assert ["mousemove", "mousedown", "mouseup", "click"] == event_types |
| for e in events: |
| if e["type"] != "mousemove": |
| assert e["pageX"] == pytest.approx(center["x"], abs=1.0) |
| assert e["pageY"] == pytest.approx(center["y"], abs=1.0) |
| assert e["target"] == "outer" |
| |
| |
| async def test_click_navigation( |
| bidi_session, |
| top_context, |
| url, |
| inline, |
| subscribe_events, |
| wait_for_event, |
| get_element, |
| ): |
| await subscribe_events(events=["browsingContext.load"]) |
| |
| destination = url("/webdriver/tests/support/html/test_actions.html") |
| start = inline(f'<a href="{destination}" id="link">destination</a>') |
| |
| async def click_link(): |
| link = await get_element("#link") |
| |
| actions = Actions() |
| ( |
| actions.add_pointer() |
| .pointer_move(x=0, y=0, origin=get_element_origin(link)) |
| .pointer_down(button=0) |
| .pointer_up(button=0) |
| ) |
| await bidi_session.input.perform_actions( |
| actions=actions, context=top_context["context"] |
| ) |
| |
| # repeat steps to check behaviour after document unload |
| for _ in range(2): |
| await bidi_session.browsing_context.navigate( |
| context=top_context["context"], url=start, wait="complete" |
| ) |
| |
| on_entry = wait_for_event("browsingContext.load") |
| await click_link() |
| event = await on_entry |
| assert event["url"] == destination |
| |
| |
| @pytest.mark.parametrize("drag_duration", [0, 300, 800]) |
| @pytest.mark.parametrize( |
| "dx, dy", [(20, 0), (0, 15), (10, 15), (-20, 0), (10, -15), (-10, -15)] |
| ) |
| async def test_drag_and_drop( |
| bidi_session, |
| top_context, |
| get_element, |
| load_static_test_page, |
| dx, |
| dy, |
| drag_duration, |
| ): |
| await load_static_test_page(page="test_actions.html") |
| |
| drag_target = await get_element("#dragTarget") |
| initial_rect = await get_element_rect( |
| bidi_session, context=top_context, element=drag_target |
| ) |
| initial_center = await get_inview_center_bidi( |
| bidi_session, context=top_context, element=drag_target |
| ) |
| |
| # Conclude chain with extra move to allow time for last queued |
| # coordinate-update of drag_target and to test that drag_target is "dropped". |
| actions = Actions() |
| ( |
| actions.add_pointer() |
| .pointer_move(x=0, y=0, origin=get_element_origin(drag_target)) |
| .pointer_down(button=0) |
| .pointer_move(dx, dy, duration=drag_duration, origin="pointer") |
| .pointer_up(button=0) |
| .pointer_move(80, 50, duration=100, origin="pointer") |
| ) |
| |
| await bidi_session.input.perform_actions( |
| actions=actions, context=top_context["context"] |
| ) |
| |
| # mouseup that ends the drag is at the expected destination |
| events = await get_events(bidi_session, top_context["context"]) |
| e = events[1] |
| assert e["type"] == "mouseup" |
| assert e["pageX"] == pytest.approx(initial_center["x"] + dx, abs=1.0) |
| assert e["pageY"] == pytest.approx(initial_center["y"] + dy, abs=1.0) |
| # check resulting location of the dragged element |
| final_rect = await get_element_rect( |
| bidi_session, context=top_context, element=drag_target |
| ) |
| assert initial_rect["x"] + dx == final_rect["x"] |
| assert initial_rect["y"] + dy == final_rect["y"] |
| |
| |
| @pytest.mark.parametrize("drag_duration", [0, 300, 800]) |
| async def test_drag_and_drop_with_draggable_element(bidi_session, top_context, |
| get_element, |
| load_static_test_page, |
| drag_duration): |
| await load_static_test_page(page="test_actions.html") |
| |
| drag_target = await get_element("#draggable") |
| drop_target = await get_element("#droppable") |
| |
| # Conclude chain with extra move to allow time for last queued |
| # coordinate-update of drag_target and to test that drag_target is "dropped". |
| actions = Actions() |
| ( |
| actions.add_pointer() |
| .pointer_move(x=0, y=0, origin=get_element_origin(drag_target)) |
| .pointer_down(button=0) |
| .pointer_move(x=0, y=0, duration=drag_duration, origin=get_element_origin(drop_target)) |
| .pointer_up(button=0) |
| ) |
| |
| await bidi_session.input.perform_actions(actions=actions, |
| context=top_context["context"]) |
| |
| # mouseup that ends the drag is at the expected destination |
| events = await get_events(bidi_session, top_context["context"]) |
| |
| drag_events_captured = [ |
| ev["type"] for ev in events |
| if ev["type"].startswith("drag") or ev["type"].startswith("drop") |
| ] |
| assert "dragstart" in drag_events_captured |
| assert "dragenter" in drag_events_captured |
| # dragleave never happens if the mouse moves directly into the drop element |
| # without intermediate movements. |
| if drag_duration != 0: |
| assert "dragleave" in drag_events_captured |
| assert "dragover" in drag_events_captured |
| assert "drop" in drag_events_captured |
| assert "dragend" in drag_events_captured |
| |
| def last_index(list, value): |
| return len(list) - list[::-1].index(value) - 1 |
| |
| # The order should follow the diagram: |
| # |
| # - dragstart |
| # - dragenter |
| # - ... |
| # - dragenter |
| # - dragleave |
| # - ... |
| # - dragleave |
| # - dragover |
| # - ... |
| # - dragover |
| # - drop |
| # - dragend |
| # |
| assert drag_events_captured.index( |
| "dragstart") < drag_events_captured.index("dragenter") |
| if drag_duration != 0: |
| assert last_index(drag_events_captured, |
| "dragenter") < last_index(drag_events_captured, "dragleave") |
| assert last_index(drag_events_captured, |
| "dragleave") < last_index(drag_events_captured, "dragover") |
| else: |
| assert last_index(drag_events_captured, |
| "dragenter") < last_index(drag_events_captured, "dragover") |
| assert last_index(drag_events_captured, |
| "dragover") < drag_events_captured.index("drop") |
| assert drag_events_captured.index( |
| "drop") == drag_events_captured.index("dragend") - 1 |