Fix clippy lints (#399)

* cargo fmt

* fix: remove redundant `use libc` import (clippy::single_component_path_imports)

* fix: use `.first()` instead of `.get(0)` (clippy::get_first)

* fix: use `.copied()` instead of `.map(|s| *s)` (clippy::map_clone)

* fix: allow too_many_arguments on ensure_daemon (clippy::too_many_arguments)

* fix: use `then_some` instead of `then` with closure (clippy::unnecessary_lazy_evaluations)

* fix: use pattern match instead of redundant guard (clippy::redundant_guards)

* fix: use pattern match instead of redundant guard in commands.rs (clippy::redundant_guards)

* fix: use `contains()` instead of `iter().any()` for simple equality (clippy::manual_contains)

* Add changeset
This commit is contained in:
Mathias Lafeldt
2026-02-13 10:44:35 -06:00
committed by GitHub
parent 604c0b9632
commit 323b6cdd9d
5 changed files with 107 additions and 81 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"agent-browser": patch
---
Fix all Clippy lint warnings in the Rust CLI: remove redundant import, use `.first()` instead of `.get(0)`, use `.copied()` instead of `.map(|s| *s)`, use `.contains()` instead of `.iter().any()`, use `then_some` instead of lazy `then`, and simplify redundant match guards.
+72 -62
View File
@@ -81,7 +81,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
match cmd { match cmd {
// === Navigation === // === Navigation ===
"open" | "goto" | "navigate" => { "open" | "goto" | "navigate" => {
let url = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let url = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: cmd.to_string(), context: cmd.to_string(),
usage: "open <url>", usage: "open <url>",
})?; })?;
@@ -117,63 +117,63 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
// === Core Actions === // === Core Actions ===
"click" => { "click" => {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let sel = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "click".to_string(), context: "click".to_string(),
usage: "click <selector>", usage: "click <selector>",
})?; })?;
Ok(json!({ "id": id, "action": "click", "selector": sel })) Ok(json!({ "id": id, "action": "click", "selector": sel }))
} }
"dblclick" => { "dblclick" => {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let sel = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "dblclick".to_string(), context: "dblclick".to_string(),
usage: "dblclick <selector>", usage: "dblclick <selector>",
})?; })?;
Ok(json!({ "id": id, "action": "dblclick", "selector": sel })) Ok(json!({ "id": id, "action": "dblclick", "selector": sel }))
} }
"fill" => { "fill" => {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let sel = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "fill".to_string(), context: "fill".to_string(),
usage: "fill <selector> <text>", usage: "fill <selector> <text>",
})?; })?;
Ok(json!({ "id": id, "action": "fill", "selector": sel, "value": rest[1..].join(" ") })) Ok(json!({ "id": id, "action": "fill", "selector": sel, "value": rest[1..].join(" ") }))
} }
"type" => { "type" => {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let sel = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "type".to_string(), context: "type".to_string(),
usage: "type <selector> <text>", usage: "type <selector> <text>",
})?; })?;
Ok(json!({ "id": id, "action": "type", "selector": sel, "text": rest[1..].join(" ") })) Ok(json!({ "id": id, "action": "type", "selector": sel, "text": rest[1..].join(" ") }))
} }
"hover" => { "hover" => {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let sel = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "hover".to_string(), context: "hover".to_string(),
usage: "hover <selector>", usage: "hover <selector>",
})?; })?;
Ok(json!({ "id": id, "action": "hover", "selector": sel })) Ok(json!({ "id": id, "action": "hover", "selector": sel }))
} }
"focus" => { "focus" => {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let sel = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "focus".to_string(), context: "focus".to_string(),
usage: "focus <selector>", usage: "focus <selector>",
})?; })?;
Ok(json!({ "id": id, "action": "focus", "selector": sel })) Ok(json!({ "id": id, "action": "focus", "selector": sel }))
} }
"check" => { "check" => {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let sel = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "check".to_string(), context: "check".to_string(),
usage: "check <selector>", usage: "check <selector>",
})?; })?;
Ok(json!({ "id": id, "action": "check", "selector": sel })) Ok(json!({ "id": id, "action": "check", "selector": sel }))
} }
"uncheck" => { "uncheck" => {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let sel = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "uncheck".to_string(), context: "uncheck".to_string(),
usage: "uncheck <selector>", usage: "uncheck <selector>",
})?; })?;
Ok(json!({ "id": id, "action": "uncheck", "selector": sel })) Ok(json!({ "id": id, "action": "uncheck", "selector": sel }))
} }
"select" => { "select" => {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let sel = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "select".to_string(), context: "select".to_string(),
usage: "select <selector> <value...>", usage: "select <selector> <value...>",
})?; })?;
@@ -189,7 +189,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
} }
} }
"drag" => { "drag" => {
let src = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let src = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "drag".to_string(), context: "drag".to_string(),
usage: "drag <source> <target>", usage: "drag <source> <target>",
})?; })?;
@@ -200,14 +200,14 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
Ok(json!({ "id": id, "action": "drag", "source": src, "target": tgt })) Ok(json!({ "id": id, "action": "drag", "source": src, "target": tgt }))
} }
"upload" => { "upload" => {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let sel = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "upload".to_string(), context: "upload".to_string(),
usage: "upload <selector> <files...>", usage: "upload <selector> <files...>",
})?; })?;
Ok(json!({ "id": id, "action": "upload", "selector": sel, "files": &rest[1..] })) Ok(json!({ "id": id, "action": "upload", "selector": sel, "files": &rest[1..] }))
} }
"download" => { "download" => {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let sel = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "download".to_string(), context: "download".to_string(),
usage: "download <selector> <path>", usage: "download <selector> <path>",
})?; })?;
@@ -220,21 +220,21 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
// === Keyboard === // === Keyboard ===
"press" | "key" => { "press" | "key" => {
let key = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let key = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "press".to_string(), context: "press".to_string(),
usage: "press <key>", usage: "press <key>",
})?; })?;
Ok(json!({ "id": id, "action": "press", "key": key })) Ok(json!({ "id": id, "action": "press", "key": key }))
} }
"keydown" => { "keydown" => {
let key = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let key = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "keydown".to_string(), context: "keydown".to_string(),
usage: "keydown <key>", usage: "keydown <key>",
})?; })?;
Ok(json!({ "id": id, "action": "keydown", "key": key })) Ok(json!({ "id": id, "action": "keydown", "key": key }))
} }
"keyup" => { "keyup" => {
let key = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let key = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "keyup".to_string(), context: "keyup".to_string(),
usage: "keyup <key>", usage: "keyup <key>",
})?; })?;
@@ -243,7 +243,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
// === Scroll === // === Scroll ===
"scroll" => { "scroll" => {
let dir = rest.get(0).unwrap_or(&"down"); let dir = rest.first().unwrap_or(&"down");
let amount = rest let amount = rest
.get(1) .get(1)
.and_then(|s| s.parse::<i32>().ok()) .and_then(|s| s.parse::<i32>().ok())
@@ -251,7 +251,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
Ok(json!({ "id": id, "action": "scroll", "direction": dir, "amount": amount })) Ok(json!({ "id": id, "action": "scroll", "direction": dir, "amount": amount }))
} }
"scrollintoview" | "scrollinto" => { "scrollintoview" | "scrollinto" => {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let sel = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "scrollintoview".to_string(), context: "scrollintoview".to_string(),
usage: "scrollintoview <selector>", usage: "scrollintoview <selector>",
})?; })?;
@@ -332,7 +332,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
} }
// Default: selector or timeout // Default: selector or timeout
if let Some(arg) = rest.get(0) { if let Some(arg) = rest.first() {
if arg.parse::<u64>().is_ok() { if arg.parse::<u64>().is_ok() {
Ok( Ok(
json!({ "id": id, "action": "wait", "timeout": arg.parse::<u64>().unwrap() }), json!({ "id": id, "action": "wait", "timeout": arg.parse::<u64>().unwrap() }),
@@ -353,7 +353,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
// screenshot [selector] [path] // screenshot [selector] [path]
// selector: @ref or CSS selector // selector: @ref or CSS selector
// path: file path (contains / or . or ends with known extension) // path: file path (contains / or . or ends with known extension)
let (selector, path) = match (rest.get(0), rest.get(1)) { let (selector, path) = match (rest.first(), rest.get(1)) {
(Some(first), Some(second)) => { (Some(first), Some(second)) => {
// Two args: first is selector, second is path // Two args: first is selector, second is path
(Some(*first), Some(*second)) (Some(*first), Some(*second))
@@ -383,7 +383,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
) )
} }
"pdf" => { "pdf" => {
let path = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let path = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "pdf".to_string(), context: "pdf".to_string(),
usage: "pdf <path>", usage: "pdf <path>",
})?; })?;
@@ -442,17 +442,22 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
let script = if is_stdin { let script = if is_stdin {
// Read script from stdin // Read script from stdin
let stdin = io::stdin(); let stdin = io::stdin();
let lines: Vec<String> = stdin.lock().lines() let lines: Vec<String> = stdin
.lock()
.lines()
.map(|l| l.unwrap_or_default()) .map(|l| l.unwrap_or_default())
.collect(); .collect();
lines.join("\n") lines.join("\n")
} else { } else {
let raw_script = script_parts.join(" "); let raw_script = script_parts.join(" ");
if is_base64 { if is_base64 {
let decoded = STANDARD.decode(&raw_script).map_err(|_| ParseError::InvalidValue { let decoded =
message: "Invalid base64 encoding".to_string(), STANDARD
usage: "eval -b <base64-encoded-script>", .decode(&raw_script)
})?; .map_err(|_| ParseError::InvalidValue {
message: "Invalid base64 encoding".to_string(),
usage: "eval -b <base64-encoded-script>",
})?;
String::from_utf8(decoded).map_err(|_| ParseError::InvalidValue { String::from_utf8(decoded).map_err(|_| ParseError::InvalidValue {
message: "Base64 decoded to invalid UTF-8".to_string(), message: "Base64 decoded to invalid UTF-8".to_string(),
usage: "eval -b <base64-encoded-script>", usage: "eval -b <base64-encoded-script>",
@@ -483,7 +488,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
} else { } else {
// It's a port number - validate and use cdpPort field // It's a port number - validate and use cdpPort field
let port: u16 = match endpoint.parse::<u32>() { let port: u16 = match endpoint.parse::<u32>() {
Ok(p) if p == 0 => { Ok(0) => {
return Err(ParseError::InvalidValue { return Err(ParseError::InvalidValue {
message: "Invalid port: port must be greater than 0".to_string(), message: "Invalid port: port must be greater than 0".to_string(),
usage: "connect <port|url>", usage: "connect <port|url>",
@@ -536,7 +541,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
// === Cookies === // === Cookies ===
"cookies" => { "cookies" => {
let op = rest.get(0).unwrap_or(&"get"); let op = rest.first().unwrap_or(&"get");
match *op { match *op {
"set" => { "set" => {
let name = rest.get(1).ok_or_else(|| ParseError::MissingArguments { let name = rest.get(1).ok_or_else(|| ParseError::MissingArguments {
@@ -650,7 +655,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
} }
// === Tabs === // === Tabs ===
"tab" => match rest.get(0).map(|s| *s) { "tab" => match rest.first().copied() {
Some("new") => { Some("new") => {
let mut cmd = json!({ "id": id, "action": "tab_new" }); let mut cmd = json!({ "id": id, "action": "tab_new" });
if let Some(url) = rest.get(1) { if let Some(url) = rest.get(1) {
@@ -675,7 +680,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
// === Window === // === Window ===
"window" => { "window" => {
const VALID: &[&str] = &["new"]; const VALID: &[&str] = &["new"];
match rest.get(0).map(|s| *s) { match rest.first().copied() {
Some("new") => Ok(json!({ "id": id, "action": "window_new" })), Some("new") => Ok(json!({ "id": id, "action": "window_new" })),
Some(sub) => Err(ParseError::UnknownSubcommand { Some(sub) => Err(ParseError::UnknownSubcommand {
subcommand: sub.to_string(), subcommand: sub.to_string(),
@@ -690,10 +695,10 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
// === Frame === // === Frame ===
"frame" => { "frame" => {
if rest.get(0).map(|s| *s) == Some("main") { if rest.first().copied() == Some("main") {
Ok(json!({ "id": id, "action": "mainframe" })) Ok(json!({ "id": id, "action": "mainframe" }))
} else { } else {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let sel = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "frame".to_string(), context: "frame".to_string(),
usage: "frame <selector|main>", usage: "frame <selector|main>",
})?; })?;
@@ -704,7 +709,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
// === Dialog === // === Dialog ===
"dialog" => { "dialog" => {
const VALID: &[&str] = &["accept", "dismiss"]; const VALID: &[&str] = &["accept", "dismiss"];
match rest.get(0).map(|s| *s) { match rest.first().copied() {
Some("accept") => { Some("accept") => {
let mut cmd = json!({ "id": id, "action": "dialog", "response": "accept" }); let mut cmd = json!({ "id": id, "action": "dialog", "response": "accept" });
if let Some(prompt_text) = rest.get(1) { if let Some(prompt_text) = rest.get(1) {
@@ -726,7 +731,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
// === Debug === // === Debug ===
"trace" => { "trace" => {
const VALID: &[&str] = &["start", "stop"]; const VALID: &[&str] = &["start", "stop"];
match rest.get(0).map(|s| *s) { match rest.first().copied() {
Some("start") => Ok(json!({ "id": id, "action": "trace_start" })), Some("start") => Ok(json!({ "id": id, "action": "trace_start" })),
Some("stop") => { Some("stop") => {
let path = rest.get(1).ok_or_else(|| ParseError::MissingArguments { let path = rest.get(1).ok_or_else(|| ParseError::MissingArguments {
@@ -749,7 +754,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
// === Recording (Playwright native video recording) === // === Recording (Playwright native video recording) ===
"record" => { "record" => {
const VALID: &[&str] = &["start", "stop", "restart"]; const VALID: &[&str] = &["start", "stop", "restart"];
match rest.get(0).map(|s| *s) { match rest.first().copied() {
Some("start") => { Some("start") => {
let path = rest.get(1).ok_or_else(|| ParseError::MissingArguments { let path = rest.get(1).ok_or_else(|| ParseError::MissingArguments {
context: "record start".to_string(), context: "record start".to_string(),
@@ -800,15 +805,15 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
} }
} }
"console" => { "console" => {
let clear = rest.iter().any(|&s| s == "--clear"); let clear = rest.contains(&"--clear");
Ok(json!({ "id": id, "action": "console", "clear": clear })) Ok(json!({ "id": id, "action": "console", "clear": clear }))
} }
"errors" => { "errors" => {
let clear = rest.iter().any(|&s| s == "--clear"); let clear = rest.contains(&"--clear");
Ok(json!({ "id": id, "action": "errors", "clear": clear })) Ok(json!({ "id": id, "action": "errors", "clear": clear }))
} }
"highlight" => { "highlight" => {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let sel = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "highlight".to_string(), context: "highlight".to_string(),
usage: "highlight <selector>", usage: "highlight <selector>",
})?; })?;
@@ -818,7 +823,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
// === State === // === State ===
"state" => { "state" => {
const VALID: &[&str] = &["save", "load"]; const VALID: &[&str] = &["save", "load"];
match rest.get(0).map(|s| *s) { match rest.first().copied() {
Some("save") => { Some("save") => {
let path = rest.get(1).ok_or_else(|| ParseError::MissingArguments { let path = rest.get(1).ok_or_else(|| ParseError::MissingArguments {
context: "state save".to_string(), context: "state save".to_string(),
@@ -847,14 +852,14 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
// === iOS-specific commands === // === iOS-specific commands ===
"tap" => { "tap" => {
// Alias for click (semantic clarity for touch interfaces) // Alias for click (semantic clarity for touch interfaces)
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let sel = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "tap".to_string(), context: "tap".to_string(),
usage: "tap <selector>", usage: "tap <selector>",
})?; })?;
Ok(json!({ "id": id, "action": "tap", "selector": sel })) Ok(json!({ "id": id, "action": "tap", "selector": sel }))
} }
"swipe" => { "swipe" => {
let direction = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let direction = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "swipe".to_string(), context: "swipe".to_string(),
usage: "swipe <up|down|left|right> [distance]", usage: "swipe <up|down|left|right> [distance]",
})?; })?;
@@ -868,13 +873,15 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
let mut cmd = json!({ "id": id, "action": "swipe", "direction": direction }); let mut cmd = json!({ "id": id, "action": "swipe", "direction": direction });
if let Some(distance) = rest.get(1) { if let Some(distance) = rest.get(1) {
if let Ok(d) = distance.parse::<u32>() { if let Ok(d) = distance.parse::<u32>() {
cmd.as_object_mut().unwrap().insert("distance".to_string(), json!(d)); cmd.as_object_mut()
.unwrap()
.insert("distance".to_string(), json!(d));
} }
} }
Ok(cmd) Ok(cmd)
} }
"device" => { "device" => {
match rest.get(0).map(|s| *s) { match rest.first().copied() {
Some("list") | None => { Some("list") | None => {
// List available iOS simulators // List available iOS simulators
Ok(json!({ "id": id, "action": "device_list" })) Ok(json!({ "id": id, "action": "device_list" }))
@@ -897,7 +904,7 @@ fn parse_get(rest: &[&str], id: &str) -> Result<Value, ParseError> {
"text", "html", "value", "attr", "url", "title", "count", "box", "styles", "text", "html", "value", "attr", "url", "title", "count", "box", "styles",
]; ];
match rest.get(0).map(|s| *s) { match rest.first().copied() {
Some("text") => { Some("text") => {
let sel = rest.get(1).ok_or_else(|| ParseError::MissingArguments { let sel = rest.get(1).ok_or_else(|| ParseError::MissingArguments {
context: "get text".to_string(), context: "get text".to_string(),
@@ -967,7 +974,7 @@ fn parse_get(rest: &[&str], id: &str) -> Result<Value, ParseError> {
fn parse_is(rest: &[&str], id: &str) -> Result<Value, ParseError> { fn parse_is(rest: &[&str], id: &str) -> Result<Value, ParseError> {
const VALID: &[&str] = &["visible", "enabled", "checked"]; const VALID: &[&str] = &["visible", "enabled", "checked"];
match rest.get(0).map(|s| *s) { match rest.first().copied() {
Some("visible") => { Some("visible") => {
let sel = rest.get(1).ok_or_else(|| ParseError::MissingArguments { let sel = rest.get(1).ok_or_else(|| ParseError::MissingArguments {
context: "is visible".to_string(), context: "is visible".to_string(),
@@ -1014,14 +1021,14 @@ fn parse_find(rest: &[&str], id: &str) -> Result<Value, ParseError> {
"nth", "nth",
]; ];
let locator = rest.get(0).ok_or_else(|| ParseError::MissingArguments { let locator = rest.first().ok_or_else(|| ParseError::MissingArguments {
context: "find".to_string(), context: "find".to_string(),
usage: "find <locator> <value> [action] [text]", usage: "find <locator> <value> [action] [text]",
})?; })?;
let name_idx = rest.iter().position(|&s| s == "--name"); let name_idx = rest.iter().position(|&s| s == "--name");
let name = name_idx.and_then(|i| rest.get(i + 1).map(|s| *s)); let name = name_idx.and_then(|i| rest.get(i + 1).copied());
let exact = rest.iter().any(|&s| s == "--exact"); let exact = rest.contains(&"--exact");
match *locator { match *locator {
"role" | "text" | "label" | "placeholder" | "alt" | "title" | "testid" | "first" "role" | "text" | "label" | "placeholder" | "alt" | "title" | "testid" | "first"
@@ -1140,7 +1147,7 @@ fn parse_find(rest: &[&str], id: &str) -> Result<Value, ParseError> {
fn parse_mouse(rest: &[&str], id: &str) -> Result<Value, ParseError> { fn parse_mouse(rest: &[&str], id: &str) -> Result<Value, ParseError> {
const VALID: &[&str] = &["move", "down", "up", "wheel"]; const VALID: &[&str] = &["move", "down", "up", "wheel"];
match rest.get(0).map(|s| *s) { match rest.first().copied() {
Some("move") => { Some("move") => {
let x_str = rest.get(1).ok_or_else(|| ParseError::MissingArguments { let x_str = rest.get(1).ok_or_else(|| ParseError::MissingArguments {
context: "mouse move".to_string(), context: "mouse move".to_string(),
@@ -1202,7 +1209,7 @@ fn parse_set(rest: &[&str], id: &str) -> Result<Value, ParseError> {
"media", "media",
]; ];
match rest.get(0).map(|s| *s) { match rest.first().copied() {
Some("viewport") => { Some("viewport") => {
let w_str = rest.get(1).ok_or_else(|| ParseError::MissingArguments { let w_str = rest.get(1).ok_or_else(|| ParseError::MissingArguments {
context: "set viewport".to_string(), context: "set viewport".to_string(),
@@ -1288,14 +1295,14 @@ fn parse_set(rest: &[&str], id: &str) -> Result<Value, ParseError> {
Ok(json!({ "id": id, "action": "credentials", "username": user, "password": pass })) Ok(json!({ "id": id, "action": "credentials", "username": user, "password": pass }))
} }
Some("media") => { Some("media") => {
let color = if rest.iter().any(|&s| s == "dark") { let color = if rest.contains(&"dark") {
"dark" "dark"
} else if rest.iter().any(|&s| s == "light") { } else if rest.contains(&"light") {
"light" "light"
} else { } else {
"no-preference" "no-preference"
}; };
let reduced = if rest.iter().any(|&s| s == "reduced-motion") { let reduced = if rest.contains(&"reduced-motion") {
"reduce" "reduce"
} else { } else {
"no-preference" "no-preference"
@@ -1318,15 +1325,15 @@ fn parse_set(rest: &[&str], id: &str) -> Result<Value, ParseError> {
fn parse_network(rest: &[&str], id: &str) -> Result<Value, ParseError> { fn parse_network(rest: &[&str], id: &str) -> Result<Value, ParseError> {
const VALID: &[&str] = &["route", "unroute", "requests"]; const VALID: &[&str] = &["route", "unroute", "requests"];
match rest.get(0).map(|s| *s) { match rest.first().copied() {
Some("route") => { Some("route") => {
let url = rest.get(1).ok_or_else(|| ParseError::MissingArguments { let url = rest.get(1).ok_or_else(|| ParseError::MissingArguments {
context: "network route".to_string(), context: "network route".to_string(),
usage: "network route <url> [--abort|--body <json>]", usage: "network route <url> [--abort|--body <json>]",
})?; })?;
let abort = rest.iter().any(|&s| s == "--abort"); let abort = rest.contains(&"--abort");
let body_idx = rest.iter().position(|&s| s == "--body"); let body_idx = rest.iter().position(|&s| s == "--body");
let body = body_idx.and_then(|i| rest.get(i + 1).map(|s| *s)); let body = body_idx.and_then(|i| rest.get(i + 1).copied());
Ok(json!({ "id": id, "action": "route", "url": url, "abort": abort, "body": body })) Ok(json!({ "id": id, "action": "route", "url": url, "abort": abort, "body": body }))
} }
Some("unroute") => { Some("unroute") => {
@@ -1337,9 +1344,9 @@ fn parse_network(rest: &[&str], id: &str) -> Result<Value, ParseError> {
Ok(cmd) Ok(cmd)
} }
Some("requests") => { Some("requests") => {
let clear = rest.iter().any(|&s| s == "--clear"); let clear = rest.contains(&"--clear");
let filter_idx = rest.iter().position(|&s| s == "--filter"); let filter_idx = rest.iter().position(|&s| s == "--filter");
let filter = filter_idx.and_then(|i| rest.get(i + 1).map(|s| *s)); let filter = filter_idx.and_then(|i| rest.get(i + 1).copied());
let mut cmd = json!({ "id": id, "action": "requests", "clear": clear }); let mut cmd = json!({ "id": id, "action": "requests", "clear": clear });
if let Some(f) = filter { if let Some(f) = filter {
cmd["filter"] = json!(f); cmd["filter"] = json!(f);
@@ -1360,9 +1367,9 @@ fn parse_network(rest: &[&str], id: &str) -> Result<Value, ParseError> {
fn parse_storage(rest: &[&str], id: &str) -> Result<Value, ParseError> { fn parse_storage(rest: &[&str], id: &str) -> Result<Value, ParseError> {
const VALID: &[&str] = &["local", "session"]; const VALID: &[&str] = &["local", "session"];
match rest.get(0).map(|s| *s) { match rest.first().copied() {
Some("local") | Some("session") => { Some("local") | Some("session") => {
let storage_type = rest.get(0).unwrap(); let storage_type = rest.first().unwrap();
let op = rest.get(1).unwrap_or(&"get"); let op = rest.get(1).unwrap_or(&"get");
let key = rest.get(2); let key = rest.get(2);
let value = rest.get(3); let value = rest.get(3);
@@ -2159,8 +2166,11 @@ mod tests {
#[test] #[test]
fn test_eval_base64_long_flag() { fn test_eval_base64_long_flag() {
// "document.title" in base64 // "document.title" in base64
let cmd = let cmd = parse_command(
parse_command(&args("eval --base64 ZG9jdW1lbnQudGl0bGU="), &default_flags()).unwrap(); &args("eval --base64 ZG9jdW1lbnQudGl0bGU="),
&default_flags(),
)
.unwrap();
assert_eq!(cmd["action"], "evaluate"); assert_eq!(cmd["action"], "evaluate");
assert_eq!(cmd["script"], "document.title"); assert_eq!(cmd["script"], "document.title");
} }
+1
View File
@@ -203,6 +203,7 @@ pub struct DaemonResult {
pub already_running: bool, pub already_running: bool,
} }
#[allow(clippy::too_many_arguments)]
pub fn ensure_daemon( pub fn ensure_daemon(
session: &str, session: &str,
headed: bool, headed: bool,
+7 -14
View File
@@ -10,9 +10,6 @@ use std::env;
use std::fs; use std::fs;
use std::process::exit; use std::process::exit;
#[cfg(unix)]
use libc;
#[cfg(windows)] #[cfg(windows)]
use windows_sys::Win32::Foundation::CloseHandle; use windows_sys::Win32::Foundation::CloseHandle;
#[cfg(windows)] #[cfg(windows)]
@@ -141,7 +138,7 @@ fn main() {
let has_version = args.iter().any(|a| a == "--version" || a == "-V"); let has_version = args.iter().any(|a| a == "--version" || a == "-V");
if has_help { if has_help {
if let Some(cmd) = clean.get(0) { if let Some(cmd) = clean.first() {
if print_command_help(cmd) { if print_command_help(cmd) {
return; return;
} }
@@ -161,14 +158,14 @@ fn main() {
} }
// Handle install separately // Handle install separately
if clean.get(0).map(|s| s.as_str()) == Some("install") { if clean.first().map(|s| s.as_str()) == Some("install") {
let with_deps = args.iter().any(|a| a == "--with-deps" || a == "-d"); let with_deps = args.iter().any(|a| a == "--with-deps" || a == "-d");
run_install(with_deps); run_install(with_deps);
return; return;
} }
// Handle session separately (doesn't need daemon) // Handle session separately (doesn't need daemon)
if clean.get(0).map(|s| s.as_str()) == Some("session") { if clean.first().map(|s| s.as_str()) == Some("session") {
run_session(&clean, &flags.session, flags.json); run_session(&clean, &flags.session, flags.json);
return; return;
} }
@@ -247,11 +244,7 @@ fn main() {
} else { } else {
None None
}, },
if flags.cli_args { if flags.cli_args { Some("--args") } else { None },
Some("--args")
} else {
None
},
if flags.cli_user_agent { if flags.cli_user_agent {
Some("--user-agent") Some("--user-agent")
} else { } else {
@@ -267,8 +260,8 @@ fn main() {
} else { } else {
None None
}, },
flags.ignore_https_errors.then(|| "--ignore-https-errors"), flags.ignore_https_errors.then_some("--ignore-https-errors"),
flags.cli_allow_file_access.then(|| "--allow-file-access"), flags.cli_allow_file_access.then_some("--allow-file-access"),
] ]
.into_iter() .into_iter()
.flatten() .flatten()
@@ -372,7 +365,7 @@ fn main() {
} else { } else {
// It's a port number - validate and use cdpPort field // It's a port number - validate and use cdpPort field
let cdp_port: u16 = match cdp_value.parse::<u32>() { let cdp_port: u16 = match cdp_value.parse::<u32>() {
Ok(p) if p == 0 => { Ok(0) => {
let msg = "Invalid CDP port: port must be greater than 0".to_string(); let msg = "Invalid CDP port: port must be greater than 0".to_string();
if flags.json { if flags.json {
println!(r#"{{"success":false,"error":"{}"}}"#, msg); println!(r#"{{"success":false,"error":"{}"}}"#, msg);
+22 -5
View File
@@ -88,17 +88,28 @@ pub fn print_response(resp: &Response, json_mode: bool, action: Option<&str>) {
// Separate real devices from simulators // Separate real devices from simulators
let real_devices: Vec<_> = devices let real_devices: Vec<_> = devices
.iter() .iter()
.filter(|d| d.get("isRealDevice").and_then(|v| v.as_bool()).unwrap_or(false)) .filter(|d| {
d.get("isRealDevice")
.and_then(|v| v.as_bool())
.unwrap_or(false)
})
.collect(); .collect();
let simulators: Vec<_> = devices let simulators: Vec<_> = devices
.iter() .iter()
.filter(|d| !d.get("isRealDevice").and_then(|v| v.as_bool()).unwrap_or(false)) .filter(|d| {
!d.get("isRealDevice")
.and_then(|v| v.as_bool())
.unwrap_or(false)
})
.collect(); .collect();
if !real_devices.is_empty() { if !real_devices.is_empty() {
println!("Connected Devices:\n"); println!("Connected Devices:\n");
for device in real_devices.iter() { for device in real_devices.iter() {
let name = device.get("name").and_then(|v| v.as_str()).unwrap_or("Unknown"); let name = device
.get("name")
.and_then(|v| v.as_str())
.unwrap_or("Unknown");
let runtime = device.get("runtime").and_then(|v| v.as_str()).unwrap_or(""); let runtime = device.get("runtime").and_then(|v| v.as_str()).unwrap_or("");
let udid = device.get("udid").and_then(|v| v.as_str()).unwrap_or(""); let udid = device.get("udid").and_then(|v| v.as_str()).unwrap_or("");
println!(" {} {} ({})", color::green(""), name, runtime); println!(" {} {} ({})", color::green(""), name, runtime);
@@ -110,9 +121,15 @@ pub fn print_response(resp: &Response, json_mode: bool, action: Option<&str>) {
if !simulators.is_empty() { if !simulators.is_empty() {
println!("Simulators:\n"); println!("Simulators:\n");
for device in simulators.iter() { for device in simulators.iter() {
let name = device.get("name").and_then(|v| v.as_str()).unwrap_or("Unknown"); let name = device
.get("name")
.and_then(|v| v.as_str())
.unwrap_or("Unknown");
let runtime = device.get("runtime").and_then(|v| v.as_str()).unwrap_or(""); let runtime = device.get("runtime").and_then(|v| v.as_str()).unwrap_or("");
let state = device.get("state").and_then(|v| v.as_str()).unwrap_or("Unknown"); let state = device
.get("state")
.and_then(|v| v.as_str())
.unwrap_or("Unknown");
let udid = device.get("udid").and_then(|v| v.as_str()).unwrap_or(""); let udid = device.get("udid").and_then(|v| v.as_str()).unwrap_or("");
let state_indicator = if state == "Booted" { let state_indicator = if state == "Booted" {
color::green("") color::green("")