Initial commit - Selenium automation framework

This commit is contained in:
2026-09-08 09:24:02 +05:30
commit e84b7e9950
76 changed files with 7484 additions and 0 deletions
+264
View File
@@ -0,0 +1,264 @@
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import StaleElementReferenceException, TimeoutException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
def _menu_text_xpath(tag_name, label):
return (
f"//{tag_name}[contains(normalize-space(),\"{label}\")]"
f"|//{tag_name}[contains(.,\"{label}\")]"
)
def open_bootstrap_nav_submenu(driver, top_menu_label, submenu_label, final_href_part):
wait = WebDriverWait(driver, 20)
top_menu = wait.until(
EC.element_to_be_clickable(
(
By.XPATH,
"//ul[contains(@class,'nav') and contains(@class,'navbar-nav')]"
f"//a[contains(@class,'dropdown-toggle') and contains(normalize-space(),'{top_menu_label}')]"
)
)
)
try:
top_menu.click()
except Exception:
driver.execute_script("arguments[0].click();", top_menu)
top_menu_container = wait.until(
lambda _driver: _find_open_top_menu_container(_driver, top_menu_label)
)
submenu = wait.until(
lambda _driver: _find_clickable_submenu(_driver, top_menu_container, submenu_label)
)
try:
submenu.click()
except Exception:
driver.execute_script("arguments[0].click();", submenu)
final_option = wait.until(
lambda _driver: _find_clickable_final_option(_driver, top_menu_container, final_href_part)
)
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", final_option)
try:
final_option.click()
except Exception:
driver.execute_script("arguments[0].click();", final_option)
def _find_open_top_menu_container(driver, top_menu_label):
containers = driver.find_elements(
By.XPATH,
"//ul[contains(@class,'nav') and contains(@class,'navbar-nav')]/li"
)
normalized_label = top_menu_label.strip().lower()
for container in containers:
classes = (container.get_attribute("class") or "").lower()
text = container.text.strip().lower()
if normalized_label in text and "open" in classes:
return container
return False
def _find_clickable_submenu(driver, top_menu_container, submenu_label):
normalized_label = submenu_label.strip().lower()
submenu_links = top_menu_container.find_elements(
By.XPATH,
".//ul[contains(@class,'dropdown-menu')]//a"
)
for link in submenu_links:
text = link.text.strip().lower()
if normalized_label in text and link.is_displayed() and link.is_enabled():
return link
return False
def _find_clickable_final_option(driver, top_menu_container, final_href_part):
final_links = top_menu_container.find_elements(
By.XPATH,
f".//ul[contains(@class,'dropdown-menu')]//a[contains(@href,'{final_href_part}')]"
)
for link in final_links:
if link.is_displayed() and link.is_enabled():
return link
return False
def select_select2_value_by_container_id(driver, container_id, value, exact=False):
wait = WebDriverWait(driver, 20)
container = wait.until(
EC.element_to_be_clickable((By.ID, container_id))
)
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", container)
try:
container.click()
except Exception:
driver.execute_script("arguments[0].click();", container)
try:
search_input = wait.until(
EC.visibility_of_element_located(
(By.XPATH, "//div[contains(@class,'select2-drop-active')]//input[contains(@class,'select2-input')]")
)
)
search_input.click()
search_input.send_keys(Keys.CONTROL, "a")
search_input.send_keys(value)
except TimeoutException:
pass
try:
option = wait.until(
lambda _driver: _find_select2_option(_driver, value, exact=exact)
)
except TimeoutException as exc:
available_options = _get_visible_select2_option_texts(driver)
raise TimeoutException(
f"Option '{value}' did not load for {container_id}. "
f"Visible options: {available_options}"
) from exc
try:
option.click()
except Exception:
driver.execute_script("arguments[0].click();", option)
def _find_select2_option(driver, value, exact=False):
options = driver.find_elements(
By.XPATH,
"//div[contains(@class,'select2-drop-active')]//div[contains(@class,'select2-result-label')]"
)
normalized_value = value.strip().lower()
visible_options = []
for option in options:
try:
if option.is_displayed():
visible_options.append(option)
except StaleElementReferenceException:
return False
for option in visible_options:
text = _safe_element_text(option)
if text is None:
return False
if text == normalized_value:
return option
for option in visible_options:
text = _safe_element_text(option)
if text is None:
return False
option_code = text.split("(", 1)[0].strip()
if option_code == normalized_value:
return option
if exact:
return False
for option in visible_options:
text = _safe_element_text(option)
if text is None:
return False
if text.startswith(normalized_value):
return option
for option in visible_options:
text = _safe_element_text(option)
if text is None:
return False
if normalized_value in text:
return option
return False
def _safe_element_text(element):
try:
return element.text.strip().lower()
except StaleElementReferenceException:
return None
def click_select2_option_by_text(driver, container_id, value):
wait = WebDriverWait(driver, 20)
container = wait.until(EC.element_to_be_clickable((By.ID, container_id)))
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", container)
try:
container.click()
except Exception:
driver.execute_script("arguments[0].click();", container)
option = wait.until(lambda _driver: _find_select2_option(_driver, value))
driver.execute_script("arguments[0].scrollIntoView({block: 'nearest'});", option)
try:
option.click()
except Exception:
driver.execute_script("arguments[0].click();", option)
def wait_for_select2_option_by_text(driver, container_id, value, timeout_seconds=30, attempts=3):
wait = WebDriverWait(driver, timeout_seconds)
last_error = None
for _ in range(attempts):
container = wait.until(EC.element_to_be_clickable((By.ID, container_id)))
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", container)
try:
container.click()
except Exception:
driver.execute_script("arguments[0].click();", container)
try:
option = wait.until(lambda _driver: _find_select2_option(_driver, value))
try:
container.click()
except Exception:
driver.execute_script("arguments[0].click();", container)
return option
except TimeoutException as exc:
last_error = exc
try:
container.click()
except Exception:
driver.execute_script("arguments[0].click();", container)
if last_error:
available_options = _get_visible_select2_option_texts(driver)
raise TimeoutException(
f"Option '{value}' did not load for {container_id}. "
f"Visible options: {available_options}"
) from last_error
raise TimeoutException(f"Option '{value}' did not load for {container_id}")
def _get_visible_select2_option_texts(driver):
options = driver.find_elements(
By.XPATH,
"//div[contains(@class,'select2-drop-active')]//div[contains(@class,'select2-result-label')]"
)
return [option.text.strip() for option in options if option.is_displayed()]