or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

app-management.mddevice-management.mdimage-processing.mdindex.mdscreen-input.mdui-interaction.mdwatchers-automation.mdxpath-selection.md

xpath-selection.mddocs/

0

# XPath-based Element Selection

1

2

Advanced XPath-based element selection providing powerful querying capabilities for complex UI hierarchies and dynamic content. XPath selection offers more flexible element targeting than traditional UiAutomator selectors.

3

4

## Capabilities

5

6

### XPath Entry Point

7

8

Access XPath functionality through the device xpath property.

9

10

```python { .api }

11

class Device:

12

@cached_property

13

def xpath(self) -> xpath.XPathEntry:

14

"""XPath-based element selection entry point"""

15

16

class XPathEntry:

17

def __call__(self, xpath_expression: str) -> XPathSelector:

18

"""

19

Create XPath selector.

20

21

Parameters:

22

- xpath_expression: XPath query string

23

24

Returns:

25

XPathSelector for element interaction

26

"""

27

28

def dump_hierarchy(self) -> str:

29

"""Get UI hierarchy XML for XPath debugging"""

30

```

31

32

Usage examples:

33

34

```python

35

d = u2.connect()

36

37

# Basic XPath selection

38

element = d.xpath('//*[@text="Settings"]')

39

button = d.xpath('//android.widget.Button[@text="OK"]')

40

41

# Complex XPath queries

42

first_item = d.xpath('//android.widget.ListView/android.widget.LinearLayout[1]')

43

checked_box = d.xpath('//android.widget.CheckBox[@checked="true"]')

44

45

# Debug hierarchy

46

hierarchy = d.xpath.dump_hierarchy()

47

print(hierarchy) # XML representation of UI

48

```

49

50

### XPath Element Selection

51

52

Select elements using XPath expressions with support for attributes, hierarchy, and logical operators.

53

54

```python { .api }

55

class XPathSelector:

56

def click(self, timeout: Optional[float] = None):

57

"""Click the element found by XPath"""

58

59

def long_click(self, duration: float = 0.5):

60

"""Long click the element"""

61

62

def exists(self, timeout: Optional[float] = None) -> bool:

63

"""Check if element exists"""

64

65

def wait(self, timeout: Optional[float] = None) -> bool:

66

"""Wait for element to appear"""

67

68

def wait_gone(self, timeout: Optional[float] = None) -> bool:

69

"""Wait for element to disappear"""

70

71

def get_text(self) -> str:

72

"""Get element text content"""

73

74

def get(self, attribute: str) -> str:

75

"""Get element attribute value"""

76

77

def set_text(self, text: str):

78

"""Set element text content"""

79

80

def screenshot(self) -> Image.Image:

81

"""Take screenshot of element"""

82

```

83

84

### Common XPath Patterns

85

86

Frequently used XPath expressions for Android UI automation.

87

88

```python

89

d = u2.connect()

90

91

# Text-based selection

92

d.xpath('//*[@text="Login"]').click()

93

d.xpath('//*[contains(@text, "Welcome")]').click()

94

d.xpath('//*[starts-with(@text, "User")]').click()

95

96

# Resource ID selection

97

d.xpath('//*[@resource-id="com.example:id/button"]').click()

98

d.xpath('//*[contains(@resource-id, "submit")]').click()

99

100

# Class-based selection

101

d.xpath('//android.widget.Button').click()

102

d.xpath('//android.widget.EditText[@enabled="true"]').set_text("input")

103

104

# Hierarchy-based selection

105

d.xpath('//android.widget.ListView/android.widget.LinearLayout[1]').click()

106

d.xpath('//android.widget.ScrollView//android.widget.Button').click()

107

108

# Attribute combinations

109

d.xpath('//*[@clickable="true" and @enabled="true"]').click()

110

d.xpath('//*[@text="Submit" or @text="Send"]').click()

111

112

# Index-based selection

113

d.xpath('(//android.widget.Button)[1]').click() # First button

114

d.xpath('(//android.widget.Button)[last()]').click() # Last button

115

116

# Parent/child relationships

117

d.xpath('//android.widget.TextView[@text="Label"]/../android.widget.EditText').set_text("value")

118

d.xpath('//android.widget.LinearLayout[android.widget.TextView[@text="Title"]]').click()

119

```

120

121

### XPath Element Information

122

123

Access element properties and attributes through XPath selections.

124

125

```python

126

d = u2.connect()

127

128

# Get element text

129

title = d.xpath('//*[@resource-id="title"]').get_text()

130

print(f"Title: {title}")

131

132

# Get element attributes

133

element = d.xpath('//android.widget.Button[@text="Submit"]')

134

bounds = element.get('bounds')

135

class_name = element.get('class')

136

enabled = element.get('enabled')

137

138

print(f"Bounds: {bounds}")

139

print(f"Class: {class_name}")

140

print(f"Enabled: {enabled}")

141

142

# Check element state

143

if d.xpath('//*[@checked="true"]').exists():

144

print("Checkbox is checked")

145

146

# Wait for elements

147

success = d.xpath('//*[@text="Success"]').wait(timeout=10)

148

if success:

149

print("Success message appeared")

150

```

151

152

### XPath Text Input and Interaction

153

154

Text input and advanced interaction through XPath-selected elements.

155

156

```python

157

d = u2.connect()

158

159

# Text input

160

username_field = d.xpath('//*[@resource-id="username"]')

161

username_field.set_text("john_doe")

162

163

password_field = d.xpath('//*[@resource-id="password"]')

164

password_field.set_text("secret123")

165

166

# Clear and set text

167

search_box = d.xpath('//*[@class="android.widget.EditText"]')

168

search_box.set_text("") # Clear

169

search_box.set_text("new search term")

170

171

# Click variations

172

d.xpath('//*[@text="Login"]').click()

173

d.xpath('//*[@text="Options"]').long_click(duration=2.0)

174

175

# Element screenshots

176

element_img = d.xpath('//*[@resource-id="logo"]').screenshot()

177

element_img.save("logo.png")

178

```

179

180

### XPath Debugging and Troubleshooting

181

182

Tools and techniques for debugging XPath expressions and UI hierarchy issues.

183

184

```python

185

d = u2.connect()

186

187

# Dump UI hierarchy for analysis

188

hierarchy_xml = d.xpath.dump_hierarchy()

189

with open("hierarchy.xml", "w", encoding="utf-8") as f:

190

f.write(hierarchy_xml)

191

192

# Check if XPath matches any elements

193

xpath_expr = '//*[@text="Submit"]'

194

if d.xpath(xpath_expr).exists():

195

print(f"XPath '{xpath_expr}' matches elements")

196

else:

197

print(f"XPath '{xpath_expr}' matches no elements")

198

199

# Get all matching elements count

200

buttons = d.xpath('//android.widget.Button')

201

print(f"Found {len(buttons)} buttons")

202

203

# Test element visibility and properties

204

element = d.xpath('//*[@resource-id="target"]')

205

if element.exists():

206

print(f"Element text: {element.get_text()}")

207

print(f"Element bounds: {element.get('bounds')}")

208

print(f"Element enabled: {element.get('enabled')}")

209

```

210

211

### Advanced XPath Features

212

213

Advanced XPath functionality for complex UI automation scenarios.

214

215

```python

216

d = u2.connect()

217

218

# Position-based selection

219

d.xpath('//android.widget.Button[position()=1]').click() # First button

220

d.xpath('//android.widget.Button[position()=last()]').click() # Last button

221

d.xpath('//android.widget.Button[position()>2]').click() # Buttons after second

222

223

# Text content functions

224

d.xpath('//*[text()="Exact Match"]').click()

225

d.xpath('//*[contains(text(), "Partial")]').click()

226

d.xpath('//*[starts-with(text(), "Prefix")]').click()

227

d.xpath('//*[string-length(text())>10]').click() # Text longer than 10 chars

228

229

# Multiple attribute conditions

230

d.xpath('//*[@enabled="true" and @clickable="true" and contains(@text, "Submit")]').click()

231

232

# Sibling navigation

233

d.xpath('//android.widget.TextView[@text="Label"]/following-sibling::android.widget.EditText').set_text("value")

234

d.xpath('//android.widget.Button[@text="Cancel"]/preceding-sibling::android.widget.Button').click()

235

236

# Ancestor/descendant navigation

237

d.xpath('//android.widget.ScrollView//android.widget.Button[@text="Deep Button"]').click()

238

d.xpath('//android.widget.LinearLayout[.//android.widget.TextView[@text="Container"]]').click()

239

```

240

241

### Complete XPath API

242

243

All XPath methods and capabilities for comprehensive element selection.

244

245

```python { .api }

246

class XPathEntry:

247

def __call__(self, xpath: str, timeout: float = 10) -> XPathSelector:

248

"""

249

Select elements using XPath expression.

250

251

Parameters:

252

- xpath: XPath expression string

253

- timeout: Maximum wait time for element

254

255

Returns:

256

XPathSelector for element interaction

257

"""

258

259

def exists(self, xpath: str) -> bool:

260

"""Check if XPath element exists"""

261

262

def get(self, xpath: str, timeout: float = 10) -> XMLElement:

263

"""Get single element by XPath"""

264

265

def all(self, xpath: str) -> List[XMLElement]:

266

"""Get all matching elements by XPath"""

267

268

def wait(self, xpath: str, timeout: float = 10) -> XMLElement:

269

"""Wait for XPath element to appear"""

270

271

class XPathSelector:

272

@property

273

def exists(self) -> bool:

274

"""Check if element exists"""

275

276

def get(self, timeout: float = 10) -> XMLElement:

277

"""Get single element with timeout"""

278

279

def get_last_match(self) -> XMLElement:

280

"""Get last matched element from cache"""

281

282

def get_text(self) -> str:

283

"""Get element text content"""

284

285

def set_text(self, text: str):

286

"""Set element text content"""

287

288

def click(self):

289

"""Click the element"""

290

291

def all(self) -> List[XMLElement]:

292

"""Get all matching elements"""

293

294

def wait(self, timeout: float = 10) -> XMLElement:

295

"""Wait for element to appear"""

296

297

class XMLElement:

298

@property

299

def tag(self) -> str:

300

"""Element tag name"""

301

302

@property

303

def text(self) -> str:

304

"""Element text content"""

305

306

@property

307

def attrib(self) -> Dict[str, str]:

308

"""Element attributes dictionary"""

309

310

@property

311

def bounds(self) -> Tuple[int, int, int, int]:

312

"""Element bounds (left, top, right, bottom)"""

313

314

@property

315

def center(self) -> Tuple[int, int]:

316

"""Element center coordinates (x, y)"""

317

318

def get(self, key: str, default: Any = None) -> Any:

319

"""Get attribute value by key"""

320

321

def click(self):

322

"""Click the element"""

323

324

def screenshot(self) -> Image.Image:

325

"""Take screenshot of element"""

326

```

327

328

Usage examples for complete XPath API:

329

330

```python

331

d = u2.connect()

332

333

# Direct XPath operations

334

xpath_entry = d.xpath

335

elements = xpath_entry.all('//android.widget.Button')

336

if xpath_entry.exists('//*[@text="Login"]'):

337

login_element = xpath_entry.get('//*[@text="Login"]')

338

login_element.click()

339

340

# XPath selector operations

341

selector = d.xpath('//android.widget.EditText[@resource-id="username"]')

342

if selector.exists:

343

element = selector.get(timeout=5)

344

element.click()

345

selector.set_text("user123")

346

347

# XMLElement operations

348

button = d.xpath('//*[@text="Submit"]').get()

349

print(f"Button tag: {button.tag}")

350

print(f"Button text: {button.text}")

351

print(f"Button bounds: {button.bounds}")

352

print(f"Button center: {button.center}")

353

print(f"Button enabled: {button.get('enabled', 'unknown')}")

354

355

# Take element screenshot

356

element_image = button.screenshot()

357

element_image.save("button_screenshot.png")

358

359

# Wait operations with timeout

360

try:

361

loading_element = d.xpath('//*[@text="Loading..."]').wait(timeout=30)

362

print("Loading element appeared")

363

except Exception:

364

print("Loading element did not appear within 30 seconds")

365

```