Metadata-Version: 2.4
Name: apppilot
Version: 1.2.37
Summary: Modern, Intelligent Mobile Automation Framework (Compiled)
Description-Content-Type: text/markdown
Requires-Dist: pytest>=8.0.0
Requires-Dist: pytest-xdist>=3.5.0
Requires-Dist: rich>=13.0.0
Requires-Dist: loguru>=0.7.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: pyyaml>=6.0.0
Requires-Dist: jinja2>=3.1.0
Requires-Dist: cryptography>=41.0.0
Requires-Dist: requests>=2.31.0
Dynamic: description
Dynamic: description-content-type
Dynamic: requires-dist
Dynamic: summary

# 🚀 AppPilot Mobile — The Master Guide

Welcome to the world-class documentation for **AppPilot Mobile**. This framework is designed to be the "Playwright for Mobile" — a Python-first, human-readable automation engine that handles the complexity of mobile UI so you can focus on writing tests.

---

## 🏗️ 1. Professional Architecture (POM)

AppPilot is optimized for the **Page Object Model (POM)**. By following this structure, your tests will be readable, maintainable, and stable.

### **1.1 Screen Transition Example**
In this model, the `LoginScreen` fills in credentials, taps submit, and then instantiates and returns the next screen (`DashboardScreen`):

```python
class LoginScreen:

    def login(self, username, password) -> DashboardScreen:
        self.mobile.input("Username").fill(username)
        self.mobile.input("Password").fill(password)
        self.mobile.button("Login").tap()
        
        return DashboardScreen(self.mobile)
```

### **1.2 Handling Elements Without Text Dynamically**
You do **not** need separate methods (like `tap_xpath()` or `tap_by_id()`) for elements without text. The **exact same public methods** (`mobile.tap()`, `mobile.fill()`, etc.) handle all targets dynamically:

* **Accessibility ID / Content Description:**
  ```python
  mobile.tap("shopping_cart_icon")  # Taps by accessibility label even if there is no text.
  ```
* **Resource ID:**
  ```python
  mobile.tap("com.example.app:id/submit_btn")  # Identifies the developer-assigned element ID.
  ```
* **Placeholder / Hint Text:**
  ```python
  mobile.tap("Enter your password")  # Text
  ```
* **XPath Fallback:**
  ```python
  mobile.tap("//android.widget.FrameLayout[1]/android.widget.Button[2]")  # Triggers automatically if starting with "//".
  ```

---

## 🛠️ 2. Developer & Diagnostic Tools

### **2.1 Device Diagnostic (`mobile.diagnose()`)**
Provides a complete health check of the device and the automation environment.
- **System Info:** Model, Android version, and Serial.
- **App State:** Package and Activity currently in focus.
- **Performance:** Real-time Memory (MB) and CPU (%) usage.
- **Usage:**
```python
mobile.diagnose()
```

---

## 📊 3. Complete API Reference

| Category | Method | Example | Description |
| :--- | :--- | :--- | :--- |
| **Core** | `tap(target)` / `click()` | `mobile.click("Login")` | Smart tap/click with auto-scroll. |
| | `fill(target, text)` / `set_text()` | `mobile.set_text("User", "admin")` | Locates label and fills input. |
| | `clear(target)` / `clear_text()` | `mobile.clear_text("Search")` | Wipes text from a field. |
| | `double_tap(t)` / `double_click()` | `mobile.double_click("Map")` | Rapid two-tap gesture. |
| | `long_press(target)` | `mobile.long_press("File")` | 1s touch-and-hold. |
| | `dropdown(target)` | `mobile.dropdown("Theme").select(option="Dark")` | Opens dropdown and selects by option text or index. |
| **Diagnostics**| `inspect()` | `mobile.inspect()` | Prints UI tree to console. |
| | `diagnose()` | `mobile.diagnose()` | Full device & app health check. |
| | `get_current_app()` | `app = mobile.get_current_app()`| Returns package/activity. |
| | `get_performance()` | `perf = mobile.get_performance()`| Returns CPU/Memory stats. |
| | `get_focused_element()` | `active = mobile.get_focused_element()` | Gets properties of currently focused element. |
| | `get_active_element()` | `active = mobile.get_active_element()` | Alias for get_focused_element(). |
| | `get_selected_element()` | `active = mobile.get_selected_element()` | Alias for get_focused_element(). |
| **Device Mgmt** | `connect_device(serial)` | `mobile.connect_device("192.168.1.5:5555")` | Connects via ADB TCP/IP. |
| | `disconnect_device()` | `mobile.disconnect_device()` | Disconnects device. |
| | `get_device_info()` | `info = mobile.get_device_info()` | OS, Model, Manufacturer. |
| | `install_app(path)` | `mobile.install_app("app.apk")` | Installs APK. |
| | `uninstall_app(pkg)` | `mobile.uninstall_app("com.app")` | Uninstalls package. |
| | `close_app(pkg)` | `mobile.close_app("com.app")` | Force stops application. |
| | `clear_app_data(pkg)`| `mobile.clear_app_data("com.app")`| Resets app state. |
| | `grant_permissions()`| `mobile.grant_permissions(pkg, ["camera"])` | Auto-allow permissions. |
| | `set_location(lat, lon)`| `mobile.set_location(12.9, 77.5)`| Spoofs GPS coordinates. |
| | `set_orientation(mode)`| `mobile.set_orientation("landscape")`| Portrait/Landscape switch. |
| **Keyboard** | `send_keys(text)` | `mobile.send_keys("Hello")` | Direct text to focused field. |
| | `hide_keyboard()` | `mobile.hide_keyboard()` | Dismisses soft keyboard. |
| | `show_keyboard()` | `mobile.show_keyboard()` | Forces keyboard to open. |
| | `press_key(key)` | `mobile.press_key("ENTER")` | Hardware key (BACK, HOME, etc). |
| **Gestures** | `swipe(x1,y1,x2,y2)` | `mobile.swipe(100,500,900,500)`| Raw coordinate movement. |
| | `scroll_to_text(text)`| `mobile.scroll_to_text("Accept")`| Scrolls until text found. |
| | `drag_and_drop(s, t)`| `mobile.drag_and_drop("App", "Bin")`| Moves element. |
| | `flick(x1,y1,x2,y2)` | `mobile.flick(500,800,500,200)`| Fast swipe gesture. |
| **Discovery** | `get_page_source()` | `xml = mobile.get_page_source()`| Returns UI hierarchy XML. |
| | `get_all_texts()` | `mobile.get_all_texts_displayed()`| Returns all visible strings. |
| | `get_text(target)` | `mobile.get_text("Title")` | Reads text from element. |
| | `get_element_attributes(t)` | `attrs = mobile.get_element_attributes("Btn")` | Gets detailed layout, state, and visual properties. |
| | `get_attributes()` | `attrs = mobile.element("Btn").get_attributes()` | Chained attributes retriever for elements. |
| **Media** | `take_screenshot(n)`| `mobile.take_screenshot("err")`| Captures full screen. |
| | `capture_element(t,n)`| `mobile.capture_element_screenshot("Btn","c")`| **Crops** to element bounds. |
| | `start_recording()` | `mobile.start_screen_recording()`| Captures MP4 video. |
| | `capture_photo()` | `mobile.capture_photo()` | Shutter + Auto-OK. |
| **State** | `is_enabled(target)` | `mobile.is_enabled("Submit")` | Clickable state check. |
| | `is_visible(target)` | `mobile.is_visible("Title")` | Visibility check. |
| **Wait** | `wait_for_page_ready()`| `mobile.wait_for_page_ready()` | Waits for UI stability. |
| | `wait_until_visible()` | `mobile.wait_until_visible("OK")`| Polling wait until visible. |
| | `wait_until_gone()` | `mobile.wait_until_gone("Load")`| Polling wait until vanished. |
| **Validation** | `verify_text(text)` | `mobile.verify_text("Saved")` | Assert exact text exists. |
| | `verify_present(t)` | `mobile.verify_element_present("id")`| Assert element exists. |
| **Advanced** | `execute_shell()` | `mobile.execute_shell_command("ls")`| Raw shell access. |
| | `execute_adb()` | `mobile.execute_adb("devices")`| Raw ADB command. |
| | `find_by_image()` | `mobile.find_by_image_click("p.png")`| **Visual Match** + Click. |

---

## 🏗️ 4. CLI Tooling Reference

| Command | Example | Description |
| :--- | :--- | :--- |
| `init` | `apppilot init` | Scaffolds a new project. |
| `setup` | `apppilot setup --project_folder tests` | Initializes project in specific folder. |
| `--overwrite`| `apppilot setup --overwrite` | Overwrites `apppilot.yaml` with latest defaults. |
| `doctor` | `apppilot doctor` | Dependency and tool path health check. |
| `devices` | `apppilot devices` | Lists all connected device serials. |
| `interactive`| `apppilot interactive`| **Live REPL:** Run commands one-by-one. |
| `run` | `apppilot run` | Standard test execution. |
| `report` | `apppilot report` | Generates/Serves HTML test report. |

---

## 📂 5. Configuration (`apppilot.yaml`)

```yaml
# apppilot.yaml
tools:
  adb_path: 'C:\path\to\adb.exe'
  scrcpy_path: 'C:\path\to\scrcpy.exe'
  log_path: '.apppilot/logs'  # Custom log folder

mirror_screen: true
auto_scroll: true
timeout: 30
recorder_refresh_delay: 1.5  # Time (in seconds) to wait for screen transitions before refreshing the recorder view
```

> **Note for Windows Users:** Always use single quotes `'` for paths to avoid errors with backslashes.

---

## 🛠️ 6. Discovery & Debugging Example

When you are automating a new app and don't know the IDs, use this "Discovery Script" to find everything you need.

```python
import pytest
from apppilot.api.mobile import Mobile

def test_discovery_session(mobile):
    # 1. Launch the app and check health
    mobile.launch_app("com.android.chrome")
    mobile.diagnose()  # Prints CPU/Memory and current Activity
    
    # 2. Navigate to a complex page
    mobile.navigate("https://www.google.com")
    mobile.wait_for_page_ready()
    
    # 3. Inspect the UI to find hidden locators
    # This will print every INPUT, BUTTON, and TEXT with coordinates
    mobile.inspect()
    
    # 4. Use Relational Selectors for elements without IDs
    # "Find the input to the right of the Google Search icon"
    mobile.right_of("Google Search").input().fill("AppPilot Mobile")
    
    # 5. Check performance after interaction
    perf = mobile.get_performance()
    print(f"Current App Memory Usage: {perf['memory_mb']} MB")
    
    mobile.press_key(66) # Enter
    mobile.screenshot("discovery_result")
```

---

© 2026 AppPilot Mobile Framework | Built for Engineers.
