diff --git a/README.md b/README.md index 3a4fb45..4e2702c 100644 --- a/README.md +++ b/README.md @@ -131,8 +131,14 @@ agent-browser find nth 2 "a" text ```bash agent-browser wait # Wait for element to be visible agent-browser wait # Wait for time (milliseconds) +agent-browser wait --text "Welcome" # Wait for text to appear +agent-browser wait --url "**/dash" # Wait for URL pattern +agent-browser wait --load networkidle # Wait for load state +agent-browser wait --fn "window.ready === true" # Wait for JS condition ``` +**Load states:** `load`, `domcontentloaded`, `networkidle` + ### Mouse Control ```bash diff --git a/cli/src/commands.rs b/cli/src/commands.rs index 9134397..8b8ff58 100644 --- a/cli/src/commands.rs +++ b/cli/src/commands.rs @@ -212,6 +212,41 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result { + // Check for --url flag: wait --url "**/dashboard" + if let Some(idx) = rest.iter().position(|&s| s == "--url" || s == "-u") { + let url = rest.get(idx + 1).ok_or_else(|| ParseError::MissingArguments { + context: "wait --url".to_string(), + usage: "wait --url ", + })?; + return Ok(json!({ "id": id, "action": "waitforurl", "url": url })); + } + + // Check for --load flag: wait --load networkidle + if let Some(idx) = rest.iter().position(|&s| s == "--load" || s == "-l") { + let state = rest.get(idx + 1).unwrap_or(&"load"); + return Ok(json!({ "id": id, "action": "waitforloadstate", "state": state })); + } + + // Check for --fn flag: wait --fn "window.ready === true" + if let Some(idx) = rest.iter().position(|&s| s == "--fn" || s == "-f") { + let expr = rest.get(idx + 1).ok_or_else(|| ParseError::MissingArguments { + context: "wait --fn".to_string(), + usage: "wait --fn ", + })?; + return Ok(json!({ "id": id, "action": "waitforfunction", "expression": expr })); + } + + // Check for --text flag: wait --text "Welcome" + if let Some(idx) = rest.iter().position(|&s| s == "--text" || s == "-t") { + let text = rest.get(idx + 1).ok_or_else(|| ParseError::MissingArguments { + context: "wait --text".to_string(), + usage: "wait --text ", + })?; + // Use getByText locator to wait for text to appear + return Ok(json!({ "id": id, "action": "wait", "selector": format!("text={}", text) })); + } + + // Default: selector or timeout if let Some(arg) = rest.get(0) { if arg.parse::().is_ok() { Ok(json!({ "id": id, "action": "wait", "timeout": arg.parse::().unwrap() })) @@ -221,7 +256,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result", + usage: "wait ", }) } } @@ -1090,6 +1125,50 @@ mod tests { assert_eq!(cmd["maxDepth"], 3); } + // === Wait === + + #[test] + fn test_wait_selector() { + let cmd = parse_command(&args("wait #element"), &default_flags()).unwrap(); + assert_eq!(cmd["action"], "wait"); + assert_eq!(cmd["selector"], "#element"); + } + + #[test] + fn test_wait_timeout() { + let cmd = parse_command(&args("wait 5000"), &default_flags()).unwrap(); + assert_eq!(cmd["action"], "wait"); + assert_eq!(cmd["timeout"], 5000); + } + + #[test] + fn test_wait_url() { + let cmd = parse_command(&args("wait --url **/dashboard"), &default_flags()).unwrap(); + assert_eq!(cmd["action"], "waitforurl"); + assert_eq!(cmd["url"], "**/dashboard"); + } + + #[test] + fn test_wait_load() { + let cmd = parse_command(&args("wait --load networkidle"), &default_flags()).unwrap(); + assert_eq!(cmd["action"], "waitforloadstate"); + assert_eq!(cmd["state"], "networkidle"); + } + + #[test] + fn test_wait_fn() { + let cmd = parse_command(&args("wait --fn window.ready"), &default_flags()).unwrap(); + assert_eq!(cmd["action"], "waitforfunction"); + assert_eq!(cmd["expression"], "window.ready"); + } + + #[test] + fn test_wait_text() { + let cmd = parse_command(&args("wait --text Welcome"), &default_flags()).unwrap(); + assert_eq!(cmd["action"], "wait"); + assert_eq!(cmd["selector"], "text=Welcome"); + } + // === Unknown command === #[test]