Merge pull request #439 from Br1an67/feat/issue-108-web-form-handling

feat: add support for select, textarea, and file upload in web forms
This commit is contained in:
Martin
2026-03-02 19:45:10 +01:00
committed by GitHub
2 changed files with 65 additions and 3 deletions
+34 -3
View File
@@ -2,7 +2,7 @@ from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.ui import WebDriverWait, Select
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, WebDriverException
from selenium.webdriver.common.action_chains import ActionChains
@@ -530,7 +530,16 @@ class Browser:
if input_type in ["hidden", "submit", "button", "image"] or not element["displayed"]:
continue
input_name = element.get("text") or element.get("id") or input_type
if input_type == "checkbox" or input_type == "radio":
if input_type == "select":
options = element.get("options", [])
options_str = ", ".join(opt["text"] for opt in options if opt["text"])
selected = next((opt["text"] for opt in options if opt.get("selected")), "")
form_strings.append(f"[{input_name}](select: {selected}) options: [{options_str}]")
elif input_type == "textarea":
form_strings.append(f"[{input_name}]("")")
elif input_type == "file":
form_strings.append(f"[{input_name}](file: )")
elif input_type == "checkbox" or input_type == "radio":
try:
checked_status = "checked" if element.is_selected() else "unchecked"
except Exception as e:
@@ -694,7 +703,29 @@ class Browser:
self.logger.warning(f"Element '{name}' is not interactable (not displayed or disabled)")
continue
input_type = (element.get_attribute("type") or "text").lower()
if input_type in ["checkbox", "radio"]:
tag_name = (element.tag_name or "").lower()
if tag_name == "select":
try:
select = Select(element)
select.select_by_visible_text(value)
self.logger.info(f"Selected '{value}' for {name}")
except Exception:
try:
select.select_by_value(value)
self.logger.info(f"Selected value '{value}' for {name}")
except Exception as sel_e:
self.logger.warning(f"Could not select '{value}' for {name}: {sel_e}")
elif tag_name == "textarea":
element.clear()
element.send_keys(value)
self.logger.info(f"Filled textarea {name}")
elif input_type == "file":
if os.path.isabs(value) and os.path.exists(value):
element.send_keys(value)
self.logger.info(f"Uploaded file '{value}' for {name}")
else:
self.logger.warning(f"File not found: {value}")
elif input_type in ["checkbox", "radio"]:
is_checked = element.is_selected()
should_be_checked = value.lower() == "checked"
+31
View File
@@ -11,6 +11,37 @@ function findInputs(element, result = []) {
displayed: isElementDisplayed(input)
});
});
// Find all <select> elements (dropdowns / multi-choice)
const selects = element.querySelectorAll('select');
selects.forEach(select => {
const options = Array.from(select.options).map(opt => ({
value: opt.value,
text: opt.textContent.trim(),
selected: opt.selected
}));
result.push({
tagName: select.tagName,
text: select.name || '',
type: 'select',
class: select.className || '',
xpath: getXPath(select),
displayed: isElementDisplayed(select),
multiple: select.multiple,
options: options
});
});
// Find all <textarea> elements
const textareas = element.querySelectorAll('textarea');
textareas.forEach(textarea => {
result.push({
tagName: textarea.tagName,
text: textarea.name || '',
type: 'textarea',
class: textarea.className || '',
xpath: getXPath(textarea),
displayed: isElementDisplayed(textarea)
});
});
const allElements = element.querySelectorAll('*');
allElements.forEach(el => {
if (el.shadowRoot) {