Skip to content

Commit

Permalink
Support UiObject2#click(Point) API (#59)
Browse files Browse the repository at this point in the history
* Support UiObject2#click(Point) API

* Introduce duration in uiobject2.click and deprecate timeout
  • Loading branch information
ko1in1u authored Nov 8, 2024
1 parent ff41d31 commit f56307c
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Snippet UiAutomator Release History

## 1.1.3:
* Support clicking on a point within the object's visible bounds
* Fix waitUntilTrue doesn't run when passing small wait time
* Raise an error when non-positive wait time is set
* Support clicking on specific coordinate when registering a UiWatcher
Expand Down
18 changes: 18 additions & 0 deletions docs/uiobject2.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,24 @@ True
True
```

#### Click on point

Clicks on a point within this object's visible bounds, see
[UiObject2#click(android.graphics.Point,long)](https://developer.android.com/reference/androidx/test/uiautomator/UiObject2#click\(android.graphics.Point,long\))
for more details.

```python
>>> example = ad.ui(text="Settings")
>>> example_center = example.visible_center

# Clicks on the center point.
>>> example.click(x=example_center.x, y=example_center.y)

# Clicks then releases after 10 seconds on the center point.
>>> click_then_hold_time = datetime.timedelta(seconds=10)
>>> example.click(x=example_center.x, y=example_center.y, duration=click_then_hold_time)
```

### Drag

Drag to specific point
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ public boolean clickObjAndWait(Selector selector, Long durationInMillis)
selector, uiObject2 -> uiObject2.clickAndWait(Until.newWindow(), durationInMillis));
}

@Rpc(description = "Clicks on a point within this object's visible bounds.")
public boolean clickObjPoint(Selector selector, int x, int y, @RpcOptional Long durationInMillis)
throws SelectorException {
return durationInMillis == null
? operate(selector, uiObject2 -> uiObject2.click(new Point(x, y)))
: operate(selector, uiObject2 -> uiObject2.click(new Point(x, y), durationInMillis));
}

@Rpc(description = "Drags this object in pixels per second to the specified location.")
public boolean dragObj(Selector selector, int x, int y, @RpcOptional Integer speed)
throws SelectorException {
Expand Down
Binary file modified snippet_uiautomator/android/app/uiautomator.apk
Binary file not shown.
38 changes: 32 additions & 6 deletions snippet_uiautomator/uiobject2.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from __future__ import annotations

from typing import Mapping, Optional, Sequence, Union
import warnings

from mobly.controllers.android_device_lib import snippet_client_v2
from snippet_uiautomator import byselector
Expand All @@ -39,19 +40,44 @@ def __init__(
self._ui = ui
self._selector = selector

def __call__(self, timeout: Optional[utils.TimeUnit] = None) -> bool:
def __call__(
self,
duration: Optional[utils.TimeUnit] = None,
timeout: Optional[utils.TimeUnit] = None,
x: Optional[int] = None,
y: Optional[int] = None,
) -> bool:
"""Clicks on this object.
Args:
timeout: The time in milliseconds to click and hold.
duration: The time in milliseconds to click and hold.
timeout: (Deprecated) The time in milliseconds to click and hold.
x: The X coordinate of the point to click (within the visible bounds).
y: The Y coordinate of the point to click (within the visible bounds).
Returns:
True if operation succeeds, False otherwise.
Raises:
errors.ApiError: When given incorrect arguments to this method.
"""
if timeout is None:
return self._ui.clickObj(self._selector.to_dict())
timeout_ms = utils.covert_to_millisecond(timeout)
return self._ui.clickObj(self._selector.to_dict(), timeout_ms)
if timeout is not None:
warnings.warn(
"The 'timeout' argument is deprecated, use 'duration' instead.",
DeprecationWarning,
stacklevel=2,
)
duration = timeout # Maintain backward compatibility

duration_ms = (
None if duration is None else utils.covert_to_millisecond(duration)
)
if x is not None and y is not None:
return self._ui.clickObjPoint(self._selector.to_dict(), x, y, duration_ms)
elif x is None and y is None:
return self._ui.clickObj(self._selector.to_dict(), duration_ms)
else:
raise errors.ApiError('Must provide both x and y to click on point')

def bottomright(self) -> bool:
"""Clicks the lower right corner of this object."""
Expand Down

0 comments on commit f56307c

Please sign in to comment.