# -*- coding: UTF-8 -*- import os import time import platform from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as ec from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.by import By from selenium.webdriver import ActionChains from selenium.webdriver.support.select import Select from base_framework.public_tools.read_config import get_current_config cull_path = os.path.dirname(os.path.abspath(__file__)) plugs = os.path.abspath(os.path.join(cull_path, '../{}'.format('/platform_tools/plugins/headerenv.crx'))) DEFAULT_TIMEOUT = 5 class SeleniumWebUI: def __init__(self): self.driver = None self.action = None # 用于鼠标类事件 self.business = get_current_config(section="run_evn_name", key="current_business") self.jira_id = get_current_config(section="run_jira_id", key="huohua-podenv") self.feature = get_current_config(section="run_jira_id", key="huohua-feature") # print(self.jira_id) def web_open_browser(self, url="", browser_type="chrome", enable_image=True, station='web'): """ | 功能说明: | 打开浏览器,默认chrome | | 输入参数: | url | 网址,默认为空:仅打开浏览器 | | | browser_type | 浏览器类型:chrome,firefox,edge | | | enable_image | 浏览器是否加载图片 | | | station | 浏览器模式:web:web模式,m:手机模式 | | 作者信息: | 谢祥益 | 2022.06.01 | """ if browser_type == "chrome": options = webdriver.ChromeOptions() if platform.system() == 'Linux': default_driver_path = r'/home/chrome_home/chromedriver' options.add_argument("--headless") options.add_argument("--no-sandbox") options.add_argument('--disable-gpu') options.add_argument('--disable-dev-shm-usage') self.driver = webdriver.Chrome(executable_path=default_driver_path, options=options) else: # 将正确的chrome driver版本放在python根目录下 options.add_extension(plugs) if not enable_image: options.add_argument('blink-settings=imagesEnabled=false') print('当前为无图片模式') if station == 'm': options.add_experimental_option('mobileEmulation', {'deviceName': 'iPhone 12 Pro'}) self.driver = webdriver.Chrome(options=options) elif browser_type == "firefox": self.driver = webdriver.Firefox() elif browser_type == "edge": self.driver = webdriver.Edge() else: raise Exception("传入的浏览器类型不正确,正确的浏览器类型(chrome, firefox, edge)") if len(url) > 0: self.web_open_url(url=url) self.action = ActionChains(self.driver) def web_open_url(self, url): """ | 功能说明: | 打开链接并最大化浏览器 | | 输入参数: | url | 访问地址 | | 作者信息: | 谢祥益 | 2022.06.01 | """ if not self.driver: self.web_open_browser() if self.jira_id.lower() not in ('', 'qa'): # 判断并添加独立环境 self.web_set_independent_environment() self.driver.maximize_window() self.driver.get(url) def web_close_browser(self): """ | 功能说明: | 关闭浏览器,但注意并没有销毁driver对象 | | 输入参数: | 无 | | 作者信息: | 谢祥益 at 2022.06.01 | 举例说明: """ self.driver.quit() def web_refresh_page(self): """ | 功能说明: | 刷新浏览器当前页面 | | 输入参数: | | | 作者信息: | 谢祥益 at 2022.06.01 | """ self.driver.refresh() def web_switch_handle(self, index): """ | 功能说明: | 切换浏览器页面标签,适用于新开页面,或多页面操作 | | 输入参数: | index | 标签索引 | | 作者信息: | 谢祥益 | 2022.06.01 | """ handles = self.driver.window_handles self.driver.switch_to_window(handles[index]) def web_get_cookie(self): """ | 功能说明: | 返回浏览器当前application的cookie | | 输入参数: | | | 作者信息: | 谢祥益 at 2022.06.01 | """ return self.driver.get_cookies() def web_find_element(self, locator, timeout=DEFAULT_TIMEOUT, raise_exception=True): """ | 功能说明: | 传入元素定位器,定位到该元素,返回第一个元素 | | 输入参数: | locator | 元素路径 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.06.01 | """ if not isinstance(locator, tuple): locator = (By.XPATH, locator) element = WebDriverWait(self.driver, timeout).until(ec.presence_of_element_located(locator), message=['The element is not exist,please check....\n' 'element xpath:{}'.format(locator) if raise_exception else None]) return element def web_find_elements(self, locator, timeout=DEFAULT_TIMEOUT, raise_exception=True): """ | 功能说明: | 传入元素定位器,定位到该元素,返回所有元素 | | 输入参数: | locator | 元素路径 | | | timeout | 超时时间,默认10秒 | | | raise_exception | 当找不到元素时:True-阻断报错(默认),False-返回空list | | 作者信息: | 谢祥益 | 2022.06.01 | """ if not isinstance(locator, tuple): locator = (By.XPATH, locator) element = [] try: element = WebDriverWait(self.driver, timeout).until(ec.presence_of_all_elements_located(locator)) except: if raise_exception: raise Exception("The element is not exist,please check....\n element xpath:{}".format(locator)) return element def web_click_element(self, locator, timeout=DEFAULT_TIMEOUT): """ | 功能说明: | 传入元素定位器,定位到该元素,普通方法点击 | | 输入参数: | locator | 元素路径 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.06.01 | """ element = self.web_find_element(locator, timeout) element.click() def web_click_elements(self, locator, timeout=DEFAULT_TIMEOUT): """ | 功能说明: | 点击所有元素 | | 输入参数: | locator | 元素路径 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.06.01 | """ elements = self.web_find_elements(locator, timeout) for element in elements: element.click() def web_click_element_by_js(self, locator=None, element=None, timeout=DEFAULT_TIMEOUT): """ | 功能说明: | 传入元素定位器,定位到该元素,以JS的方式点击 | | 输入参数: | locator | 元素路径,当没有element时输入 | | | element | 元素对象,当没有locator时输入 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.06.01 | """ if not element and locator: obj = self.web_find_element(locator, timeout) self.driver.execute_script("arguments[0].click();", obj) elif element and not locator: self.driver.execute_script("arguments[0].click();", element) else: raise Exception('不支持的传参方式,locator和element必须且只能传一个') def web_move_element_to_top(self, locator, timeout=DEFAULT_TIMEOUT): """ | 功能说明: | 将指定元素滑动到当前页面顶部 | | 输入参数: | locator | 元素路径 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.08.12 | """ element = self.web_find_element(locator, timeout) self.driver.execute_script("arguments[0].scrollIntoView();", element) def web_move_element_to_bottom(self, locator, timeout=DEFAULT_TIMEOUT): """ | 功能说明: | 将指定元素滑动到当前页面底部 | | 输入参数: | locator | 元素路径 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.08.12 | """ element = self.web_find_element(locator, timeout) self.driver.execute_script("arguments[0].scrollIntoView(false);", element) def web_move_to_top(self): """ | 功能说明: | 滑动到当前页面顶部 | | 作者信息: | 谢祥益 | 2022.08.12 | """ self.driver.execute_script("window.scrollTo(document.body.scrollHeight,0)") def web_move_to_bottom(self): """ | 功能说明: | 滑动到当前页面底部 | | 作者信息: | 谢祥益 | 2022.08.12 | """ self.driver.execute_script("window.scrollTo(0,document.body.scrollHeight)") def web_send_keys(self, locator, text, timeout=DEFAULT_TIMEOUT): """ | 功能说明: | 传入元素定位器,定位到该元素,清空输入框,写入text | | 输入参数: | locator | 元素路径 | | | text | 输入内容 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.06.01 | """ element = self.web_find_element(locator, timeout) element.send_keys(Keys.CONTROL, 'a') element.send_keys(text) def web_get_element_text(self, locator, timeout=DEFAULT_TIMEOUT): """ | 功能说明: | 传入元素定位器,定位到该元素,返回该元素的文本值 | | 输入参数: | locator | 元素路径 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.06.01 | """ element = self.web_find_element(locator, timeout) return element.text def web_click_single_box(self, locator, timeout=DEFAULT_TIMEOUT): """ | 功能说明: | 传入单选框元素定位器,定位到该元素,依次点击单选框 | | 输入参数: | locator | 元素路径 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.06.01 | """ elements = self.web_find_elements(locator, timeout) for element in elements: self.driver.execute_script("arguments[0].click();", element) time.sleep(1.5) def web_select_drop_down_box(self, locator, index=0, timeout=DEFAULT_TIMEOUT): """ | 功能说明: | 传入下拉框定位器,定位到该元素,选择下拉框的第index个选项 | | 输入参数: | locator | 元素路径 | | | index | 第几个元素的下标 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.06.01 | """ select = Select(self.web_find_element(locator, timeout)) select.select_by_index(index) def web_click_checkbox(self, locator, timeout=DEFAULT_TIMEOUT): """ | 功能说明: | 传入多选框元素定位器,定位到该元素,全选 | | 输入参数: | locator | 元素路径 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.06.01 | """ checkbox = self.web_find_elements(locator, timeout) for i in checkbox: if not i.is_selected(): i.click() def web_upload_file(self, locator, path, timeout=DEFAULT_TIMEOUT): """ | 功能说明: | 传入元素定位器,定位到该元素,传入文件路径,只适用于input标签 | | 输入参数: | locator | 元素路径 | | | path | 文件完整路径 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.06.01 | """ element = self.web_find_element(locator, timeout) element.send_keys(path) def web_move_windows(self, x=0, y=0): """ | 功能说明: | 传滑动窗口 | | 输入参数: | x | x轴距离 | | | y | y轴距离 | | 作者信息: | 谢祥益 | 2022.06.01 | """ self.driver.execute_script("window.scrollBy({},{})".format(x, y)) def web_go_to_previous_page(self): """ | 功能说明: | 返回上一页(浏览器工具栏向左箭头) | | 输入参数: | 无 | | 作者信息: | 谢祥益 at 2022.06.01 | """ self.driver.back() def web_go_to_next_page(self): """ | 功能说明: | 前进一页(浏览器工具栏向右箭头) | | 输入参数: | 无 | | 作者信息: | 谢祥益 at 2022.06.01 | """ self.driver.forward() def web_close_current_page(self): """ | 功能说明: | 关闭当前窗口页面 | | 输入参数: | 无 | | 作者信息: | 谢祥益 at 2022.06.01 | """ self.driver.close() def web_get_window_title(self): """ | 功能说明: | 获取当前浏览器标题 | | 输入参数: | 无 | | 作者信息: | 谢祥益 at 2022.06.01 | """ return self.driver.title def web_get_element_attribute_value(self, locator, attr: str, timeout=DEFAULT_TIMEOUT): """ | 功能说明: | 获取元素属性值 | | 输入参数: | locator | 元素路径 | | | attr | 属性名 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.06.01 | """ obj = self.web_find_element(locator, timeout=timeout) attr_value = obj.get_attribute(attr) return attr_value def web_modify_tag_attribution(self, locator, attr, value, timeout=DEFAULT_TIMEOUT): """ | 功能说明: | 修改页签属性 | | 输入参数: | locator | 元素路径 | | | attr | 修改属性名 | | | value | 修改后的值 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.06.01 | """ obj = self.web_find_element(locator, timeout) self.driver.execute_script("arguments[0].{attr}={value};".format(attr=attr, value=value), obj) def web_input_to_readonly_tag(self, locator, text, timeout=DEFAULT_TIMEOUT): """ | 功能说明: | 带只读属性的标签输入 | | 输入参数: | locator | 元素路径 | | | text | 输入内容 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.06.01 | """ obj = self.web_find_element(locator, timeout) self.driver.execute_script("arguments[0].removeAttribute('readonly');", obj) self.web_send_keys(locator=locator, text=text) def web_get_css_property_value(self, locator, css_property, timeout=DEFAULT_TIMEOUT): """ | 功能说明: | 获取css属性值 | | 输入参数: | locator | 元素路径 | | | text | 输入内容 | | | timeout | 超时时间,默认10秒 | | 作者信息: | 谢祥益 | 2022.07.08 | """ obj = self.web_find_element(locator, timeout) value = obj.value_of_css_property(css_property) return value def web_take_screenshot(self, save_path, picture_name): """ | 功能说明: | 截屏浏览器当前页面 | | 输入参数: | save_path | 保存地址 | | | picture_name | 图片名称 | | 作者信息: | 谢祥益 | 2022.06.01 | """ picture_path = os.path.join(save_path, picture_name + '.png') self.driver.get_screenshot_as_file(picture_path) def web_set_independent_environment(self): """ | 功能说明: | 设置独立环境 | | 输入参数: | 无 | | 作者信息: | 谢祥益 at 2022.06.01 | """ # 新增独立环境 new_loc = ('xpath', '/html/body/div/div[3]/button/div/div/i') # 独立环境名称 rule_name_loc = ('id', 'rule-name') # 规则类型 rule_type_loc = ('xpath', '//*[@id="edit-page"]/div[2]/div[1]/div/div[2]/div[2]/div[2]/div[3]/div') # 头名称 rule_header_name_loc = ('id', 'rule-headerName') # 头内容 rule_header_value_loc = ('id', 'rule-headerValue') # 保存 create_loc = ('xpath', '//*[@id="edit-page"]/div[2]/div[2]/div[2]/div[2]/button/div/div') self.driver.get("chrome-extension://eningockdidmgiojffjmkdblpjocbhgh/options/options.html") if self.jira_id and self.jira_id.lower()!='qa': rule_header_name = 'huohua-podenv' rule_header_value = self.jira_id self.web_click_element(new_loc) self.web_send_keys(rule_name_loc, self.jira_id) self.web_click_element(rule_type_loc) self.web_send_keys(rule_header_name_loc, rule_header_name) self.web_send_keys(rule_header_value_loc, rule_header_value) self.web_click_element(create_loc) rule_header_name = 'huohua-feature' rule_header_value = self.feature self.web_click_element(new_loc) self.web_send_keys(rule_name_loc, "front") self.web_click_element(rule_type_loc) self.web_send_keys(rule_header_name_loc, rule_header_name) self.web_send_keys(rule_header_value_loc, rule_header_value) self.web_click_element(create_loc) else: print("无独立环境!") def web_mouse_move_to_element(self, locator): """ | 功能 | 移动鼠标到元素位置 | | 入参 | locator | 元素xpath路径 | | 说明 | 多次刷新页面 | 容易导致此方法失效,慎用... | | | 必要时 | 可以尝试直接点击对应控件:web_click_element | """ self.action.reset_actions() obj = self.web_find_element(locator=locator) self.action.move_to_element(obj) self.action.perform() def web_mouse_click(self): """功能:模拟鼠标点击""" self.action.click().perform() # self.action.perform() def web_check_element_exist(self, locator, quantity=1): """ | 功能说明: | 检查页面元素是否存在:0-不存在,1-存在,>1-存在多少个,-1-仅判断存在不判断数量 | | 输入参数: | locator | 元素路径 | | | quantity | 对应locator的元素有多少个, 传入-1则仅检查存在,不判断数量 | | 作者信息: | 吴勇刚 | 2022.08.01 | """ if int(quantity) == 0: # 当检查元素不存在时,设计设置为2秒 time_out = 2 else: time_out = DEFAULT_TIMEOUT elements = self.web_find_elements(locator=locator, raise_exception=False, timeout=time_out) if quantity != -1: if len(elements) != int(quantity): raise Exception("the element [{}] expect exist {},but current is {}..." .format(locator, quantity, len(elements))) else: if len(elements) == 0: raise Exception("the element is not exist:{}...".format(locator)) def web_check_element_text(self, locator, exp_text): """ | 功能说明: | 检查源文本是否正确 | 转为字符串比较 | | 输入参数: | locator | 元素路径 | | | exp_text | 元素预期文本 | | 作者信息: | 吴勇刚 | 2022.08.01 | """ act_text = self.web_get_element_text(locator=locator) if act_text != str(exp_text): raise Exception("The element [{}]'s text expect [{}],bug now it's [{}] " .format(locator, exp_text, act_text)) def web_check_element_attribute(self, locator, attr_name, exp_value): """ | 功能说明: | 检查元素属性值是否正确 | | 输入参数: | locator | 元素路径 | | | attr_name | 元素属性名称 | | | exp_value | 元素预期属性值 | | 作者信息: | 吴勇刚 | 2022.08.01 | """ act_value = self.web_get_element_attribute_value(locator=locator, attr=attr_name) if act_value != exp_value: raise Exception("The element [{}] attribute [{}]'s value expect [{}],bug now it's [{}] " .format(locator, attr_name, exp_value, act_value)) def web_get_current_url(self): """ | 功能说明: | 检查源文本是否正确 | 转为字符串比较 | | 输入参数: | locator | 元素路径 | | | exp_text | 元素预期文本 | | 作者信息: | 吴勇刚 | 2022.08.01 | """ current_url = self.driver.current_url return current_url if __name__ == '__main__': web_driver = SeleniumWebUI() vispark_url = "https://sparkle.qa.huohua.cn/intl/schedule" web_driver.web_open_url(url=vispark_url) url = web_driver.web_get_current_url() print(url) web_driver.web_close_browser()