fix: support accessibility tree refs in upload command (#1156)

* fix: support accessibility tree refs in upload command (#1107)

The upload command only accepted CSS selectors while click/fill supported
accessibility tree refs (e.g. e1, @e1, ref=e1). This resolves the API
inconsistency by reusing resolve_element_object_id for all selector types.

* style: apply cargo fmt

---------

Co-authored-by: hyunjinee <leehj0110@kakao.com>
This commit is contained in:
jin.2
2026-04-05 15:38:49 -05:00
committed by GitHub
co-authored by hyunjinee
parent c47756be9b
commit fcb6615f5a
4 changed files with 128 additions and 42 deletions
+94
View File
@@ -34,6 +34,7 @@ fn native_test_fixture_html(name: &str) -> &'static str {
"drag_probe" => include_str!("test_fixtures/drag_probe.html"),
"html5_drag_probe" => include_str!("test_fixtures/html5_drag_probe.html"),
"pointer_capture_probe" => include_str!("test_fixtures/pointer_capture_probe.html"),
"upload_probe" => include_str!("test_fixtures/upload_probe.html"),
_ => panic!("Unknown native test fixture: {}", name),
}
}
@@ -3884,3 +3885,96 @@ async fn e2e_relaunch_on_options_change() {
let resp = execute_command(&json!({ "id": "99", "action": "close" }), &mut state).await;
assert_success(&resp);
}
// ---------------------------------------------------------------------------
// Upload: ref-based selector support (issue #1107)
// ---------------------------------------------------------------------------
#[tokio::test]
#[ignore]
async fn e2e_upload_with_ref_selector() {
let mut state = DaemonState::new();
let resp = execute_command(
&json!({ "id": "1", "action": "launch", "headless": true }),
&mut state,
)
.await;
assert_success(&resp);
let resp = execute_command(
&json!({ "id": "2", "action": "navigate", "url": native_test_fixture_url("upload_probe") }),
&mut state,
)
.await;
assert_success(&resp);
let resp = execute_command(&json!({ "id": "3", "action": "snapshot" }), &mut state).await;
assert_success(&resp);
let snapshot = get_data(&resp)["snapshot"].as_str().unwrap();
// Match by label text, not by role which may vary across Chrome versions
let file_input_ref = snapshot
.lines()
.filter_map(|line| {
if line.contains("Choose file") && line.contains("ref=") {
let start = line.find("ref=")? + 4;
let end = line[start..].find(']')? + start;
Some(line[start..end].to_string())
} else {
None
}
})
.next()
.expect("Snapshot should contain the file input with a ref");
let tmp = std::env::temp_dir().join(format!("ab-upload-ref-{}.txt", std::process::id()));
std::fs::write(&tmp, "test").unwrap();
let resp = execute_command(
&json!({ "id": "4", "action": "upload", "selector": file_input_ref, "files": [tmp.to_string_lossy()] }),
&mut state,
)
.await;
assert_success(&resp);
assert_eq!(get_data(&resp)["uploaded"], 1);
let _ = std::fs::remove_file(&tmp);
let resp = execute_command(&json!({ "id": "99", "action": "close" }), &mut state).await;
assert_success(&resp);
}
#[tokio::test]
#[ignore]
async fn e2e_upload_with_css_selector() {
let mut state = DaemonState::new();
let resp = execute_command(
&json!({ "id": "1", "action": "launch", "headless": true }),
&mut state,
)
.await;
assert_success(&resp);
let resp = execute_command(
&json!({ "id": "2", "action": "navigate", "url": native_test_fixture_url("upload_probe") }),
&mut state,
)
.await;
assert_success(&resp);
let tmp = std::env::temp_dir().join(format!("ab-upload-css-{}.txt", std::process::id()));
std::fs::write(&tmp, "test").unwrap();
let resp = execute_command(
&json!({ "id": "3", "action": "upload", "selector": "#fileInput", "files": [tmp.to_string_lossy()] }),
&mut state,
)
.await;
assert_success(&resp);
assert_eq!(get_data(&resp)["uploaded"], 1);
let _ = std::fs::remove_file(&tmp);
let resp = execute_command(&json!({ "id": "99", "action": "close" }), &mut state).await;
assert_success(&resp);
}