from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import TimeoutException, StaleElementReferenceException from core.config.config_manager import ConfigManager from core.utils.logger import Logger from core.utils.wait_utils import WaitUtils from core.exceptions.element_exceptions import ElementNotFoundException, ElementNotInteractableException class BasePage: def __init__(self, driver): self.driver = driver self.config = ConfigManager() self.logger = Logger.get_logger() self.wait_utils = WaitUtils(driver) # 页面超时配置 self.timeout = self.config.get('browser.explicit_wait', 30) self.poll_frequency = self.config.get('browser.poll_frequency', 0.5) def open(self, url): """打开页面""" self.logger.info(f"打开页面: {url}") self.driver.get(url) def get_title(self): """获取页面标题""" return self.driver.title def get_current_url(self): """获取当前URL""" return self.driver.current_url def find_element(self, locator, timeout=None): """查找元素""" timeout = timeout or self.timeout try: return self.wait_utils.wait_for_element_present(locator, timeout) except TimeoutException: self.logger.error(f"元素未找到: {locator}") raise ElementNotFoundException(f"元素未找到: {locator}") def find_elements(self, locator, timeout=None): """查找多个元素""" timeout = timeout or self.timeout try: return self.wait_utils.wait_for_elements_present(locator, timeout) except TimeoutException: self.logger.error(f"元素未找到: {locator}") raise ElementNotFoundException(f"元素未找到: {locator}") def click(self, locator, timeout=None): """点击元素""" element = self.find_element(locator, timeout) try: element.click() self.logger.info(f"点击元素: {locator}") except Exception as e: self.logger.error(f"点击元素失败: {locator}, 错误: {str(e)}") raise ElementNotInteractableException(f"无法点击元素: {locator}") def input_text(self, locator, text, timeout=None, clear_first=True): """输入文本""" element = self.find_element(locator, timeout) try: if clear_first: element.clear() element.send_keys(text) self.logger.info(f"在元素 {locator} 中输入文本: {text}") except Exception as e: self.logger.error(f"输入文本失败: {locator}, 错误: {str(e)}") raise ElementNotInteractableException(f"无法在元素中输入文本: {locator}") def get_text(self, locator, timeout=None): """获取元素文本""" element = self.find_element(locator, timeout) try: text = element.text self.logger.info(f"获取元素文本: {locator} -> {text}") return text except Exception as e: self.logger.error(f"获取元素文本失败: {locator}, 错误: {str(e)}") raise ElementNotInteractableException(f"无法获取元素文本: {locator}") def get_attribute(self, locator, attribute, timeout=None): """获取元素属性""" element = self.find_element(locator, timeout) try: value = element.get_attribute(attribute) self.logger.info(f"获取元素属性: {locator}.{attribute} -> {value}") return value except Exception as e: self.logger.error(f"获取元素属性失败: {locator}.{attribute}, 错误: {str(e)}") raise ElementNotInteractableException(f"无法获取元素属性: {locator}.{attribute}") def is_element_present(self, locator, timeout=None): """检查元素是否存在""" try: self.find_element(locator, timeout) return True except ElementNotFoundException: return False def is_element_visible(self, locator, timeout=None): """检查元素是否可见""" try: element = self.find_element(locator, timeout) return element.is_displayed() except (ElementNotFoundException, StaleElementReferenceException): return False def is_element_enabled(self, locator, timeout=None): """检查元素是否可用""" try: element = self.find_element(locator, timeout) return element.is_enabled() except (ElementNotFoundException, StaleElementReferenceException): return False def wait_for_element_visible(self, locator, timeout=None): """等待元素可见""" timeout = timeout or self.timeout return self.wait_utils.wait_for_element_visible(locator, timeout) def wait_for_element_invisible(self, locator, timeout=None): """等待元素不可见""" timeout = timeout or self.timeout return self.wait_utils.wait_for_element_invisible(locator, timeout) def wait_for_element_clickable(self, locator, timeout=None): """等待元素可点击""" timeout = timeout or self.timeout return self.wait_utils.wait_for_element_clickable(locator, timeout) def take_screenshot(self, name): """截取屏幕截图""" from utils.file.screenshot_manager import ScreenshotManager screenshot_manager = ScreenshotManager() return screenshot_manager.take_screenshot(self.driver, name) def scroll_to_element(self, locator, timeout=None): """滚动到元素""" element = self.find_element(locator, timeout) self.driver.execute_script("arguments[0].scrollIntoView(true);", element) self.logger.info(f"滚动到元素: {locator}") def execute_script(self, script, *args): """执行JavaScript脚本""" result = self.driver.execute_script(script, *args) self.logger.info(f"执行JavaScript脚本: {script}") return result