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
+14 -41
View File
@@ -1,5 +1,5 @@
use serde_json::{json, Value};
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};
use std::future::Future;
use std::sync::Arc;
use std::time::{Duration, Instant};
@@ -10,6 +10,7 @@ use super::cdp::client::CdpClient;
use super::cdp::discovery::discover_cdp_url;
use super::cdp::lightpanda::{launch_lightpanda, LightpandaLaunchOptions, LightpandaProcess};
use super::cdp::types::*;
use super::element::{resolve_element_object_id, RefMap};
// ---------------------------------------------------------------------------
// Launch validation
@@ -1091,50 +1092,25 @@ impl BrowserManager {
Ok(())
}
pub async fn upload_files(&self, selector: &str, files: &[String]) -> Result<(), String> {
pub async fn upload_files(
&self,
selector: &str,
files: &[String],
ref_map: &RefMap,
iframe_sessions: &HashMap<String, String>,
) -> Result<(), String> {
let session_id = self.active_session_id()?;
let node_result = self
.client
.send_command(
"DOM.querySelector",
Some(json!({
"nodeId": 1,
"selector": selector,
})),
Some(session_id),
)
.await;
let (object_id, effective_session_id) =
resolve_element_object_id(&self.client, session_id, ref_map, selector, iframe_sessions)
.await?;
// Alternative: resolve via JS
let result: EvaluateResult = self
.client
.send_command_typed(
"Runtime.evaluate",
&EvaluateParams {
expression: format!(
"document.querySelector({})",
serde_json::to_string(selector).unwrap_or_default()
),
return_by_value: Some(false),
await_promise: Some(false),
},
Some(session_id),
)
.await?;
let object_id = result
.result
.object_id
.ok_or("File input element not found")?;
// Get the DOM node from the remote object
let describe: Value = self
.client
.send_command(
"DOM.describeNode",
Some(json!({ "objectId": object_id })),
Some(session_id),
Some(&effective_session_id),
)
.await?;
@@ -1144,9 +1120,6 @@ impl BrowserManager {
.and_then(|v| v.as_i64())
.ok_or("Could not get backendNodeId for file input")?;
// Suppress unused variable warning
let _ = node_result;
self.client
.send_command(
"DOM.setFileInputFiles",
@@ -1154,7 +1127,7 @@ impl BrowserManager {
"files": files,
"backendNodeId": backend_node_id,
})),
Some(session_id),
Some(&effective_session_id),
)
.await?;