use car_desktop::models::{
ClickRequest, KeyPressRequest, MouseButton, TypeRequest, WindowFilter, WindowHandle,
};
use car_desktop::{default_backend, CarDesktopError};
#[tokio::test]
async fn list_windows_returns_expected_error_surface_on_unsupported() {
if cfg!(target_os = "macos") {
return;
}
let backend = default_backend();
let result = backend.list_windows(WindowFilter::default()).await;
assert!(
matches!(result, Err(CarDesktopError::PlatformUnsupported { .. })),
"unexpected error variant on unsupported platform: {result:?}"
);
}
#[cfg(target_os = "macos")]
#[tokio::test]
async fn list_windows_succeeds_on_macos() {
let backend = default_backend();
let all = backend
.list_windows(WindowFilter::default())
.await
.expect("list_windows must succeed on macOS with the macos feature");
assert!(
!all.is_empty(),
"expected at least one on-screen window (the test host's terminal or IDE)"
);
for info in &all {
assert!(
info.handle.pid > 0,
"pid must be populated for {}",
info.owner_name
);
assert!(
info.frame.width >= 0.0 && info.frame.height >= 0.0,
"frame dims must be non-negative for {:?}",
info
);
}
let pid = all[0].handle.pid;
let filtered = backend
.list_windows(WindowFilter::by_pid(pid))
.await
.expect("pid-filtered list_windows must succeed");
assert!(
filtered.iter().any(|w| w.handle.pid == pid),
"pid filter dropped every window for pid {pid}"
);
}
#[cfg(target_os = "macos")]
#[tokio::test]
#[ignore = "requires Screen Recording permission"]
async fn capture_primary_display_round_trips_bytes() {
use car_desktop::models::DisplayId;
let backend = default_backend();
let frame = backend
.capture_display(DisplayId::PRIMARY)
.await
.expect("capture_display must succeed on macOS with Screen Recording granted");
assert!(frame.width > 0, "display width must be non-zero");
assert!(frame.height > 0, "display height must be non-zero");
assert_eq!(
frame.rgba.len(),
frame.width as usize * frame.height as usize * 4,
"RGBA buffer must match declared dimensions",
);
}
#[cfg(target_os = "macos")]
#[tokio::test]
async fn focus_nonexistent_window_reports_window_not_found() {
use car_desktop::models::WindowHandle;
let backend = default_backend();
let result = backend.focus_window(WindowHandle::new(0, 0)).await;
assert!(
matches!(result, Err(CarDesktopError::WindowNotFound { .. })),
"expected WindowNotFound for bogus pid, got {result:?}"
);
}
#[tokio::test]
async fn click_against_bogus_window_errors_cleanly() {
let backend = default_backend();
let window = WindowHandle::new(1, 1);
let result = backend
.click(ClickRequest {
window,
element_id: None,
point: Some((10.0, 10.0)),
button: MouseButton::Left,
modifiers: Vec::new(),
unsafe_ok: false,
dry_run: false,
})
.await;
match result {
Err(CarDesktopError::PlatformUnsupported { .. })
| Err(CarDesktopError::NotYetImplemented { .. })
| Err(CarDesktopError::WindowNotFound { .. })
| Err(CarDesktopError::OutOfTargetWindow { .. })
| Err(CarDesktopError::RateLimited)
| Err(CarDesktopError::PermissionDenied { .. }) => {}
other => panic!("unexpected click() result against bogus pid: {other:?}"),
}
}
#[tokio::test]
async fn type_text_dry_run_succeeds_on_macos_errors_on_others() {
let backend = default_backend();
let result = backend
.type_text(TypeRequest {
window: WindowHandle::new(1, 1),
text: "hello".into(),
dry_run: true,
})
.await;
if cfg!(target_os = "macos") {
assert!(
result.is_ok() || matches!(result, Err(CarDesktopError::WindowNotFound { .. })),
"dry-run type_text: {result:?}"
);
} else {
assert!(matches!(
result,
Err(CarDesktopError::PlatformUnsupported { .. })
));
}
}
#[tokio::test]
async fn keypress_dry_run_unsupported_character_reports_clearly() {
let backend = default_backend();
let result = backend
.keypress(KeyPressRequest {
window: WindowHandle::new(1, 1),
key: car_desktop::models::Key::Char('\u{FFFD}'),
modifiers: Vec::new(),
dry_run: true,
})
.await;
if cfg!(target_os = "macos") {
assert!(
matches!(result, Err(CarDesktopError::UnsupportedCharacter { .. })),
"unexpected keypress result: {result:?}"
);
} else {
assert!(matches!(
result,
Err(CarDesktopError::PlatformUnsupported { .. })
));
}
}