Skip to content

Commit dba3300

Browse files
authored
Update utils.py to fix names for input fields
1 parent 6650346 commit dba3300

1 file changed

Lines changed: 66 additions & 0 deletions

File tree

stagehand/a11y/utils.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,51 @@ async def build_hierarchical_tree(
222222
"idToUrl": id_to_url,
223223
}
224224

225+
async def get_accessibility_node_name(page: "StagehandPage", node: AccessibilityNode) -> str:
226+
"""Gets the name of an accessibility node."""
227+
name = node.get("name")
228+
if name and name.get("value"):
229+
return name
230+
231+
nodeId = node.get("nodeId")
232+
if not nodeId:
233+
return None
234+
235+
nodeId = int(nodeId)
236+
237+
args = {"backendNodeId": nodeId}
238+
response = await page.send_cdp("DOM.resolveNode", args)
239+
object_id = response.get("object", {}).get("objectId")
240+
241+
xpath = await get_xpath_by_resolved_object_id(page._cdp_client, object_id)
242+
if not xpath:
243+
return None
244+
245+
locator = page.locator(f"xpath={xpath}")
246+
if not locator:
247+
return None
248+
249+
name_value = await locator.get_attribute("name")
250+
if name_value:
251+
return {"value": name_value, "type": "string"}
252+
253+
aria_label_value = await locator.get_attribute("aria-label")
254+
if aria_label_value:
255+
return {"value": aria_label_value, "type": "string"}
256+
257+
id_value = await locator.get_attribute("id")
258+
if id_value:
259+
return {"value": id_value, "type": "string"}
260+
261+
placeholder_value = await locator.get_attribute("placeholder")
262+
if placeholder_value:
263+
return {"value": placeholder_value, "type": "string"}
264+
265+
title_value = await locator.get_attribute("title")
266+
if title_value:
267+
return {"value": title_value, "type": "string"}
268+
269+
return None
225270

226271
async def get_accessibility_tree(
227272
page: "StagehandPage",
@@ -254,6 +299,27 @@ async def get_accessibility_tree(
254299
"value": new_role,
255300
} # Create role if missing
256301

302+
# Process accessibility node names in parallel after the main loop
303+
async def get_node_name_with_timeout(node_data):
304+
try:
305+
if "ignored" in node_data and not node_data["ignored"]:
306+
node_name = await asyncio.wait_for(get_accessibility_node_name(page, node_data), timeout=0.5)
307+
if node_name and ("name" not in node_data or (not node_data["name"].get("value"))):
308+
node_data["name"] = node_name
309+
except asyncio.TimeoutError:
310+
logger.debug(
311+
message=f"Timeout getting accessibility node name for node {node_data.get('nodeId')}",
312+
auxiliary={"error": {"value": "Timeout after 0.5 seconds", "type": "string"}},
313+
)
314+
except Exception as e:
315+
logger.debug(
316+
message=f"Error getting accessibility node name for node {node_data.get('nodeId')}",
317+
auxiliary={"error": {"value": str(e), "type": "string"}},
318+
)
319+
320+
# Run all node name retrievals in parallel
321+
await asyncio.gather(*[get_node_name_with_timeout(node_data) for node_data in nodes], return_exceptions=True)
322+
257323
hierarchical_tree = await build_hierarchical_tree(nodes, page, logger)
258324

259325
end_time = time.time()

0 commit comments

Comments
 (0)