import time
from datetime import datetime
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.common.action_chains import ActionChains
from ******.scripts.handle_logger import case_logger
from ******.scripts.constants import OutPuts_DIR
from ******.Common.file_upload import upload


class BasePage:
    '''
    BasePage类,针对PageObjects类的二次封装
    '''

    def __init__(self, driver: WebDriver):
        self.driver = driver

    def wait_element_to_be_visible(self, loc_tuple, img_doc, timeout=20, frequency=0.5):
        '''
        等待元素可见
        :param loc_tuple: 元素定位的XPATH元组表达式
        :param img_doc: 截图说明
        :param timeout: 等待的超时时间
        :param frequency: 轮询频率
        :return:
        '''
        try:
            case_logger.info("开始等待页面元素<{}>是否可见!".format(loc_tuple))
            start_time = time.time()
            WebDriverWait(self.driver, timeout, frequency).until(EC.visibility_of_element_located(loc_tuple))
        except Exception as e:
            case_logger.error("页面元素<{}>等待可见失败!".format(loc_tuple))
            self.save_screenshot(img_doc)
            raise e
        else:
            end_time = time.time()
            case_logger.info("页面元素<{}>等待可见,等待时间:{}秒".format(loc_tuple, round(end_time-start_time, 1)))

    def wait_element_to_be_click(self, loc_tuple, img_doc, timeout=20, frequency=0.5):
        '''
        等待元素可点击
        :param loc_tuple: 元素定位的XPATH元组表达式
        :param img_doc: 截图说明
        :param timeout: 等待的超时时间
        :param frequency: 轮询频率
        :return:
        '''
        try:
            case_logger.info("开始等待页面元素<{}>是否可点击!".format(loc_tuple))
            start_time = time.time()
            WebDriverWait(self.driver, timeout, frequency).until(EC.element_to_be_clickable(loc_tuple))
        except Exception as e:
            case_logger.error("页面元素<{}>等待可点击失败!".format(loc_tuple))
            self.save_screenshot(img_doc)
            raise e
        else:
            end_time = time.time()
            case_logger.info("页面元素<{}>等待可点击,等待时间:{}秒".format(loc_tuple, round(end_time-start_time, 1)))

    def wait_element_to_be_exist(self, loc_tuple, img_doc, timeout=20, frequency=0.5):
        '''
        等待元素存在
        :param loc_tuple: 元素定位的XPATH元组表达式
        :param img_doc: 截图说明
        :param timeout: 等待的超时时间
        :param frequency: 轮询频率
        :return:
        '''
        try:
            case_logger.info("开始等待页面元素<{}>是否存在!".format(loc_tuple))
            start_time = time.time()
            WebDriverWait(self.driver, timeout, frequency).until(EC.presence_of_all_elements_located(loc_tuple))
        except Exception as e:
            case_logger.error("页面元素<{}>等待存在失败!".format(loc_tuple))
            self.save_screenshot(img_doc)
            raise e
        else:
            end_time = time.time()
            case_logger.info("页面元素<{}>等待存在,等待时间:{}秒".format(loc_tuple, round(end_time-start_time, 1)))

    def save_screenshot(self, img_doc):
        '''
        页面截屏保存截图
        :param img_doc: 截图说明
        :return:
        '''
        filename = OutPuts_DIR + "\\{}{}".format(img_doc, datetime.strftime(datetime.now(), "%Y%m%d%H%M%S"))
        self.driver.save_screenshot(filename)
        case_logger.info("页面截图文件保存在:{}".format(filename))

    def get_element(self, loc_tuple, img_doc):
        '''
        获取页面中的元素
        :param loc_tuple: 元素定位的XPATH元组表达式
        :param img_doc: 截图说明
        :return: WebElement对象
        '''
        case_logger.info("在{}中查找元素<{}>".format(img_doc, loc_tuple))
        try:
            ele = self.driver.find_element(*loc_tuple)
        except Exception as e:
            case_logger.error("在{}中查找元素<{}>失败!".format(img_doc, loc_tuple))
            raise e
        else:
            return ele

    def input_text(self, input_text, loc_tuple, img_doc, timeout=20, frequency=0.5):
        '''
        对输入框输入文本内容
        :param input_text: 输入的文本内容
        :param loc_tuple: 元素定位的XPATH元组表达式
        :param img_doc: 截图说明
        :param timeout: 等待的超时时间
        :param frequency: 轮询频率
        :return:
        '''
        try:
            case_logger.info("在{}中输入元素<{}>的内容为{}".format(img_doc, loc_tuple, input_text))
            self.wait_element_to_be_visible(loc_tuple, img_doc, timeout, frequency)
            self.get_element(loc_tuple, img_doc).send_keys(input_text)
        except Exception as e:
            case_logger.error("在元素<{}>中输入内容{}失败!".format(loc_tuple, input_text))
            self.save_screenshot(img_doc)
            raise e

    def clear_text(self, loc_tuple, img_doc, timeout=20, frequency=0.5):
        '''
        清除文本框的内容
        :param loc_tuple: 元素定位的XPATH元组表达式
        :param img_doc: 截图说明
        :param timeout: 等待的超时时间
        :param frequency: 轮询频率
        :return:
        '''
        try:
            case_logger.info("在{}中清除元素<{}>的文本内容".format(img_doc, loc_tuple))
            self.wait_element_to_be_click(loc_tuple, img_doc, timeout, frequency)
            self.get_element(loc_tuple, img_doc).clear()
        except Exception as e:
            case_logger.error("在{}中清除元素<{}>的文本内容失败!".format(img_doc, loc_tuple))
            self.save_screenshot(img_doc)
            raise e

    def click_button(self, loc_tuple, img_doc, timeout=20, frequency=0.5):
        '''
        点击按钮
        :param loc_tuple: 元素定位的XPATH元组表达式
        :param img_doc: 截图说明
        :param timeout: 等待的超时时间
        :param frequency: 轮询频率
        :return:
        '''
        try:
            case_logger.info("在{}中点击元素<{}>".format(img_doc, loc_tuple))
            self.wait_element_to_be_click(loc_tuple, img_doc, timeout, frequency)
            self.get_element(loc_tuple, img_doc).click()
        except Exception as e:
            case_logger.error("在{}中点击元素<{}>失败!".format(img_doc, loc_tuple))
            self.save_screenshot(img_doc)
            raise e

    def get_element_text(self, loc_tuple, img_doc, timeout=20, frequency=0.5):
        '''
        获取WebElement对象的文本值
        :param loc_tuple: 元素定位的XPATH元组表达式
        :param img_doc: 截图说明
        :param timeout: 等待的超时时间
        :param frequency: 轮询频率
        :return: WebElement对象的文本值
        '''
        try:
            case_logger.info("在{}中获取元素<{}>的文本值".format(img_doc, loc_tuple))
            self.wait_element_to_be_exist(loc_tuple, img_doc, timeout, frequency)
            text = self.get_element(loc_tuple, img_doc).text
        except Exception as e:
            case_logger.error("在{}中获取元素<{}>的文本值失败!".format(img_doc, loc_tuple))
            self.save_screenshot(img_doc)
            raise e
        else:
            case_logger.info("获取到的元素文本值为{}".format(text))
            return text

    def get_element_attr(self, attr_name, loc_tuple, img_doc, timeout=20, frequency=0.5):
        '''
        获取WebElement对象的属性值
        :param attr_name: 属性名称
        :param loc_tuple: 元素定位的XPATH元组表达式
        :param img_doc: 截图说明
        :param timeout: 等待的超时时间
        :param frequency: 轮询频率
        :return: WebElement对象的属性值
        '''
        try:
            case_logger.info("在{}中获取元素<{}>的属性{}的值".format(img_doc, loc_tuple, attr_name))
            self.wait_element_to_be_exist(loc_tuple, img_doc, timeout, frequency)
            value = self.get_element(loc_tuple, img_doc).get_attribute(attr_name)
        except Exception as e:
            case_logger.error("在{}中获取元素<{}>的属性{}的值失败!".format(img_doc, loc_tuple, attr_name))
            self.save_screenshot(img_doc)
            raise e
        else:
            case_logger.info("获取到的元素属性{}的值为{}".format(attr_name, value))
            return value

    def switch_to_frame(self, loc_tuple, img_doc, timeout=20, frequency=0.5):
        '''
        切换iframe页面
        :param loc_tuple: 元素定位的XPATH元组表达式
        :param img_doc: 截图说明
        :param timeout: 等待的超时时间
        :param frequency: 轮询频率
        :return:
        '''
        try:
            case_logger.info("在{}中根据元素<{}>进行iframe切换".format(img_doc, loc_tuple))
            start_time = time.time()
            WebDriverWait(self.driver, timeout, frequency).until(EC.frame_to_be_available_and_switch_to_it(loc_tuple))
        except Exception as e:
            case_logger.error("在{}中根据元素<{}>进行iframe切换失败!".format(img_doc, loc_tuple))
            self.save_screenshot(img_doc)
            raise e
        else:
            end_time = time.time()
            case_logger.info("在{}中根据元素<{}>进行iframe切换,等待时间:{}秒".
                             format(img_doc, loc_tuple, round(end_time-start_time, 1)))

    def switch_to_default_content(self, img_doc):
        '''
        切换iframe到main页面
        :param img_doc: 截图说明
        :return:
        '''
        try:
            case_logger.info("切换iframe到main页面")
            self.driver.switch_to.default_content()
        except Exception as e:
            case_logger.error("切换iframe到main页面失败!")
            self.save_screenshot(img_doc)
            raise e

    def upload_file(self, filename, img_doc, browser_type="chrome"):
        '''
        非input标签的文件上传
        :param filename: 文件名(绝对路径)
        :param img_doc: 截图说明
        :param browser_type: 浏览器类型
        :return:
        '''
        try:
            case_logger.info("上传文件({})".format(filename))
            upload(filePath=filename, browser_type=browser_type)
        except Exception as e:
            case_logger.error("上传文件({})失败!".format(filename))
            self.save_screenshot(img_doc)
            raise e

    def suspend_mouse(self, loc_tuple, img_doc, timeout=20, frequency=0.5):
        '''
        鼠标悬浮
        :param loc_tuple: 元素定位的XPATH元组表达式
        :param img_doc: 截图说明
        :param timeout: 等待的超时时间
        :param frequency: 轮询频率
        :return:
        '''
        try:
            case_logger.error("在{}上根据元素<{}>进行悬浮".format(img_doc, loc_tuple))
            self.wait_element_to_be_click(loc_tuple, img_doc, timeout, frequency)
            ele = self.get_element(img_doc, loc_tuple)
            ActionChains(self.driver).move_to_element(ele).perform()
        except Exception as e:
            case_logger.error("在{}上根据元素<{}>进行悬浮失败!".format(img_doc, loc_tuple))
            self.save_screenshot(img_doc)
            raise e

窗口切换、alert弹框关闭、select选择等还未进行二次封装,未完待续......

01-16 11:23