# Element

`Element` is a lazy selector bound to a device: nothing is looked up until an action or query
runs, and each one needs exactly one match. `element.wait()` returns an `ElementWait`. Guide:
[Elements and text](../../guide/elements.md), [Gestures](../../guide/gestures.md),
[Waits](../../guide/waits.md).

## <kbd>class</kbd> `Element`
A selector bound to a device. 

Nothing is resolved until a method is called; every call sends the selector to the device again, so an Element can be kept for the whole test. Actions require exactly one match and raise ``CommandError`` (``AMBIGUOUS``/``NOT_FOUND``) before any input otherwise. 

### <kbd>method</kbd> `Element.__init__`

```python
__init__(device: 'Device', selector: 'Selector')
```

---

### <kbd>method</kbd> `Element.at`

```python
at(index: 'int') → Element
```

Accept the ``index``-th match (0-based) in accessibility order. 

---

### <kbd>method</kbd> `Element.child`

```python
child(other: 'Selector') → Element
```

The direct child of this node matching ``other``. 

---

### <kbd>method</kbd> `Element.clear_text`

```python
clear_text(timeout: 'float | None' = None) → None
```

``set_text("")``: ``ACTION_SET_TEXT`` on the one matching node, not read back. 

---

### <kbd>method</kbd> `Element.count`

```python
count(timeout: 'float | None' = None) → int
```

Matches in the selector's scope right now, ignoring its match limit. 

---

### <kbd>method</kbd> `Element.descendant`

```python
descendant(other: 'Selector') → Element
```

The node matching ``other`` somewhere below this one. 

---

### <kbd>method</kbd> `Element.double_tap`

```python
double_tap(timeout: 'float | None' = None) → None
```

Two taps at the centre of the one matching node's visible bounds, inside Android's double-tap window. 

---

### <kbd>method</kbd> `Element.drag_to`

```python
drag_to(destination: 'Selector', timeout: 'float | None' = None) → None
```

Press the one matching node until it is a long press, move the finger to the centre of the one node matching ``destination`` (resolved on the same screen, before any input), hold there briefly and lift. Nothing is reported about what the app did with the drop. 

---

### <kbd>method</kbd> `Element.exists`

```python
exists(timeout: 'float | None' = None) → bool
```

True when at least one node matches right now (any number of matches is fine). 

---

### <kbd>method</kbd> `Element.first`

```python
first() → Element
```

Accept the first match in accessibility order instead of requiring exactly one. 

---

### <kbd>method</kbd> `Element.fling`

```python
fling(direction: 'Direction', timeout: 'float | None' = None) → None
```

One fast swipe across the one matching node towards ``direction``'s content edge (as for ``scroll``: ``DOWN`` flings towards content below). Returns once the finger lifts; the content may keep moving, so wait for what you need next. 

---

### <kbd>method</kbd> `Element.ime_action`

```python
ime_action(timeout: 'float | None' = None) → None
```

Run the one matching text field's keyboard action (Search, Go, Send, Done, … as the app configured it) exactly as the keyboard's action key does, through accessibility ``ACTION_IME_ENTER``. API 30+: older devices raise ``CommandError`` (``UNSUPPORTED`` / ``REQUIRES_API_30``) before any input, since pressing Enter is not equivalent. The field must have input focus (tap it first): Android offers the action only then, and a node that does not offer it raises ``ACTION_REJECTED`` before any input. 

---

### <kbd>method</kbd> `Element.is_checked`

```python
is_checked(timeout: 'float | None' = None) → bool
```

``snapshot().checked`` of the one matching node. 

---

### <kbd>method</kbd> `Element.is_enabled`

```python
is_enabled(timeout: 'float | None' = None) → bool
```

``snapshot().enabled`` of the one matching node. 

---

### <kbd>method</kbd> `Element.long_tap`

```python
long_tap(timeout: 'float | None' = None) → None
```

Long click on the one matching node. 

---

### <kbd>method</kbd> `Element.perform_action`

```python
perform_action(action: 'StandardAction', timeout: 'float | None' = None) → None
```

Perform a standard accessibility ``action`` on the one matching node, as a screen reader does: no touch, so a covered node is no obstacle. The node must offer it (``snapshot().actions``); otherwise ``CommandError`` (``ACTION_REJECTED`` / ``ACTION_NOT_OFFERED``) before any input. A node that refuses an offered action is ``ACTION_REJECTED``. Only Android's answer is reported: assert what the app did. 

---

### <kbd>method</kbd> `Element.perform_custom_action`

```python
perform_custom_action(label: 'str', timeout: 'float | None' = None) → None
```

Perform the custom accessibility action labelled ``label`` (exactly) on the one matching node: the "Archive" or "Delete" a list item offers screen reader users instead of a swipe (``snapshot().custom_actions``). Not offered, or offered twice under that label: ``ACTION_REJECTED`` / ``ACTION_NOT_OFFERED`` before any input. 

---

### <kbd>method</kbd> `Element.pinch_close`

```python
pinch_close(percent: 'int' = 80, timeout: 'float | None' = None) → None
```

Two fingers moving together towards the one matching node's centre, across ``percent`` of its size. 

---

### <kbd>method</kbd> `Element.pinch_open`

```python
pinch_open(percent: 'int' = 80, timeout: 'float | None' = None) → None
```

Two fingers moving apart from the one matching node's centre, across ``percent`` of its size. 

---

### <kbd>method</kbd> `Element.scroll`

```python
scroll(
    direction: 'Direction',
    distance_percent: 'int' = 80,
    timeout: 'float | None' = None
) → None
```

One scroll gesture on the one matching node towards ``direction``'s content edge (UiAutomator semantics: DOWN reveals content below). Nothing is reported about whether content moved; observe that with a query or wait. 

---

### <kbd>method</kbd> `Element.scroll_until`

```python
scroll_until(
    target: 'Selector',
    direction: 'Direction' = <Direction.DOWN: 'DOWN'>,
    max_scrolls: 'int' = 20,
    distance_percent: 'int' = 80,
    timeout: 'float | None' = None
) → Element
```

Client-side loop: checks whether ``target`` exists inside this container (``descendant``) and, while it does not, ``scroll``s once, up to ``max_scrolls`` scrolls within ``timeout`` seconds (default: the device's wait timeout). Returns the target as a lazy element scoped to this container, so a later action cannot hit a duplicate elsewhere on screen; a container with ``first()``/``at()`` cannot be carried into a relation, and then the bare ``target`` is used. 

Raises ``WaitTimeoutError`` when the target never appeared. The list may have scrolled by then. Every step is an ordinary command, so a failing step raises its own ``CommandError``. 

---

### <kbd>method</kbd> `Element.set_progress`

```python
set_progress(value: 'float', timeout: 'float | None' = None) → None
```

Set the one matching range node (SeekBar, Slider, RatingBar) to ``value`` in its own units (``snapshot().range``) through accessibility ``ACTION_SET_PROGRESS``: exact, where a drag would land on whatever pixel maps to. A node without the action, or a value outside its min..max, is ``ACTION_REJECTED`` (``ACTION_NOT_OFFERED`` / ``OUT_OF_RANGE``) before any input; the view is not left to clamp it. 

---

### <kbd>method</kbd> `Element.set_text`

```python
set_text(value: 'str', timeout: 'float | None' = None) → None
```

Accessibility text replacement (``ACTION_SET_TEXT``) on the one matching node. 

Fails with ``ACTION_REJECTED`` only when the node refuses the action. The field is not read back: assert the effect with a selector that survives the edit, e.g. ``app.wait(res("email")).text_equals("new")``. 

---

### <kbd>method</kbd> `Element.snapshot`

```python
snapshot(timeout: 'float | None' = None) → ElementSnapshot
```

State of the one matching node at this instant (AMBIGUOUS/NOT_FOUND otherwise). 

---

### <kbd>method</kbd> `Element.swipe`

```python
swipe(
    direction: 'Direction',
    distance_percent: 'int' = 80,
    timeout: 'float | None' = None
) → None
```

One swipe gesture across the node in the direction the finger moves (``UP``/``DOWN``/``LEFT``/``RIGHT``). 

---

### <kbd>method</kbd> `Element.tap`

```python
tap(timeout: 'float | None' = None) → None
```

Click at the centre of the one matching node's visible bounds. 

---

### <kbd>method</kbd> `Element.text`

```python
text(timeout: 'float | None' = None) → str | None
```

Raw accessibility text of the one matching node, or None when it has none. On API 26+ an empty field reports its hint here; ``snapshot().showing_hint`` says so. 

---

### <kbd>method</kbd> `Element.type_text`

```python
type_text(
    value: 'str',
    await_focus: 'bool' = True,
    timeout: 'float | None' = None
) → None
```

Tap the one matching node, wait until it reports focus, then type ``value``. 

Three steps (``tap``, ``wait().focused()`` when ``await_focus``, ``Device.type_text``), so a failure says which one failed. Pass ``await_focus=False`` when focus goes elsewhere (a child or a separate input view) and wait for what that app needs yourself. The field is not read back: assert the effect yourself. 

---

### <kbd>method</kbd> `Element.wait`

```python
wait(timeout: 'float | None' = None) → ElementWait
```

An ``ElementWait`` on this selector (default timeout ``timeouts.wait``). 

## <kbd>class</kbd> `ElementWait`
Returned by ``Device.wait`` / ``Element.wait``. ``visible`` and ``gone`` poll on the device in a single RPC; property waits poll snapshots from the host. 

### <kbd>method</kbd> `ElementWait.__init__`

```python
__init__(device: 'Device', selector: 'Selector', timeout: 'float')
```

---

### <kbd>method</kbd> `ElementWait.checked`

```python
checked() → Element
```

Wait until the one matching node is checked. 

---

### <kbd>method</kbd> `ElementWait.count`

```python
count(expected: 'int') → Element
```

Wait until exactly ``expected`` nodes match. 

---

### <kbd>method</kbd> `ElementWait.disabled`

```python
disabled() → Element
```

Wait until the one matching node is disabled. 

---

### <kbd>method</kbd> `ElementWait.enabled`

```python
enabled() → Element
```

Wait until the one matching node is enabled. 

---

### <kbd>method</kbd> `ElementWait.focused`

```python
focused() → Element
```

Wait until the one matching node has focus. 

---

### <kbd>method</kbd> `ElementWait.gone`

```python
gone() → None
```

Wait until no node matches; polled on the device in one RPC. A timeout's ``reason`` is ``STILL_PRESENT`` with ``match_count``. 

---

### <kbd>method</kbd> `ElementWait.one`

```python
one() → Element
```

Wait until exactly one node matches — what a mutation such as ``tap()`` needs; polled on the device in one RPC. A timeout's ``reason`` is ``NO_MATCH`` or ``AMBIGUOUS`` with ``match_count`` from the last poll. 

---

### <kbd>method</kbd> `ElementWait.text_contains`

```python
text_contains(part: 'str') → Element
```

Wait until the one matching node's text contains ``part``. 

---

### <kbd>method</kbd> `ElementWait.text_equals`

```python
text_equals(expected: 'str') → Element
```

Wait until the one matching node's text equals ``expected``. 

---

### <kbd>method</kbd> `ElementWait.unchecked`

```python
unchecked() → Element
```

Wait until the one matching node is unchecked. 

---

### <kbd>method</kbd> `ElementWait.visible`

```python
visible() → Element
```

Wait until at least one node matches; polled on the device in one RPC. A timeout's ``reason`` is ``NO_MATCH``. 

