use native_devtools_mcp::android::{device, input, navigation, screenshot, ui_automator};
use std::thread;
use std::time::Duration;
fn connect_first_device() -> device::AndroidDevice {
let devices = device::list_devices().expect("Failed to list devices");
assert!(!devices.is_empty(), "No ADB devices connected");
let serial = &devices[0].serial;
device::AndroidDevice::connect(serial)
.unwrap_or_else(|e| panic!("Failed to connect to device '{}': {}", serial, e))
}
fn wake_and_go_home(device: &mut device::AndroidDevice) {
input::press_key(device, "KEYCODE_WAKEUP").ok();
thread::sleep(Duration::from_millis(500));
input::press_key(device, "KEYCODE_HOME").ok();
thread::sleep(Duration::from_secs(1));
}
fn launch_settings(device: &mut device::AndroidDevice) {
navigation::launch_app(device, "com.android.settings").expect("Failed to launch Settings");
thread::sleep(Duration::from_secs(2));
}
#[test]
#[ignore]
fn test_list_devices() {
let devices = device::list_devices().expect("Failed to list devices");
assert!(!devices.is_empty(), "No ADB devices connected");
for d in &devices {
assert!(!d.serial.is_empty());
assert_eq!(
d.state, "device",
"Device '{}' not ready: {}",
d.serial, d.state
);
}
}
#[test]
#[ignore]
fn test_connect_and_shell() {
let mut device = connect_first_device();
let output = device.shell("echo hello").expect("Shell command failed");
assert!(output.contains("hello"));
}
#[test]
#[ignore]
fn test_get_display_info() {
let mut device = connect_first_device();
let info = navigation::get_display_info(&mut device).expect("Failed to get display info");
assert!(info.width > 0);
assert!(info.height > 0);
assert!(info.density > 0);
}
#[test]
#[ignore]
fn test_screenshot() {
let mut device = connect_first_device();
let shot = screenshot::capture(&mut device).expect("Failed to capture screenshot");
assert!(!shot.png_data.is_empty());
assert!(shot.width > 0);
assert!(shot.height > 0);
assert_eq!(&shot.png_data[..4], &[0x89, 0x50, 0x4E, 0x47]);
}
#[test]
#[ignore]
fn test_list_apps() {
let mut device = connect_first_device();
let apps = navigation::list_apps(&mut device, false).expect("Failed to list apps");
assert!(!apps.is_empty());
assert!(apps
.iter()
.any(|a| a.package_name == "com.android.settings"));
}
#[test]
#[ignore]
fn test_press_key_and_click() {
let mut device = connect_first_device();
wake_and_go_home(&mut device);
let info = navigation::get_display_info(&mut device).expect("Failed to get display info");
input::click(
&mut device,
info.width as f64 / 2.0,
info.height as f64 / 2.0,
)
.expect("Failed to tap screen");
}
#[test]
#[ignore]
fn test_get_current_activity() {
let mut device = connect_first_device();
wake_and_go_home(&mut device);
launch_settings(&mut device);
let activity =
navigation::get_current_activity(&mut device).expect("Failed to get current activity");
assert!(activity.package.contains("com.android.settings"));
input::press_key(&mut device, "KEYCODE_HOME").ok();
}
#[test]
#[ignore]
fn test_launch_app() {
let mut device = connect_first_device();
wake_and_go_home(&mut device);
launch_settings(&mut device);
let shot = screenshot::capture(&mut device).expect("Failed to capture screenshot");
assert!(shot.width > 0);
input::press_key(&mut device, "KEYCODE_HOME").ok();
}
#[test]
#[ignore]
fn test_find_text_in_settings() {
let mut device = connect_first_device();
wake_and_go_home(&mut device);
launch_settings(&mut device);
let result = ui_automator::find_text(&mut device, "Settings")
.expect("uiautomator dump failed — is the screen unlocked?");
assert!(
!result.matches.is_empty(),
"Should find 'Settings' text in Settings app"
);
assert!(
result.matches[0].x > 0.0 && result.matches[0].y > 0.0,
"Coordinates should be positive"
);
assert!(result.matches[0].bounds.width > 0.0 && result.matches[0].bounds.height > 0.0);
input::press_key(&mut device, "KEYCODE_HOME").ok();
}
#[test]
#[ignore]
fn test_swipe() {
let mut device = connect_first_device();
wake_and_go_home(&mut device);
launch_settings(&mut device);
let info = navigation::get_display_info(&mut device).expect("Failed to get display info");
let cx = info.width as f64 / 2.0;
let top = info.height as f64 * 0.7;
let bottom = info.height as f64 * 0.3;
input::swipe(&mut device, cx, top, cx, bottom, Some(300)).expect("Failed to swipe");
input::press_key(&mut device, "KEYCODE_HOME").ok();
}
#[test]
#[ignore]
fn test_type_text() {
let mut device = connect_first_device();
wake_and_go_home(&mut device);
launch_settings(&mut device);
let info = navigation::get_display_info(&mut device).expect("Failed to get display info");
let search_results = ui_automator::find_text(&mut device, "Search");
if let Ok(result) = search_results {
if !result.matches.is_empty() {
input::click(&mut device, result.matches[0].x, result.matches[0].y).ok();
thread::sleep(Duration::from_secs(1));
input::type_text(&mut device, "wifi").expect("Failed to type text");
thread::sleep(Duration::from_secs(1));
}
}
input::press_key(&mut device, "KEYCODE_HOME").ok();
let _ = info;
}