from selenium.webdriver.remote.webdriver import WebDriver from selenium.webdriver.remote.webelement import WebElement from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time class BasePage: """ The BasePage class serves as a foundation for all page objects. It encapsulates common Selenium operations to promote code reuse and improve test maintenance. """ def __init__(self, driver: WebDriver): """ Initializes the BasePage with a WebDriver instance. :param driver: The WebDriver instance to interact with the browser. """ self.driver = driver self.wait = WebDriverWait(driver, 10) # Default explicit wait of 10 seconds def open(self, base_url: str, path: str): """ Navigates to a specific path relative to the base URL. :param base_url: The base URL of the web application. :param path: The relative path to open (e.g., "/form-elements"). """ url = base_url.rstrip('/') + path self.driver.get(url) def find_element(self, locator: tuple) -> WebElement: """ Finds and returns a web element using an explicit wait. :param locator: A tuple containing the locator strategy and value (e.g., (By.ID, "my-element")). :return: The located WebElement. """ return self.wait.until(EC.presence_of_element_located(locator)) def find_visible_element(self, locator: tuple) -> WebElement: """ Finds and returns a web element that is visible on the page. :param locator: A tuple containing the locator strategy and value. :return: The located and visible WebElement. """ return self.wait.until(EC.visibility_of_element_located(locator)) def click(self, locator: tuple): """ Waits for an element to be clickable and then clicks on it. :param locator: A tuple containing the locator strategy and value. """ element = self.wait.until(EC.element_to_be_clickable(locator)) element.click() def send_keys(self, locator: tuple, text: str): """ Finds an element, clears its content, and sends keys to it. :param locator: A tuple containing the locator strategy and value. :param text: The text to send to the element. """ element = self.find_element(locator) element.clear() element.send_keys(text) def get_text(self, locator: tuple) -> str: """ Finds an element and returns its text content. :param locator: A tuple containing the locator strategy and value. :return: The text content of the element. """ element = self.find_element(locator) return element.text def is_element_selected(self, locator: tuple) -> bool: """ Checks if a checkbox or radio button element is selected. :param locator: A tuple containing the locator strategy and value. :return: True if the element is selected, False otherwise. """ element = self.find_element(locator) return element.is_selected() def is_element_enabled(self, locator: tuple) -> bool: """ Checks if a form element is enabled. :param locator: A tuple containing the locator strategy and value. :return: True if the element is enabled, False otherwise. """ element = self.find_element(locator) return element.is_enabled() def switch_to_alert(self): """ Switches the driver's focus to a browser alert. :return: The alert object. """ return self.wait.until(EC.alert_is_present()) def back(self): """ Navigates one step backward in the browser history. """ self.driver.back() def forward(self): """ Navigates one step forward in the browser history. """ self.driver.forward() def refresh(self): """ Refreshes the current page. """ self.driver.refresh() def take_screenshot(self, name: str = "screenshot"): """ Captures a screenshot of the current browser window. :param name: Base name for the screenshot file. :return: The filename of the saved screenshot. """ timestamp = time.strftime("%Y%m%d_%H%M%S") filename = f"{name}_{timestamp}.png" self.driver.save_screenshot(filename) return filename def find_elements(self, locator: tuple): """ Finds and returns a list of web elements using an explicit wait. :param locator: A tuple containing the locator strategy and value (e.g., (By.CLASS_NAME, "items")). :return: A list of located WebElements. """ return self.wait.until(EC.presence_of_all_elements_located(locator)) def scroll_into_view(self, locator: tuple): """ Scrolls the page until the specified element is in view. :param locator: A tuple containing the locator strategy and value. """ element = self.find_element(locator) self.driver.execute_script("arguments[0].scrollIntoView(true);", element) def click_by_js(self, locator: tuple): """ Clicks on an element using JavaScript execution. Useful when standard Selenium click does not work. :param locator: A tuple containing the locator strategy and value. """ element = self.find_element(locator) self.driver.execute_script("arguments[0].click();", element) def wait_for_text(self, locator: tuple, text: str): """ Waits until the specified text is present within an element. :param locator: A tuple containing the locator strategy and value. :param text: The text to wait for in the element. :return: True if the text is present, False otherwise. """ return self.wait.until(EC.text_to_be_present_in_element(locator, text)) def wait_for_url_contains(self, url_substring: str): """ Waits until the current URL contains the given substring. :param url_substring: The substring to look for in the URL. :return: True if the URL contains the substring, False otherwise. """ return self.wait.until(EC.url_contains(url_substring))