use cosh_tools::computer::touch::validate;
use cosh_tools::computer::types::{ActAction, ComputerAct, SurfaceKind};
fn main() {
let export = ComputerAct {
name: Some("Reports".into()),
selector: Some("button[name='Export']".into()),
action: Some(ActAction::Press), timeout_ms: Some(5000),
..Default::default()
};
assert!(validate(&export, "computer_act").is_ok());
let fill_and_export = ComputerAct {
name: Some("Reports".into()),
selector: Some("text_field[name='Filename']".into()),
action: Some(ActAction::SetValue),
value: Some("2026-q3".into()),
..Default::default()
}
.chain(ComputerAct {
wait: Some(400), ..Default::default()
})
.chain(ComputerAct {
name: Some("Reports".into()),
selector: Some("button[name='Export']".into()),
action: Some(ActAction::Press),
..Default::default()
});
assert!(validate(&fill_and_export, "computer_act").is_ok());
println!("semantic pipeline validated (3 steps)");
let select_all = ComputerAct {
key: Some("a".into()),
held: Some(vec!["ctrl".into()]),
..Default::default()
};
if let Err(e) = validate(&select_all, "computer_act") {
println!("keyboard step under the semantic validator: {e}");
}
let no_selector = ComputerAct {
action: Some(ActAction::Press),
name: Some("Reports".into()),
..Default::default()
};
if let Err(e) = validate(&no_selector, "computer_act") {
println!("missing selector rejected: {e}");
}
let set_value_without_value = ComputerAct {
name: Some("Reports".into()),
selector: Some("text_field[name='Filename']".into()),
action: Some(ActAction::SetNumericValue),
..Default::default()
};
if let Err(e) = validate(&set_value_without_value, "computer_act") {
println!("missing payload rejected: {e}");
}
let press_taskbar_item = ComputerAct {
surface: Some(SurfaceKind::Taskbar),
selector: Some("button[name='Files']".into()),
..Default::default()
};
assert!(validate(&press_taskbar_item, "computer_act").is_ok());
}
trait Chain: Sized {
fn chain(self, next: ComputerAct) -> Self;
}
impl Chain for ComputerAct {
fn chain(mut self, next: ComputerAct) -> Self {
let mut tail = &mut self;
while tail.then.is_some() {
tail = tail.then.as_deref_mut().unwrap();
}
tail.then = Some(Box::new(next));
self
}
}