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
+560
View File
@@ -0,0 +1,560 @@
import json
import os
from datetime import datetime
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoAlertPresentException, TimeoutException, StaleElementReferenceException
from .locators import Locator
from .config_reader import (
get_login_captcha_wait_seconds,
get_login_post_submit_wait_seconds,
get_step_delay_seconds,
)
import time
import msvcrt
STEP_DELAY_SECONDS = get_step_delay_seconds()
LOGIN_CAPTCHA_WAIT_SECONDS = get_login_captcha_wait_seconds()
LOGIN_POST_SUBMIT_WAIT_SECONDS = get_login_post_submit_wait_seconds()
def pause_after_step(seconds=STEP_DELAY_SECONDS):
time.sleep(seconds)
def wait_for_manual_input(prompt="Press Enter in the terminal when you want to finish this run..."):
print(prompt)
try:
input()
except EOFError as exc:
raise RuntimeError(
"Manual input is required for this test. Run pytest with -s so Enter can be captured."
) from exc
def clear_pending_console_input():
while msvcrt.kbhit():
msvcrt.getwch()
def enter_pressed():
if not msvcrt.kbhit():
return False
pressed = False
while msvcrt.kbhit():
key = msvcrt.getwch()
if key in ("\r", "\n"):
pressed = True
return pressed
def login(driver, username, password):
wait = WebDriverWait(driver, 20)
# username
userid_field = wait.until(
EC.visibility_of_element_located((By.XPATH, Locator.userid))
)
userid_field.send_keys(username)
# password
password_field = driver.find_element(By.XPATH, Locator.password)
password_field.send_keys(password)
print(f"Solve captcha within {LOGIN_CAPTCHA_WAIT_SECONDS} seconds...")
# wait for manual captcha solve
time.sleep(LOGIN_CAPTCHA_WAIT_SECONDS)
# click submit
submit_btn = wait.until(
EC.element_to_be_clickable((By.XPATH, Locator.submitbtn))
)
submit_btn.click()
time.sleep(LOGIN_POST_SUBMIT_WAIT_SECONDS)
accept_browser_alert_if_present(driver)
# wait for dashboard
wait.until(
EC.visibility_of_element_located((By.XPATH, Locator.dashboard_marker))
)
close_tac_expiry_modal_if_present(driver)
print("Login successful")
def accept_browser_alert_if_present(driver, timeout=5):
try:
alert = WebDriverWait(driver, timeout).until(EC.alert_is_present())
print(f"Browser alert accepted: {alert.text}")
alert.accept()
return True
except (TimeoutException, NoAlertPresentException):
return False
def close_tac_expiry_modal_if_present(driver, timeout=5):
try:
close_button = WebDriverWait(driver, timeout).until(
EC.element_to_be_clickable((By.XPATH, Locator.tacexpiryclosebtn))
)
except TimeoutException:
return False
try:
close_button.click()
except Exception:
driver.execute_script("arguments[0].click();", close_button)
print("Closed TAC Expiry modal")
return True
def handle_transient_popups(driver):
accepted_alert = accept_browser_alert_if_present(driver, timeout=2)
closed_modal = close_tac_expiry_modal_if_present(driver, timeout=2)
return accepted_alert or closed_modal
def backup_current_session_token(driver):
session_backup = {
"current_url": driver.current_url,
"cookies": driver.get_cookies(),
}
print(f"Backed up current browser session with {len(session_backup['cookies'])} cookies")
return session_backup
def save_session_backup(driver, test_context, name="session_backup"):
backup = backup_current_session_token(driver)
backup["created_at"] = datetime.now().isoformat(timespec="seconds")
path = os.path.join(test_context["folder"], f"{name}.json")
with open(path, "w", encoding="utf-8") as backup_file:
json.dump(backup, backup_file, indent=2)
test_context.setdefault("extra_folders", [])
print(f"Session backup saved: {path}")
return backup
def logout(driver):
wait = WebDriverWait(driver, 20)
handle_transient_popups(driver)
try:
user_menu = wait.until(
EC.element_to_be_clickable((By.XPATH, Locator.usermenutoggle))
)
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", user_menu)
try:
user_menu.click()
except Exception:
driver.execute_script("arguments[0].click();", user_menu)
wait.until(
EC.visibility_of_element_located(
(
By.XPATH,
"//li[contains(@class,'dropdown') and contains(@class,'navbar-user') and contains(@class,'open')]"
)
)
)
logout_link = wait.until(
EC.element_to_be_clickable((By.XPATH, Locator.logoutlink))
)
try:
logout_link.click()
except Exception:
driver.execute_script("arguments[0].click();", logout_link)
accept_browser_alert_if_present(driver, timeout=3)
wait.until(
EC.visibility_of_element_located((By.XPATH, Locator.userid))
)
print("Logout successful")
return True
except TimeoutException:
print("Logout link was not found; browser will still close from fixture teardown")
return False
def select_ui_dropdown(driver, dropdown_label, value):
wait = WebDriverWait(driver, 20)
# 1️⃣ Open dropdown
dropdown = wait.until(
EC.element_to_be_clickable(
(By.XPATH, f"//span[@aria-label='{dropdown_label} activate']")
)
)
dropdown.click()
# 2️⃣ Find search box
search_box = wait.until(
EC.visibility_of_element_located((By.CSS_SELECTOR, "input.ui-select-search"))
)
# 3️⃣ Type product name
search_box.clear()
search_box.send_keys(value)
# 4️⃣ Wait for dropdown options to load
option_xpath = f"//div[contains(@class,'ui-select-choices-row')]//span[contains(text(),'{value}')]"
option = wait.until(
EC.element_to_be_clickable((By.XPATH, option_xpath))
)
# 5️⃣ Click option
option.click()
print(f"{value} selected successfully")
def select_labeled_ui_dropdown(driver, field_label, value):
wait = WebDriverWait(driver, 20)
dropdown_xpath = (
f"//label[normalize-space()='{field_label}']"
"/following::span[contains(@class,'ui-select-toggle')][1]"
)
dropdown = wait.until(
EC.element_to_be_clickable(
(
By.XPATH,
dropdown_xpath
)
)
)
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", dropdown)
try:
dropdown.click()
except Exception:
driver.execute_script("arguments[0].click();", dropdown)
search_xpath = (
f"//label[normalize-space()='{field_label}']"
"/following::input[contains(@class,'ui-select-search')][1]"
)
search_box = wait.until(
EC.visibility_of_element_located(
(By.XPATH, search_xpath)
)
)
search_box.click()
search_box.send_keys(Keys.CONTROL, "a")
search_box.clear()
search_box.send_keys(value)
wait.until(
EC.presence_of_element_located(
(By.XPATH, "//div[contains(@class,'ui-select-choices-row')]")
)
)
def _visible_choice_rows():
rows = driver.find_elements(By.XPATH, "//div[contains(@class,'ui-select-choices-row')]")
return [row for row in rows if row.is_displayed()]
option = None
visible_rows = _visible_choice_rows()
for row in visible_rows:
if row.text.strip() == value:
option = row
break
if option is None:
available_options = [row.text.strip() for row in visible_rows if row.text.strip()]
raise AssertionError(
f"Exact option '{value}' was not available in {field_label}. "
f"Visible options: {available_options}"
)
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", option)
try:
option.click()
except Exception:
driver.execute_script("arguments[0].click();", option)
print(f"{value} selected successfully from {field_label}")
def open_trading_maintenance_page(driver, menu_xpath):
wait = WebDriverWait(driver, 20)
trading_maintenance = wait.until(
EC.presence_of_element_located((By.XPATH, Locator.tradingmaintenance))
)
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", trading_maintenance)
submenu = driver.find_elements(By.XPATH, menu_xpath)
submenu_visible = any(item.is_displayed() for item in submenu)
if not submenu_visible:
try:
wait.until(EC.element_to_be_clickable((By.XPATH, Locator.tradingmaintenance)))
trading_maintenance.click()
except Exception:
driver.execute_script("arguments[0].click();", trading_maintenance)
menu_item = wait.until(
EC.element_to_be_clickable((By.XPATH, menu_xpath))
)
try:
menu_item.click()
except Exception:
driver.execute_script("arguments[0].click();", menu_item)
def click_visible_menu_item(driver, menu_xpath):
wait = WebDriverWait(driver, 20)
menu_items = driver.find_elements(By.XPATH, menu_xpath)
for menu_item in menu_items:
if menu_item.is_displayed():
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", menu_item)
try:
menu_item.click()
except Exception:
driver.execute_script("arguments[0].click();", menu_item)
return
menu_item = wait.until(
EC.element_to_be_clickable((By.XPATH, menu_xpath))
)
try:
menu_item.click()
except Exception:
driver.execute_script("arguments[0].click();", menu_item)
def type_into_field(driver, locator, value):
wait = WebDriverWait(driver, 20)
field = wait.until(
EC.visibility_of_element_located(locator)
)
field.clear()
field.send_keys(value)
def select_bootstrap_dropdown_by_id(driver, element_id, value):
wait = WebDriverWait(driver, 20)
container = wait.until(
EC.presence_of_element_located((By.ID, element_id))
)
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", container)
toggle_xpath = (
f"//div[@id='{element_id}']//span[contains(@class,'ui-select-toggle')]"
f"|//div[@id='{element_id}']//span[contains(@class,'btn-default')]"
f"|//div[@id='{element_id}']//span[contains(@class,'ui-select-placeholder')]"
f"|//div[@id='{element_id}']//input[contains(@class,'ui-select-search')]"
)
toggle = wait.until(
EC.presence_of_element_located((By.XPATH, toggle_xpath))
)
try:
wait.until(EC.element_to_be_clickable((By.XPATH, toggle_xpath)))
toggle.click()
except Exception:
driver.execute_script("arguments[0].click();", toggle)
try:
search_box = wait.until(
EC.visibility_of_element_located(
(By.XPATH, f"//div[@id='{element_id}']//input[contains(@class,'ui-select-search')]")
)
)
except TimeoutException:
search_box = wait.until(
EC.visibility_of_element_located(
(By.XPATH, "//input[contains(@class,'ui-select-search') and not(@aria-hidden='true')]")
)
)
search_box.click()
search_box.send_keys(Keys.CONTROL, "a")
search_box.clear()
search_box.send_keys(value)
option = wait.until(
EC.element_to_be_clickable(
(
By.XPATH,
"//div[contains(@class,'ui-select-choices-row')]"
f"//*[normalize-space()='{value}' or starts-with(normalize-space(),'{value}')]"
)
)
)
option.click()
print(f"{value} selected successfully from {element_id}")
def click_grid_button_for_row_text(driver, row_text, button_text):
wait = WebDriverWait(driver, 20)
button_xpath = (
"//div[contains(@class,'ui-grid-row')]"
f"[contains(.,'{row_text}')]"
f"//button[normalize-space()='{button_text}']"
)
last_error = None
for _ in range(3):
try:
button = wait.until(
EC.presence_of_element_located((By.XPATH, button_xpath))
)
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", button)
wait.until(EC.element_to_be_clickable((By.XPATH, button_xpath)))
refreshed_button = driver.find_element(By.XPATH, button_xpath)
try:
refreshed_button.click()
except Exception:
driver.execute_script("arguments[0].click();", refreshed_button)
print(f"Clicked {button_text} for row containing {row_text}")
return
except StaleElementReferenceException as exc:
last_error = exc
time.sleep(1)
if last_error:
raise last_error
def click_first_grid_button(driver, button_text):
wait = WebDriverWait(driver, 20)
button_xpath = f"(//button[normalize-space()='{button_text}' and not(contains(@class,'ng-hide'))])[1]"
last_error = None
for _ in range(3):
try:
button = wait.until(
EC.presence_of_element_located((By.XPATH, button_xpath))
)
driver.execute_script("arguments[0].scrollIntoView({block: 'start'});", button)
refreshed_button = driver.find_element(By.XPATH, button_xpath)
try:
refreshed_button.click()
except Exception:
driver.execute_script("arguments[0].click();", refreshed_button)
print(f"Clicked first visible {button_text}")
return
except StaleElementReferenceException as exc:
last_error = exc
time.sleep(1)
if last_error:
raise last_error
def type_first_visible_input(driver, xpath, value):
wait = WebDriverWait(driver, 20)
def _find_visible_input(_driver):
elements = _driver.find_elements(By.XPATH, xpath)
for element in elements:
if element.is_displayed() and element.is_enabled():
return element
return False
element = wait.until(_find_visible_input)
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", element)
element.click()
element.clear()
element.send_keys(value)
def toggle_bootstrap_dropdown_by_id(driver, element_id):
wait = WebDriverWait(driver, 20)
toggle_xpath = (
f"//div[@id='{element_id}']//span[contains(@class,'ui-select-toggle')]"
f"|//div[@id='{element_id}']//span[contains(@class,'btn-default')]"
f"|//div[@id='{element_id}']//span[contains(@class,'ui-select-placeholder')]"
f"|//div[@id='{element_id}']//input[contains(@class,'ui-select-search')]"
)
toggle = wait.until(
EC.presence_of_element_located((By.XPATH, toggle_xpath))
)
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", toggle)
try:
wait.until(EC.element_to_be_clickable((By.XPATH, toggle_xpath)))
toggle.click()
except Exception:
driver.execute_script("arguments[0].click();", toggle)
def click_page_body(driver):
body = WebDriverWait(driver, 20).until(
EC.presence_of_element_located((By.TAG_NAME, "body"))
)
body.click()
def toggle_labeled_ui_dropdown(driver, field_label):
wait = WebDriverWait(driver, 20)
dropdown_xpath = (
f"//label[normalize-space()='{field_label}']"
"/following::span[contains(@class,'ui-select-toggle')][1]"
)
dropdown = wait.until(
EC.element_to_be_clickable((By.XPATH, dropdown_xpath))
)
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", dropdown)
try:
dropdown.click()
except Exception:
driver.execute_script("arguments[0].click();", dropdown)