use aethermap_common::{DeviceInfo, MacroEntry, KeyCombo, Action, DeviceType};
use aethermap_gui::{State, Message};
use iced::application::Application;
use std::path::PathBuf;
use std::time::Instant;
fn create_test_device(name: &str, path: &str) -> DeviceInfo {
DeviceInfo {
name: name.to_string(),
path: PathBuf::from(path),
vendor_id: 0x1532,
product_id: 0x0203,
phys: "usb-0000:00:14.0-1/input/input0".to_string(),
device_type: DeviceType::Keyboard,
}
}
fn create_test_macro(name: &str, enabled: bool) -> MacroEntry {
MacroEntry {
name: name.to_string(),
trigger: KeyCombo {
keys: vec![30, 40], modifiers: vec![29], },
actions: vec![
Action::KeyPress(30),
Action::Delay(100),
Action::KeyRelease(30),
],
device_id: Some("test_device".to_string()),
enabled,
humanize: true,
capture_mouse: false,
}
}
fn create_test_state() -> State {
let mut state = State::default();
state.devices = vec![
create_test_device("Razer Keyboard", "/dev/input/event0"),
create_test_device("Razer Mouse", "/dev/input/event1"),
];
state.macros = vec![
create_test_macro("Test Macro 1", true),
create_test_macro("Test Macro 2", false),
];
state.selected_device = Some(0);
state.status = "Test initialized".to_string();
state.status_history.push_back("Previous status 1".to_string());
state.status_history.push_back("Previous status 2".to_string());
state.daemon_connected = true;
state.socket_path = PathBuf::from("/tmp/test.sock");
state
}
#[test]
fn test_gui_construction_and_view() {
let state = create_test_state();
let _element = state.view();
assert!(true, "GUI view should build without panicking");
}
#[test]
fn test_devices_loaded_message() {
let mut state = State::default();
let devices = vec![
create_test_device("Test Device 1", "/dev/input/event0"),
create_test_device("Test Device 2", "/dev/input/event1"),
];
let message = Message::DevicesLoaded(Ok(devices.clone()));
let _command = state.update(message);
assert_eq!(state.devices.len(), 2);
assert_eq!(state.devices[0].name, "Test Device 1");
assert_eq!(state.devices[1].name, "Test Device 2");
assert!(state.selected_device.is_none());
}
#[test]
fn test_macros_loaded_message() {
let mut state = State::default();
let macros = vec![
create_test_macro("Test Macro 1", true),
create_test_macro("Test Macro 2", false),
create_test_macro("Test Macro 3", true),
];
let message = Message::MacrosLoaded(Ok(macros.clone()));
let _command = state.update(message);
assert_eq!(state.macros.len(), 3);
assert_eq!(state.macros[0].name, "Test Macro 1");
assert_eq!(state.macros[1].name, "Test Macro 2");
assert_eq!(state.macros[2].name, "Test Macro 3");
assert!(state.macros[0].enabled);
assert!(!state.macros[1].enabled);
assert!(state.macros[2].enabled);
}
#[test]
fn test_view_structure_contains_devices() {
let state = create_test_state();
let element = state.view();
assert!(!state.devices.is_empty(), "Should have devices to render");
assert!(state.devices.len() >= 1, "Should have at least one device");
for device in &state.devices {
assert!(!device.name.is_empty(), "Device name should not be empty");
assert!(!device.path.as_os_str().is_empty(), "Device path should not be empty");
}
}
#[test]
fn test_view_structure_contains_macros() {
let state = create_test_state();
let element = state.view();
assert!(!state.macros.is_empty(), "Should have macros to render");
assert!(state.macros.len() >= 1, "Should have at least one macro");
for macro_entry in &state.macros {
assert!(!macro_entry.name.is_empty(), "Macro name should not be empty");
assert!(!macro_entry.actions.is_empty(), "Macro should have actions");
}
}
#[test]
fn test_recording_state_updates() {
let mut state = State::default();
assert!(!state.recording, "Should not be recording initially");
assert!(state.recording_macro_name.is_none(), "Should have no recording macro name");
let message = Message::StartRecording;
let _command = state.update(message);
state.recording = true;
state.recording_macro_name = Some("Test Recording".to_string());
assert!(state.recording, "Should be recording");
assert_eq!(state.recording_macro_name.as_ref().unwrap(), "Test Recording");
let _element = state.view();
}
#[test]
fn test_status_updates() {
let mut state = State::default();
let message = Message::ShowNotification("New status message".to_string(), false);
let _command = state.update(message);
assert!(!state.status_history.is_empty(), "Should have status history");
let _element = state.view();
}
#[test]
fn test_recently_updated_macros() {
let mut state = State::default();
let macro_name = "Test Macro".to_string();
state.recently_updated_macros.insert(macro_name.clone(), Instant::now());
assert!(state.recently_updated_macros.contains_key(¯o_name));
let _element = state.view();
}
#[test]
fn test_error_handling() {
let mut state = State::default();
let error_msg = "Failed to load devices".to_string();
let message = Message::DevicesLoaded(Err(error_msg.clone()));
let _command = state.update(message);
{
let _element = state.view();
}
let macro_error = "Failed to load macros".to_string();
let message = Message::MacrosLoaded(Err(macro_error.clone()));
let _command = state.update(message);
let _element = state.view();
}
#[test]
fn test_animation_ticker() {
let mut state = State::default();
state.recently_updated_macros.insert("Macro1".to_string(), Instant::now());
state.recently_updated_macros.insert("Macro2".to_string(), Instant::now());
let message = Message::TickAnimations;
let _command = state.update(message);
assert!(!state.recently_updated_macros.is_empty());
let _element = state.view();
}
#[test]
fn test_complete_flow_simulation() {
let mut state = State::default();
let connect_msg = Message::DaemonStatusChanged(true);
let _command = state.update(connect_msg);
assert!(state.daemon_connected);
let devices_msg = Message::DevicesLoaded(Ok(vec![create_test_device("Test Device", "/dev/input/event0")]));
let _command = state.update(devices_msg);
assert_eq!(state.devices.len(), 1);
let macros_msg = Message::MacrosLoaded(Ok(vec![create_test_macro("Test Macro", true)]));
let _command = state.update(macros_msg);
assert_eq!(state.macros.len(), 1);
let status_msg = Message::ShowNotification("Application ready".to_string(), false);
let _command = state.update(status_msg);
let _element = state.view();
assert!(true, "Complete application flow should work without panicking");
}