Fix CLI/protocol mismatches for select, frame main, and headers (#45)

* fix: align CLI command payloads with protocol

* fix(cli): support multi-value select in CLI
This commit is contained in:
Nicenonecb
2026-01-17 20:25:19 -06:00
committed by GitHub
parent 4112234371
commit 28740acecf
4 changed files with 57 additions and 8 deletions
+36 -5
View File
@@ -153,13 +153,18 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
"select" => {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments {
context: "select".to_string(),
usage: "select <selector> <value>",
usage: "select <selector> <value...>",
})?;
let val = rest.get(1).ok_or_else(|| ParseError::MissingArguments {
let _val = rest.get(1).ok_or_else(|| ParseError::MissingArguments {
context: "select".to_string(),
usage: "select <selector> <value>",
usage: "select <selector> <value...>",
})?;
Ok(json!({ "id": id, "action": "select", "selector": sel, "value": val }))
let values = &rest[1..];
if values.len() == 1 {
Ok(json!({ "id": id, "action": "select", "selector": sel, "values": values[0] }))
} else {
Ok(json!({ "id": id, "action": "select", "selector": sel, "values": values }))
}
}
"drag" => {
let src = rest.get(0).ok_or_else(|| ParseError::MissingArguments {
@@ -408,7 +413,7 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
// === Frame ===
"frame" => {
if rest.get(0).map(|s| *s) == Some("main") {
Ok(json!({ "id": id, "action": "frame_main" }))
Ok(json!({ "id": id, "action": "mainframe" }))
} else {
let sel = rest.get(0).ok_or_else(|| ParseError::MissingArguments {
context: "frame".to_string(),
@@ -1249,6 +1254,32 @@ mod tests {
assert_eq!(cmd["text"], "some text");
}
#[test]
fn test_select() {
let cmd = parse_command(&args("select #menu option1"), &default_flags()).unwrap();
assert_eq!(cmd["action"], "select");
assert_eq!(cmd["selector"], "#menu");
assert_eq!(cmd["values"], "option1");
}
#[test]
fn test_select_multiple_values() {
let cmd = parse_command(
&args("select #menu opt1 opt2 opt3"),
&default_flags(),
)
.unwrap();
assert_eq!(cmd["action"], "select");
assert_eq!(cmd["selector"], "#menu");
assert_eq!(cmd["values"], json!(["opt1", "opt2", "opt3"]));
}
#[test]
fn test_frame_main() {
let cmd = parse_command(&args("frame main"), &default_flags()).unwrap();
assert_eq!(cmd["action"], "mainframe");
}
// === Tabs ===
#[test]
+4 -3
View File
@@ -423,9 +423,9 @@ Examples:
"select" => r##"
agent-browser select - Select a dropdown option
Usage: agent-browser select <selector> <value>
Usage: agent-browser select <selector> <value...>
Selects an option in a <select> dropdown by its value attribute.
Selects one or more options in a <select> dropdown by value.
Global Options:
--json Output as JSON
@@ -434,6 +434,7 @@ Global Options:
Examples:
agent-browser select "#country" "US"
agent-browser select @e5 "option2"
agent-browser select "#menu" "opt1" "opt2" "opt3"
"##,
"drag" => r##"
agent-browser drag - Drag and drop
@@ -1233,7 +1234,7 @@ Core Commands:
focus <sel> Focus element
check <sel> Check checkbox
uncheck <sel> Uncheck checkbox
select <sel> <val> Select dropdown option
select <sel> <val...> Select dropdown option
drag <src> <dst> Drag and drop
upload <sel> <files...> Upload files
scroll <dir> [px] Scroll (up/down/left/right)
+16
View File
@@ -15,6 +15,22 @@ describe('parseCommand', () => {
}
});
it('should parse navigate with headers', () => {
const result = parseCommand(
cmd({
id: '1',
action: 'navigate',
url: 'https://example.com',
headers: { Authorization: 'Bearer token' },
})
);
expect(result.success).toBe(true);
if (result.success) {
expect(result.command.action).toBe('navigate');
expect(result.command.headers).toEqual({ Authorization: 'Bearer token' });
}
});
it('should reject navigate without url', () => {
const result = parseCommand(cmd({ id: '1', action: 'navigate' }));
expect(result.success).toBe(false);
+1
View File
@@ -36,6 +36,7 @@ const navigateSchema = baseCommandSchema.extend({
action: z.literal('navigate'),
url: z.string().min(1),
waitUntil: z.enum(['load', 'domcontentloaded', 'networkidle']).optional(),
headers: z.record(z.string()).optional(),
});
const clickSchema = baseCommandSchema.extend({