diff --git a/cli/src/commands.rs b/cli/src/commands.rs index b13b5e2..c7cca7b 100644 --- a/cli/src/commands.rs +++ b/cli/src/commands.rs @@ -684,15 +684,39 @@ fn parse_find(rest: &[&str], id: &str) -> Result { }; match *locator { - "role" => Ok(json!({ "id": id, "action": "getbyrole", "role": value, "subaction": subaction, "value": fill_value, "name": name, "exact": exact })), + "role" => { + let mut cmd = json!({ "id": id, "action": "getbyrole", "role": value, "subaction": subaction, "name": name, "exact": exact }); + if let Some(v) = fill_value { cmd["value"] = json!(v); } + Ok(cmd) + } "text" => Ok(json!({ "id": id, "action": "getbytext", "text": value, "subaction": subaction, "exact": exact })), - "label" => Ok(json!({ "id": id, "action": "getbylabel", "label": value, "subaction": subaction, "value": fill_value, "exact": exact })), - "placeholder" => Ok(json!({ "id": id, "action": "getbyplaceholder", "placeholder": value, "subaction": subaction, "value": fill_value, "exact": exact })), + "label" => { + let mut cmd = json!({ "id": id, "action": "getbylabel", "label": value, "subaction": subaction, "exact": exact }); + if let Some(v) = fill_value { cmd["value"] = json!(v); } + Ok(cmd) + } + "placeholder" => { + let mut cmd = json!({ "id": id, "action": "getbyplaceholder", "placeholder": value, "subaction": subaction, "exact": exact }); + if let Some(v) = fill_value { cmd["value"] = json!(v); } + Ok(cmd) + } "alt" => Ok(json!({ "id": id, "action": "getbyalttext", "text": value, "subaction": subaction, "exact": exact })), "title" => Ok(json!({ "id": id, "action": "getbytitle", "text": value, "subaction": subaction, "exact": exact })), - "testid" => Ok(json!({ "id": id, "action": "getbytestid", "testId": value, "subaction": subaction, "value": fill_value })), - "first" => Ok(json!({ "id": id, "action": "nth", "selector": value, "index": 0, "subaction": subaction, "value": fill_value })), - "last" => Ok(json!({ "id": id, "action": "nth", "selector": value, "index": -1, "subaction": subaction, "value": fill_value })), + "testid" => { + let mut cmd = json!({ "id": id, "action": "getbytestid", "testId": value, "subaction": subaction }); + if let Some(v) = fill_value { cmd["value"] = json!(v); } + Ok(cmd) + } + "first" => { + let mut cmd = json!({ "id": id, "action": "nth", "selector": value, "index": 0, "subaction": subaction }); + if let Some(v) = fill_value { cmd["value"] = json!(v); } + Ok(cmd) + } + "last" => { + let mut cmd = json!({ "id": id, "action": "nth", "selector": value, "index": -1, "subaction": subaction }); + if let Some(v) = fill_value { cmd["value"] = json!(v); } + Ok(cmd) + } _ => unreachable!(), } } @@ -715,7 +739,9 @@ fn parse_find(rest: &[&str], id: &str) -> Result { } else { None }; - Ok(json!({ "id": id, "action": "nth", "selector": sel, "index": idx, "subaction": sub, "value": fv })) + let mut cmd = json!({ "id": id, "action": "nth", "selector": sel, "index": idx, "subaction": sub }); + if let Some(v) = fv { cmd["value"] = json!(v); } + Ok(cmd) } _ => Err(ParseError::UnknownSubcommand { subcommand: locator.to_string(), @@ -756,7 +782,7 @@ fn parse_mouse(rest: &[&str], id: &str) -> Result { Some("wheel") => { let dy = rest.get(1).and_then(|s| s.parse::().ok()).unwrap_or(100); let dx = rest.get(2).and_then(|s| s.parse::().ok()).unwrap_or(0); - Ok(json!({ "id": id, "action": "mousewheel", "deltaX": dx, "deltaY": dy })) + Ok(json!({ "id": id, "action": "wheel", "deltaX": dx, "deltaY": dy })) } Some(sub) => Err(ParseError::UnknownSubcommand { subcommand: sub.to_string(), @@ -854,8 +880,12 @@ fn parse_set(rest: &[&str], id: &str) -> Result { } else { "no-preference" }; - let reduced = rest.iter().any(|&s| s == "reduced-motion"); - Ok(json!({ "id": id, "action": "media", "colorScheme": color, "reducedMotion": reduced })) + let reduced = if rest.iter().any(|&s| s == "reduced-motion") { + "reduce" + } else { + "no-preference" + }; + Ok(json!({ "id": id, "action": "emulatemedia", "colorScheme": color, "reducedMotion": reduced })) } Some(sub) => Err(ParseError::UnknownSubcommand { subcommand: sub.to_string(), @@ -1447,4 +1477,54 @@ mod tests { assert!(matches!(err, ParseError::MissingArguments { .. })); assert!(err.format().contains("get text")); } + + // === Protocol alignment tests === + + #[test] + fn test_mouse_wheel() { + let cmd = parse_command(&args("mouse wheel 100 50"), &default_flags()).unwrap(); + assert_eq!(cmd["action"], "wheel"); + assert_eq!(cmd["deltaY"], 100); + assert_eq!(cmd["deltaX"], 50); + } + + #[test] + fn test_set_media() { + let cmd = parse_command(&args("set media dark"), &default_flags()).unwrap(); + assert_eq!(cmd["action"], "emulatemedia"); + assert_eq!(cmd["colorScheme"], "dark"); + assert_eq!(cmd["reducedMotion"], "no-preference"); + } + + #[test] + fn test_set_media_reduced_motion() { + let cmd = parse_command(&args("set media light reduced-motion"), &default_flags()).unwrap(); + assert_eq!(cmd["action"], "emulatemedia"); + assert_eq!(cmd["colorScheme"], "light"); + assert_eq!(cmd["reducedMotion"], "reduce"); + } + + #[test] + fn test_find_first_no_value() { + let cmd = parse_command(&args("find first a click"), &default_flags()).unwrap(); + assert_eq!(cmd["action"], "nth"); + assert_eq!(cmd["index"], 0); + assert!(cmd.get("value").is_none()); + } + + #[test] + fn test_find_first_with_value() { + let cmd = parse_command(&args("find first input fill hello"), &default_flags()).unwrap(); + assert_eq!(cmd["action"], "nth"); + assert_eq!(cmd["index"], 0); + assert_eq!(cmd["value"], "hello"); + } + + #[test] + fn test_find_nth_no_value() { + let cmd = parse_command(&args("find nth 2 a click"), &default_flags()).unwrap(); + assert_eq!(cmd["action"], "nth"); + assert_eq!(cmd["index"], 2); + assert!(cmd.get("value").is_none()); + } }