From ba6ef89b35971dedb19293cb3537b7d2bf30edde Mon Sep 17 00:00:00 2001 From: LawyZheng Date: Wed, 16 Oct 2024 19:23:12 +0800 Subject: [PATCH] custom select optimize (#985) --- skyvern/webeye/actions/handler.py | 20 +++++++++++++++++++- skyvern/webeye/utils/dom.py | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/skyvern/webeye/actions/handler.py b/skyvern/webeye/actions/handler.py index fb8c3a1e..54c7584a 100644 --- a/skyvern/webeye/actions/handler.py +++ b/skyvern/webeye/actions/handler.py @@ -451,7 +451,18 @@ async def handle_input_text_action( # press arrowdown to watch if there's any options popping up await incremental_scraped.start_listen_dom_increment() - await skyvern_element.press_key("ArrowDown") + try: + await skyvern_element.press_key("ArrowDown") + except TimeoutError: + # sometimes we notice `press_key()` raise a timeout but actually the dropdown is opened. + LOG.info( + "Timeout to press ArrowDown to open dropdown, ignore the timeout and continue to execute the action", + task_id=task.task_id, + step_id=step.step_id, + element_id=skyvern_element.get_id(), + action=action, + ) + await asyncio.sleep(5) incremental_element = await incremental_scraped.get_incremental_element_tree( @@ -677,6 +688,13 @@ async def handle_select_option_action( element_dict=element_dict, ) + # Handle the edge case: + # Sometimes our custom select logic could fail, and leaving the dropdown being opened. + # Confirm if the select action is on the custom option element + if await skyvern_element.is_custom_option(): + click_action = ClickAction(element_id=action.element_id) + return await chain_click(task, scraped_page, page, click_action, skyvern_element) + if not await skyvern_element.is_selectable(): # 1. find from children # TODO: 2. find from siblings and their chidren diff --git a/skyvern/webeye/utils/dom.py b/skyvern/webeye/utils/dom.py index 80855865..a37fc3f0 100644 --- a/skyvern/webeye/utils/dom.py +++ b/skyvern/webeye/utils/dom.py @@ -148,6 +148,9 @@ class SkyvernElement: return False + async def is_custom_option(self) -> bool: + return self.get_tag_name() == "li" or await self.get_attr("role") == "option" + async def is_checkbox(self) -> bool: tag_name = self.get_tag_name() if tag_name != "input":