diff --git a/skyvern/webeye/actions/handler.py b/skyvern/webeye/actions/handler.py index f5048c67..90e2397c 100644 --- a/skyvern/webeye/actions/handler.py +++ b/skyvern/webeye/actions/handler.py @@ -320,9 +320,16 @@ async def handle_select_option_action( ) return [ActionFailure(Exception(f"Cannot handle SelectOptionAction on a non-listbox element"))] + # TODO: double click will uncheck the checkbox + if tag_name == "input" and await locator.get_attribute( + "type", timeout=SettingsManager.get_settings().BROWSER_ACTION_TIMEOUT_MS + ) in ["radio", "checkbox"]: + click_action = ClickAction(element_id=action.element_id) + return await chain_click(task, page, click_action, xpath) + current_text = await locator.input_value() if current_text == action.option.label: - return ActionSuccess() + return [ActionSuccess()] try: # First click by label (if it matches) await page.click(f"xpath={xpath}", timeout=SettingsManager.get_settings().BROWSER_ACTION_TIMEOUT_MS) diff --git a/skyvern/webeye/scraper/domUtils.js b/skyvern/webeye/scraper/domUtils.js index 274448a9..f6293f8b 100644 --- a/skyvern/webeye/scraper/domUtils.js +++ b/skyvern/webeye/scraper/domUtils.js @@ -502,6 +502,27 @@ function buildTreeFromBody() { var resultArray = []; const checkSelect2 = () => { + const showInvisible = (element) => { + if (element.style.display === "none") { + element.style.removeProperty("display"); + return true; + } + + const removedClass = []; + for (let i = 0; i < element.classList.length; i++) { + const className = element.classList[i]; + if (className.includes("hidden")) { + removedClass.push(className); + } + } + if (removedClass.length !== 0) { + removedClass.forEach((className) => { + element.classList.remove(className); + }); + return true; + } + return false; + }; // according to select2(https://select2.org/getting-started/basic-usage) // select2-container seems to be the most common class in select2, // and the invisible select seems to be the sibling to the "select2-container" element. @@ -511,11 +532,7 @@ function buildTreeFromBody() { // search select in previous let _pre = element.previousElementSibling; while (_pre) { - if ( - _pre.tagName.toLowerCase() === "select" && - _pre.style.display === "none" - ) { - _pre.style.removeProperty("display"); + if (_pre.tagName.toLowerCase() === "select" && showInvisible(_pre)) { // only hide the select2 container when an alternative select found element.style.display = "none"; return; @@ -526,11 +543,7 @@ function buildTreeFromBody() { // search select in next let _next = element.nextElementSibling; while (_next) { - if ( - _next.tagName.toLowerCase() === "select" && - _next.style.display === "none" - ) { - _next.style.removeProperty("display"); + if (_next.tagName.toLowerCase() === "select" && showInvisible(_next)) { // only hide the select2 container when an alternative select found element.style.display = "none"; return;