or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdandroid-platform.mdapplication-management.mdconfiguration-options.mddevice-interaction.mdelement-location.mdindex.mdservice-management.mdwebdriver-core.md

advanced-features.mddocs/

0

# Advanced Features

1

2

Advanced capabilities including context switching, screen recording, image comparison, clipboard operations, settings management, and Flutter integration. These features enable sophisticated testing scenarios and cross-platform automation.

3

4

## Capabilities

5

6

### Context Management

7

8

Switch between native app and web contexts for hybrid app testing and WebView automation.

9

10

```python {.api}

11

@property

12

def contexts(self) -> list:

13

"""

14

Get list of available contexts (app and web views).

15

16

Returns:

17

list: List of context names (e.g., ['NATIVE_APP', 'WEBVIEW_1'])

18

"""

19

20

@property

21

def current_context(self) -> str:

22

"""

23

Get current active context name.

24

25

Returns:

26

str: Current context name

27

"""

28

29

@property

30

def context(self) -> str:

31

"""

32

Alias for current_context property.

33

34

Returns:

35

str: Current context name

36

"""

37

38

@context.setter

39

def context(self, context_name: str):

40

"""

41

Switch to specified context.

42

43

Args:

44

context_name (str): Context name to switch to

45

"""

46

```

47

48

### Screen Recording

49

50

Record device screen during test execution for debugging and documentation purposes.

51

52

```python {.api}

53

def start_recording_screen(self, **options):

54

"""

55

Start screen recording with specified options.

56

57

Args:

58

**options: Recording options

59

time_limit (int): Maximum recording time in seconds (default: 180)

60

video_type (str): Video format ('mp4', 'mov') - iOS only

61

video_quality (str): Video quality ('low', 'medium', 'high')

62

video_fps (int): Frames per second

63

video_scale (str): Video scale factor

64

video_size (str): Video dimensions (e.g., '1280x720')

65

bit_rate (int): Video bit rate - Android only

66

bug_report (bool): Include bug report - Android only

67

"""

68

69

def stop_recording_screen(self) -> str:

70

"""

71

Stop screen recording and get video data.

72

73

Returns:

74

str: Base64 encoded video data

75

"""

76

```

77

78

### Image Comparison

79

80

Compare images and find sub-images within larger images for visual testing and element location.

81

82

```python {.api}

83

def compare_images(self, base64_image1: str, base64_image2: str, **options) -> dict:

84

"""

85

Compare two images and get similarity metrics.

86

87

Args:

88

base64_image1 (str): First image as base64 string

89

base64_image2 (str): Second image as base64 string

90

**options: Comparison options

91

mode (str): Comparison mode ('matchFeatures', 'getSimilarity', 'matchTemplate')

92

threshold (float): Similarity threshold (0.0-1.0)

93

visualize (bool): Return visualization of differences

94

95

Returns:

96

dict: Comparison results with similarity score and visualization data

97

"""

98

99

def find_image_occurrence(self, full_image: str, partial_image: str, **options) -> dict:

100

"""

101

Find occurrence of partial image within full image.

102

103

Args:

104

full_image (str): Full image as base64 string

105

partial_image (str): Partial image to find as base64 string

106

**options: Search options

107

threshold (float): Match threshold (0.0-1.0)

108

multiple (bool): Find multiple occurrences

109

visualize (bool): Return visualization of matches

110

111

Returns:

112

dict: Match results with coordinates and confidence scores

113

"""

114

```

115

116

### Settings Management

117

118

Configure Appium server settings and behavior during test execution.

119

120

```python {.api}

121

def get_settings(self) -> dict:

122

"""

123

Get current Appium settings.

124

125

Returns:

126

dict: Dictionary of current setting name-value pairs

127

"""

128

129

def update_settings(self, settings: dict):

130

"""

131

Update Appium settings.

132

133

Args:

134

settings (dict): Dictionary of setting name-value pairs to update

135

Examples:

136

{'waitForIdleTimeout': 1000}

137

{'shouldUseCompactResponses': False}

138

{'elementResponseAttributes': 'type,label'}

139

"""

140

```

141

142

### Execute Mobile Commands

143

144

Execute platform-specific mobile commands not available through standard WebDriver API.

145

146

```python {.api}

147

def execute_mobile_command(self, command: str, **params):

148

"""

149

Execute mobile-specific command.

150

151

Args:

152

command (str): Mobile command name (e.g., 'shell', 'deepLink', 'startPerfRecord')

153

**params: Command-specific parameters

154

155

Returns:

156

Any: Command execution result (varies by command)

157

"""

158

```

159

160

### Flutter Integration

161

162

Specialized finders and commands for Flutter app testing.

163

164

```python {.api}

165

class FlutterFinder:

166

@staticmethod

167

def by_key(value: str):

168

"""

169

Find Flutter element by key.

170

171

Args:

172

value (str): Flutter key value

173

174

Returns:

175

FlutterFinder: Finder instance for element location

176

"""

177

178

@staticmethod

179

def by_text(value: str):

180

"""

181

Find Flutter element by text content.

182

183

Args:

184

value (str): Text content to find

185

186

Returns:

187

FlutterFinder: Finder instance for element location

188

"""

189

190

@staticmethod

191

def by_semantics_label(value: str):

192

"""

193

Find Flutter element by semantics label.

194

195

Args:

196

value (str): Semantics label value

197

198

Returns:

199

FlutterFinder: Finder instance for element location

200

"""

201

202

@staticmethod

203

def by_type(value: str):

204

"""

205

Find Flutter element by widget type.

206

207

Args:

208

value (str): Flutter widget type name

209

210

Returns:

211

FlutterFinder: Finder instance for element location

212

"""

213

214

@staticmethod

215

def by_text_containing(value: str):

216

"""

217

Find Flutter element by partial text match.

218

219

Args:

220

value (str): Partial text to match

221

222

Returns:

223

FlutterFinder: Finder instance for element location

224

"""

225

```

226

227

## Usage Examples

228

229

### Context Switching for Hybrid Apps

230

231

```python

232

from appium import webdriver

233

from appium.options.android import UiAutomator2Options

234

from selenium.webdriver.common.by import By

235

236

# Setup for hybrid app testing

237

options = UiAutomator2Options()

238

options.platform_name = "Android"

239

options.device_name = "Android Emulator"

240

options.app = "/path/to/hybrid/app.apk"

241

driver = webdriver.Remote("http://localhost:4723", options=options)

242

243

# Check available contexts

244

print("Available contexts:", driver.contexts)

245

print("Current context:", driver.current_context)

246

247

# Switch to WebView context

248

webview_contexts = [ctx for ctx in driver.contexts if 'WEBVIEW' in ctx]

249

if webview_contexts:

250

driver.context = webview_contexts[0]

251

print(f"Switched to context: {driver.current_context}")

252

253

# Now use standard web element finding

254

web_element = driver.find_element(By.ID, "web-button")

255

web_element.click()

256

257

# Switch back to native context

258

driver.context = "NATIVE_APP"

259

print(f"Switched back to: {driver.current_context}")

260

261

# Use mobile locators again

262

from appium.webdriver.common.appiumby import AppiumBy

263

native_element = driver.find_element(AppiumBy.ACCESSIBILITY_ID, "native-button")

264

native_element.click()

265

```

266

267

### Screen Recording for Test Documentation

268

269

```python

270

import base64

271

import time

272

273

def record_test_scenario(driver, test_name):

274

"""Record a test scenario with automatic file saving."""

275

276

try:

277

# Start recording with options

278

driver.start_recording_screen(

279

time_limit=300, # 5 minutes max

280

video_quality="medium",

281

video_fps=10

282

)

283

284

print(f"Started recording for {test_name}")

285

286

# Perform test actions

287

yield # This allows the calling code to run test steps

288

289

finally:

290

# Stop recording and save

291

try:

292

video_data = driver.stop_recording_screen()

293

294

# Decode and save video

295

video_bytes = base64.b64decode(video_data)

296

filename = f"{test_name}_{int(time.time())}.mp4"

297

298

with open(filename, 'wb') as f:

299

f.write(video_bytes)

300

301

print(f"Recording saved as {filename}")

302

303

except Exception as e:

304

print(f"Failed to save recording: {e}")

305

306

# Usage with context manager pattern

307

with record_test_scenario(driver, "login_test"):

308

# Perform login test steps

309

username_field = driver.find_element("id", "username")

310

username_field.send_keys("testuser")

311

312

password_field = driver.find_element("id", "password")

313

password_field.send_keys("password123")

314

315

login_button = driver.find_element("id", "login")

316

login_button.click()

317

318

time.sleep(2) # Wait for login to complete

319

```

320

321

### Image-Based Testing and Validation

322

323

```python

324

import base64

325

import cv2

326

import numpy as np

327

328

def capture_element_screenshot(driver, element):

329

"""Capture screenshot of specific element."""

330

# Take full screenshot

331

screenshot = driver.get_screenshot_as_png()

332

333

# Get element location and size

334

location = element.location

335

size = element.size

336

337

# Convert to numpy array

338

nparr = np.frombuffer(screenshot, np.uint8)

339

img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

340

341

# Crop to element bounds

342

x, y = location['x'], location['y']

343

w, h = size['width'], size['height']

344

element_img = img[y:y+h, x:x+w]

345

346

# Convert back to base64

347

_, buffer = cv2.imencode('.png', element_img)

348

return base64.b64encode(buffer).decode('utf-8')

349

350

def visual_regression_test(driver, expected_image_path, element):

351

"""Perform visual regression testing on element."""

352

353

# Capture current element appearance

354

current_image = capture_element_screenshot(driver, element)

355

356

# Load expected image

357

with open(expected_image_path, 'rb') as f:

358

expected_image = base64.b64encode(f.read()).decode('utf-8')

359

360

# Compare images

361

comparison_result = driver.compare_images(

362

expected_image,

363

current_image,

364

mode='getSimilarity',

365

threshold=0.95

366

)

367

368

similarity = comparison_result.get('score', 0)

369

print(f"Visual similarity: {similarity:.2%}")

370

371

if similarity < 0.95:

372

print("Visual regression detected!")

373

# Save diff image if available

374

if 'visualization' in comparison_result:

375

save_diff_image(comparison_result['visualization'])

376

return False

377

378

return True

379

380

def find_ui_element_by_image(driver, template_image_path):

381

"""Find UI element using image template matching."""

382

383

# Take screenshot

384

screenshot = driver.get_screenshot_as_base64()

385

386

# Load template image

387

with open(template_image_path, 'rb') as f:

388

template_image = base64.b64encode(f.read()).decode('utf-8')

389

390

# Find image occurrence

391

result = driver.find_image_occurrence(

392

screenshot,

393

template_image,

394

threshold=0.8,

395

visualize=True

396

)

397

398

if result.get('matches'):

399

match = result['matches'][0] # Get first match

400

center_x = match['x'] + match['width'] // 2

401

center_y = match['y'] + match['height'] // 2

402

403

# Tap at found location

404

driver.tap([(center_x, center_y)])

405

return True

406

407

return False

408

```

409

410

### Settings and Performance Optimization

411

412

```python

413

def optimize_test_performance(driver):

414

"""Optimize Appium settings for faster test execution."""

415

416

# Get current settings

417

current_settings = driver.get_settings()

418

print("Current settings:", current_settings)

419

420

# Update settings for performance

421

performance_settings = {

422

'waitForIdleTimeout': 1000, # Reduce idle wait time

423

'waitForSelectorTimeout': 5000, # Reduce selector timeout

424

'shouldUseCompactResponses': True, # Use compact JSON responses

425

'elementResponseAttributes': 'type,name,label,enabled,visible', # Limit response data

426

'mjpegServerScreenshotQuality': 50, # Lower screenshot quality for speed

427

'mjpegScalingFactor': 50 # Scale down screenshots

428

}

429

430

driver.update_settings(performance_settings)

431

print("Applied performance optimizations")

432

433

# Verify settings were applied

434

updated_settings = driver.get_settings()

435

print("Updated settings:", updated_settings)

436

437

def configure_debug_settings(driver):

438

"""Configure settings for debugging and troubleshooting."""

439

440

debug_settings = {

441

'waitForIdleTimeout': 10000, # Longer idle timeout for debugging

442

'waitForSelectorTimeout': 30000, # Longer selector timeout

443

'shouldUseCompactResponses': False, # Full responses for debugging

444

'elementResponseAttributes': '*', # All element attributes

445

'screenshotQuality': 100, # High quality screenshots

446

'mjpegScalingFactor': 100 # Full resolution screenshots

447

}

448

449

driver.update_settings(debug_settings)

450

print("Applied debug settings")

451

```

452

453

### Mobile Command Execution

454

455

```python

456

def execute_platform_commands(driver):

457

"""Execute various platform-specific mobile commands."""

458

459

# Android shell commands

460

if driver.capabilities.get('platformName').lower() == 'android':

461

# Execute shell command

462

result = driver.execute_mobile_command('shell', command='getprop ro.build.version.release')

463

print(f"Android version: {result}")

464

465

# Deep link

466

driver.execute_mobile_command('deepLink',

467

url='myapp://profile/123',

468

package='com.example.myapp')

469

470

# Start performance recording

471

driver.execute_mobile_command('startPerfRecord',

472

timeout=30000,

473

profileName='cpu')

474

475

# Perform actions to measure

476

perform_cpu_intensive_actions()

477

478

# Stop performance recording

479

perf_data = driver.execute_mobile_command('stopPerfRecord')

480

save_performance_data(perf_data)

481

482

# iOS specific commands

483

elif driver.capabilities.get('platformName').lower() == 'ios':

484

# Siri command

485

driver.execute_mobile_command('siri', text='What time is it?')

486

487

# Face ID simulation

488

driver.execute_mobile_command('enrollBiometric', isEnabled=True)

489

driver.execute_mobile_command('sendBiometricMatch', type='faceId', match=True)

490

491

# Pasteboard access

492

driver.execute_mobile_command('setPasteboard', content='Test clipboard content')

493

clipboard_content = driver.execute_mobile_command('getPasteboard')

494

print(f"Clipboard: {clipboard_content}")

495

496

def perform_cpu_intensive_actions():

497

"""Placeholder for CPU intensive test actions."""

498

pass

499

500

def save_performance_data(data):

501

"""Save performance data for analysis."""

502

pass

503

```

504

505

### Flutter Integration Testing

506

507

```python

508

from appium.webdriver.extensions.flutter_integration.flutter_finder import FlutterFinder

509

510

def flutter_testing_example(driver):

511

"""Example of Flutter-specific testing."""

512

513

# Find elements using Flutter finders

514

submit_button = driver.find_element(

515

AppiumBy.FLUTTER_INTEGRATION_KEY,

516

FlutterFinder.by_key('submit_button')

517

)

518

submit_button.click()

519

520

# Find by text content

521

welcome_text = driver.find_element(

522

AppiumBy.FLUTTER_INTEGRATION_TEXT,

523

FlutterFinder.by_text('Welcome to the app')

524

)

525

assert welcome_text.is_displayed()

526

527

# Find by widget type

528

text_fields = driver.find_elements(

529

AppiumBy.FLUTTER_INTEGRATION_TYPE,

530

FlutterFinder.by_type('TextField')

531

)

532

533

# Fill in all text fields

534

test_data = ['username', 'password', 'email@example.com']

535

for i, field in enumerate(text_fields):

536

if i < len(test_data):

537

field.send_keys(test_data[i])

538

539

# Find by semantics label

540

navigation_button = driver.find_element(

541

AppiumBy.FLUTTER_INTEGRATION_SEMANTICS_LABEL,

542

FlutterFinder.by_semantics_label('Navigate to next page')

543

)

544

navigation_button.click()

545

546

# Find by partial text

547

help_elements = driver.find_elements(

548

AppiumBy.FLUTTER_INTEGRATION_TEXT_CONTAINING,

549

FlutterFinder.by_text_containing('Help')

550

)

551

552

for help_element in help_elements:

553

print(f"Help element found: {help_element.text}")

554

```

555

556

## Types

557

558

```python {.api}

559

# Context types

560

ContextList = List[str] # List of context names

561

ContextName = str # Context identifier (e.g., 'NATIVE_APP', 'WEBVIEW_1')

562

563

# Recording types

564

RecordingOptions = Dict[str, Union[int, str, bool]]

565

VideoData = str # Base64 encoded video data

566

RecordingTimeLimit = int # Maximum recording time in seconds

567

568

# Image types

569

Base64Image = str # Base64 encoded image data

570

ImagePath = str # File path to image

571

SimilarityScore = float # 0.0 to 1.0 similarity score

572

MatchThreshold = float # 0.0 to 1.0 match threshold

573

574

# Comparison results

575

ComparisonResult = Dict[str, Union[float, str, bool]]

576

OccurrenceResult = Dict[str, Union[List[dict], str, bool]]

577

578

# Settings types

579

SettingsDict = Dict[str, Union[str, int, bool]]

580

SettingName = str

581

SettingValue = Union[str, int, bool]

582

583

# Mobile command types

584

MobileCommand = str # Command name

585

CommandParams = Dict[str, Union[str, int, bool, List]]

586

CommandResult = Union[str, dict, bool, None]

587

588

# Flutter types

589

FlutterKey = str # Flutter widget key

590

FlutterText = str # Flutter widget text

591

FlutterType = str # Flutter widget type

592

SemanticsLabel = str # Flutter semantics label

593

```