fix(cli): align protocol action names for wheel, emulatemedia, and find locators (#143)
- mouse wheel: send 'wheel' instead of 'mousewheel' - set media: send 'emulatemedia' instead of 'media', fix reducedMotion to be string enum - find locators: omit 'value' field when not provided (Zod .optional() expects undefined, not null) - Consistently applied to: role, label, placeholder, testid, first, last, nth Fixes #131
This commit is contained in:
+90
-10
@@ -684,15 +684,39 @@ fn parse_find(rest: &[&str], id: &str) -> Result<Value, ParseError> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match *locator {
|
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 })),
|
"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 })),
|
"label" => {
|
||||||
"placeholder" => Ok(json!({ "id": id, "action": "getbyplaceholder", "placeholder": value, "subaction": subaction, "value": fill_value, "exact": exact })),
|
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 })),
|
"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 })),
|
"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 })),
|
"testid" => {
|
||||||
"first" => Ok(json!({ "id": id, "action": "nth", "selector": value, "index": 0, "subaction": subaction, "value": fill_value })),
|
let mut cmd = json!({ "id": id, "action": "getbytestid", "testId": value, "subaction": subaction });
|
||||||
"last" => Ok(json!({ "id": id, "action": "nth", "selector": value, "index": -1, "subaction": subaction, "value": fill_value })),
|
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!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -715,7 +739,9 @@ fn parse_find(rest: &[&str], id: &str) -> Result<Value, ParseError> {
|
|||||||
} else {
|
} else {
|
||||||
None
|
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 {
|
_ => Err(ParseError::UnknownSubcommand {
|
||||||
subcommand: locator.to_string(),
|
subcommand: locator.to_string(),
|
||||||
@@ -756,7 +782,7 @@ fn parse_mouse(rest: &[&str], id: &str) -> Result<Value, ParseError> {
|
|||||||
Some("wheel") => {
|
Some("wheel") => {
|
||||||
let dy = rest.get(1).and_then(|s| s.parse::<i32>().ok()).unwrap_or(100);
|
let dy = rest.get(1).and_then(|s| s.parse::<i32>().ok()).unwrap_or(100);
|
||||||
let dx = rest.get(2).and_then(|s| s.parse::<i32>().ok()).unwrap_or(0);
|
let dx = rest.get(2).and_then(|s| s.parse::<i32>().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 {
|
Some(sub) => Err(ParseError::UnknownSubcommand {
|
||||||
subcommand: sub.to_string(),
|
subcommand: sub.to_string(),
|
||||||
@@ -854,8 +880,12 @@ fn parse_set(rest: &[&str], id: &str) -> Result<Value, ParseError> {
|
|||||||
} else {
|
} else {
|
||||||
"no-preference"
|
"no-preference"
|
||||||
};
|
};
|
||||||
let reduced = rest.iter().any(|&s| s == "reduced-motion");
|
let reduced = if rest.iter().any(|&s| s == "reduced-motion") {
|
||||||
Ok(json!({ "id": id, "action": "media", "colorScheme": color, "reducedMotion": reduced }))
|
"reduce"
|
||||||
|
} else {
|
||||||
|
"no-preference"
|
||||||
|
};
|
||||||
|
Ok(json!({ "id": id, "action": "emulatemedia", "colorScheme": color, "reducedMotion": reduced }))
|
||||||
}
|
}
|
||||||
Some(sub) => Err(ParseError::UnknownSubcommand {
|
Some(sub) => Err(ParseError::UnknownSubcommand {
|
||||||
subcommand: sub.to_string(),
|
subcommand: sub.to_string(),
|
||||||
@@ -1447,4 +1477,54 @@ mod tests {
|
|||||||
assert!(matches!(err, ParseError::MissingArguments { .. }));
|
assert!(matches!(err, ParseError::MissingArguments { .. }));
|
||||||
assert!(err.format().contains("get text"));
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user