feat(driver): add Driver.long_press on WDA and Android
This commit is contained in:
@@ -47,6 +47,9 @@ class FakeDriver(Driver):
|
|||||||
def tap(self, x: float, y: float) -> None:
|
def tap(self, x: float, y: float) -> None:
|
||||||
self.calls.append(("tap", (x, y)))
|
self.calls.append(("tap", (x, y)))
|
||||||
|
|
||||||
|
def long_press(self, x: float, y: float, duration_ms: int = 1200) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
def swipe(
|
def swipe(
|
||||||
self,
|
self,
|
||||||
start_x: float,
|
start_x: float,
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ class FakeDriver(Driver):
|
|||||||
def tap(self, x: float, y: float) -> None:
|
def tap(self, x: float, y: float) -> None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def long_press(self, x: float, y: float, duration_ms: int = 1200) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
def swipe(
|
def swipe(
|
||||||
self,
|
self,
|
||||||
start_x: float,
|
start_x: float,
|
||||||
|
|||||||
@@ -87,6 +87,17 @@ class AndroidDriver(Driver):
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise DriverError("tap failed") from exc
|
raise DriverError("tap failed") from exc
|
||||||
|
|
||||||
|
def long_press(self, x: float, y: float, duration_ms: int = 1200) -> None:
|
||||||
|
# Android ``mobile: longClickGesture`` uses a system-fixed hold
|
||||||
|
# duration; the caller's ``duration_ms`` is intentionally ignored
|
||||||
|
# (see design R2). Verify on real Appium against the running device
|
||||||
|
# driver — see plan task 2.
|
||||||
|
client = self._require_client()
|
||||||
|
try:
|
||||||
|
client.execute_script("mobile: longClickGesture", {"x": x, "y": y})
|
||||||
|
except Exception as exc:
|
||||||
|
raise DriverError("long press failed") from exc
|
||||||
|
|
||||||
def swipe(
|
def swipe(
|
||||||
self,
|
self,
|
||||||
start_x: float,
|
start_x: float,
|
||||||
|
|||||||
@@ -27,6 +27,13 @@ class Driver(ABC):
|
|||||||
def tap(self, x: float, y: float) -> None:
|
def tap(self, x: float, y: float) -> None:
|
||||||
"""Tap the screen at the given coordinates."""
|
"""Tap the screen at the given coordinates."""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def long_press(self, x: float, y: float, duration_ms: int = 1200) -> None:
|
||||||
|
"""Press and hold at the given coordinates for ``duration_ms``.
|
||||||
|
|
||||||
|
Some platforms ignore ``duration_ms`` (fixed system hold duration).
|
||||||
|
"""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def swipe(
|
def swipe(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@@ -77,6 +77,19 @@ class WDADriver(Driver):
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise DriverError("tap failed") from exc
|
raise DriverError("tap failed") from exc
|
||||||
|
|
||||||
|
def long_press(self, x: float, y: float, duration_ms: int = 1200) -> None:
|
||||||
|
# ``mobile: touchAndHold`` is an XCUITest WDA endpoint; ``duration`` is
|
||||||
|
# in seconds (float). Verify on real Appium against the running device
|
||||||
|
# driver — see plan task 2.
|
||||||
|
client = self._require_client()
|
||||||
|
try:
|
||||||
|
client.execute_script(
|
||||||
|
"mobile: touchAndHold",
|
||||||
|
{"x": x, "y": y, "duration": duration_ms / 1000},
|
||||||
|
)
|
||||||
|
except Exception as exc:
|
||||||
|
raise DriverError("long press failed") from exc
|
||||||
|
|
||||||
def swipe(
|
def swipe(
|
||||||
self,
|
self,
|
||||||
start_x: float,
|
start_x: float,
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ class FakeDriver(Driver):
|
|||||||
def tap(self, x: float, y: float) -> None:
|
def tap(self, x: float, y: float) -> None:
|
||||||
self.calls.append(("tap", (x, y)))
|
self.calls.append(("tap", (x, y)))
|
||||||
|
|
||||||
|
def long_press(self, x: float, y: float, duration_ms: int = 1200) -> None:
|
||||||
|
self.calls.append(("long_press", (x, y, duration_ms)))
|
||||||
|
|
||||||
def swipe(
|
def swipe(
|
||||||
self,
|
self,
|
||||||
start_x: float,
|
start_x: float,
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ def test_connect_failure_raises_device_offline_and_clears_client() -> None:
|
|||||||
("lock", {}),
|
("lock", {}),
|
||||||
("unlock", {}),
|
("unlock", {}),
|
||||||
("disconnect", {}),
|
("disconnect", {}),
|
||||||
|
("long_press", {"x": 1, "y": 2}),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_operation_before_connect_raises_device_offline(
|
def test_operation_before_connect_raises_device_offline(
|
||||||
@@ -255,6 +256,21 @@ def test_swipe_near_zero_distance_uses_default_speed() -> None:
|
|||||||
assert speed > 0
|
assert speed > 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_long_press_uses_long_click_gesture() -> None:
|
||||||
|
driver = _connected_driver()
|
||||||
|
driver.long_press(30, 40, duration_ms=1500)
|
||||||
|
driver._client.execute_script.assert_called_once_with(
|
||||||
|
"mobile: longClickGesture", {"x": 30, "y": 40}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_long_press_wraps_exception_into_driver_error() -> None:
|
||||||
|
driver = _connected_driver()
|
||||||
|
driver._client.execute_script.side_effect = RuntimeError("boom")
|
||||||
|
with pytest.raises(DriverError):
|
||||||
|
driver.long_press(1, 2)
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------- #
|
# --------------------------------------------------------------------------- #
|
||||||
# build_android_driver_factory
|
# build_android_driver_factory
|
||||||
# --------------------------------------------------------------------------- #
|
# --------------------------------------------------------------------------- #
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ class TreeFailingDriver(Driver):
|
|||||||
def tap(self, x: float, y: float) -> None:
|
def tap(self, x: float, y: float) -> None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def long_press(self, x: float, y: float, duration_ms: int = 1200) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
def swipe(
|
def swipe(
|
||||||
self,
|
self,
|
||||||
start_x: float,
|
start_x: float,
|
||||||
|
|||||||
Reference in New Issue
Block a user