diff options
| author | zhaokun <[email protected]> | 2023-11-08 13:44:25 +0800 |
|---|---|---|
| committer | zhaokun <[email protected]> | 2023-11-08 13:44:25 +0800 |
| commit | 4e683d5703daf29810097b9961b5ce02420202ea (patch) | |
| tree | 4ad01d46a7417a14a8c8a9045e95d0387cf24388 /common | |
| parent | 44ed57c3f0b5f83e2836aadeea34003f08867b08 (diff) | |
updatemain
Diffstat (limited to 'common')
44 files changed, 2200 insertions, 0 deletions
diff --git a/common/__init__.py b/common/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/common/__init__.py diff --git a/common/__pycache__/__init__.cpython-38.pyc b/common/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..13af0213 --- /dev/null +++ b/common/__pycache__/__init__.cpython-38.pyc diff --git a/common/__pycache__/demo_1.cpython-38.pyc b/common/__pycache__/demo_1.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..b74fe3a6 --- /dev/null +++ b/common/__pycache__/demo_1.cpython-38.pyc diff --git a/common/__pycache__/read_data.cpython-38.pyc b/common/__pycache__/read_data.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..22ea7626 --- /dev/null +++ b/common/__pycache__/read_data.cpython-38.pyc diff --git a/common/demo_1.py b/common/demo_1.py new file mode 100644 index 00000000..e5fcd4f7 --- /dev/null +++ b/common/demo_1.py @@ -0,0 +1,23 @@ +import pytest +import requests +import time + + +def demo1(): + assert 1 == 11 + +def demo2(data): + print(f"demo2使用数据{data}") + assert 2 == 2 + +class DemoA: + def __init__(self): + self.n = 1 + + def demo3(self, data): + print(f"demo3使用数据{data}") + assert 3 == 3 + + def demo4(self, data): + print(f"demo4使用数据{data}") + assert 4 == 4
\ No newline at end of file diff --git a/common/driver_common/__init__.py b/common/driver_common/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/common/driver_common/__init__.py diff --git a/common/driver_common/__pycache__/__init__.cpython-38.pyc b/common/driver_common/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..38bc323b --- /dev/null +++ b/common/driver_common/__pycache__/__init__.cpython-38.pyc diff --git a/common/driver_common/__pycache__/mywebdriver.cpython-38.pyc b/common/driver_common/__pycache__/mywebdriver.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..8e258f8b --- /dev/null +++ b/common/driver_common/__pycache__/mywebdriver.cpython-38.pyc diff --git a/common/driver_common/__pycache__/random_name.cpython-38.pyc b/common/driver_common/__pycache__/random_name.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..ce517551 --- /dev/null +++ b/common/driver_common/__pycache__/random_name.cpython-38.pyc diff --git a/common/driver_common/__pycache__/screenshot.cpython-38.pyc b/common/driver_common/__pycache__/screenshot.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..1c1f63c7 --- /dev/null +++ b/common/driver_common/__pycache__/screenshot.cpython-38.pyc diff --git a/common/driver_common/mywebdriver.py b/common/driver_common/mywebdriver.py new file mode 100644 index 00000000..cb8dadaf --- /dev/null +++ b/common/driver_common/mywebdriver.py @@ -0,0 +1,58 @@ +import time +import traceback +import inspect +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.support.wait import WebDriverWait +from typing import Optional + + +class MyWebDriver(webdriver.Remote): + def find_element(self, by=By.ID, value: Optional[str] = None, + find_before_wait_time=0.3, find_after_wait_time=0.3, wait_timeout=10): + if wait_timeout > 60: + wait_timeout = 60 + while wait_timeout > 0: + time.sleep(find_before_wait_time) + wait_timeout = wait_timeout - (find_before_wait_time if find_before_wait_time > 0 else 2.5) + try: + self.element = super().find_element(by, value) + except: + caller_info = inspect.stack()[1] + caller_filename = caller_info.filename + caller_line_number = caller_info.frame + caller_code_context = caller_info.code_context + print(caller_filename, caller_line_number, caller_code_context) + print(f"查找方法:{by};-->>", f"查找元素:{value}\n") + throw_assert = 1 + assert_info = traceback.format_exc() + continue + else: + time.sleep(find_after_wait_time) + throw_assert = 0 + break #找到则退出循环 + if throw_assert == 1: + print(assert_info) + raise + return self.element + + + +if __name__ == '__main__': + chrome_option = webdriver.ChromeOptions() + driver = MyWebDriver( + command_executor="http://192.168.64.34:4444", + options=chrome_option + ) + driver.implicitly_wait(5) + driver.get("http://192.168.44.72") + driver.find_element(By.NAME, "username1").send_keys("zcw3") + driver.find_element(By.NAME, "username").send_keys("zcw3") + driver.find_element(By.NAME, "username").send_keys("zcw3") + driver.find_element(By.NAME, "username").send_keys("zcw3") + driver.find_element(By.NAME, "password").send_keys("111111") + driver.find_element(By.NAME, "password").send_keys("111111") + driver.find_element(By.NAME, "password").send_keys("111111") + driver.find_element(By.NAME, "password").send_keys("111111") + + driver.quit() diff --git a/common/driver_common/random_name.py b/common/driver_common/random_name.py new file mode 100644 index 00000000..8f5327f0 --- /dev/null +++ b/common/driver_common/random_name.py @@ -0,0 +1,48 @@ +import random +import string +import time +import datetime + +class RandomName: + """ + 生成随机使用名称 + """ + def __init__(self, pro_name="test_uitemp", r_letter_count=8, r_number_count=8): + self.pro_name = pro_name + self.r_letter_count = r_letter_count + self.r_number_count = r_number_count + + def random_name(self): + letters = self.random_letter(self.r_letter_count) + numbers = self.random_number(self.r_number_count) + format_time = self.current_time() + r_name = f"{self.pro_name}_{letters}_{numbers}_{format_time}" + return r_name + + def random_letter(self, count=8): + temp_list = [] + for i in range(count): + temp_list.append(random.choice(string.ascii_letters)) + r_letter = "".join(temp_list) + #print(r_letter) + return r_letter + + def random_number(self, count=8): + temp_list = [] + for i in range(count): + temp_list.append(random.choice(string.digits)) + r_number = "".join(temp_list) + #print(r_number) + return r_number + + def current_time(self): + c_time = time.time() + formatted_time = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d-%H-%M-%S') + return formatted_time + +# r = RandomName() +# c = r.random_name() +# print(c) +# print(c) +# print(c) + diff --git a/common/driver_common/recovery.py b/common/driver_common/recovery.py new file mode 100644 index 00000000..b982faa9 --- /dev/null +++ b/common/driver_common/recovery.py @@ -0,0 +1,25 @@ +import configparser +from config.workpath import * +import requests + + +class Recovery: + """ + 自动回收异常时,产生的创建对象 + 从接口来删除对象 + """ + def __init__(self): + #初始化,负载远程用户登录 + self.loginout_parse = configparser.ConfigParser() + loginout_parse_dir = os.path.join(workdir, "config", "ui_conf", "loginout.ini") + self.loginout_parse.read(loginout_parse_dir, encoding="utf-8") + self.username = self.loginout_parse.get("ui_account_1", "username") + self.passwd = self.loginout_parse.get("ui_account_1", "passwd") + + def login_by_interface(self): + #todo + pass + + def del_profile(self): + # todo + pass diff --git a/common/driver_common/screenshot.py b/common/driver_common/screenshot.py new file mode 100644 index 00000000..84c00968 --- /dev/null +++ b/common/driver_common/screenshot.py @@ -0,0 +1,39 @@ +from selenium import webdriver +import shutil +import time, datetime +import os +import functools +from config.workpath import workdir + +#截图装饰器 +def screenshot_on_failure(func): + @functools.wraps(func) + def warpper(self, *args, **kwargs): + try: + return func(self, *args, **kwargs) + except: + driver = self.driver + if driver: + formatted_time = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d-%H-%M-%S') + file = "{}.png".format(formatted_time) + file_path = os.path.join(workdir, "results", "screenshot", file) + print(f"截图保存于:{file_path}") + driver.save_screenshot(file_path) + #删除历史7天前数据 + try: + clear_history(file_path) + except: + print("删除历史数据失败...") + raise + return warpper + +def clear_history(file_path, retain_time=3600*24*1): + time_now = time.time() + file_work = os.path.dirname(file_path) + data_list = [os.path.join(file_work, i) for i in os.listdir(file_work)] + for datapath in data_list: + if time_now - os.path.getctime(datapath) > retain_time: + try: + os.remove(datapath) + except: + shutil.rmtree(datapath) diff --git a/common/read_data.py b/common/read_data.py new file mode 100644 index 00000000..69d6478c --- /dev/null +++ b/common/read_data.py @@ -0,0 +1,16 @@ +import json + +class ReadData: + def __init__(self): + print(__file__) + + @property + def read_from_json(self): + with open("C:/zcw/aoto_selenium/testdata/demo1_data.json", "r") as f: + data = json.load(f)["item"] + data = list(data) + return data + + +if __name__ == '__main__': + ReadData().read_from_json
\ No newline at end of file diff --git a/common/ui_common/__init__.py b/common/ui_common/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/common/ui_common/__init__.py diff --git a/common/ui_common/__pycache__/__init__.cpython-38.pyc b/common/ui_common/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..3c247a2f --- /dev/null +++ b/common/ui_common/__pycache__/__init__.cpython-38.pyc diff --git a/common/ui_common/login_logout/__init__.py b/common/ui_common/login_logout/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/common/ui_common/login_logout/__init__.py diff --git a/common/ui_common/login_logout/__pycache__/__init__.cpython-38.pyc b/common/ui_common/login_logout/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..d7ef9377 --- /dev/null +++ b/common/ui_common/login_logout/__pycache__/__init__.cpython-38.pyc diff --git a/common/ui_common/login_logout/__pycache__/loginout.cpython-38.pyc b/common/ui_common/login_logout/__pycache__/loginout.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..56aba1be --- /dev/null +++ b/common/ui_common/login_logout/__pycache__/loginout.cpython-38.pyc diff --git a/common/ui_common/login_logout/loginout.py b/common/ui_common/login_logout/loginout.py new file mode 100644 index 00000000..f09ddcb2 --- /dev/null +++ b/common/ui_common/login_logout/loginout.py @@ -0,0 +1,26 @@ +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +import configparser +from config.workpath import * +from page_element.element_position import * + +class LogInOut: + def __init__(self, driver: MyWebDriver): + self.driver = driver + #初始化,负载远程用户登录 + self.loginout_parse = configparser.ConfigParser() + loginout_parse_dir = os.path.join(workdir, "config", "ui_conf", "loginout.ini") + self.loginout_parse.read(loginout_parse_dir, encoding="utf-8") + self.tsglogin_url = self.loginout_parse.get("tsg_url", "login_url") + + def login(self): + self.driver.get(self.tsglogin_url) + #输入账户和密码 + self.driver.find_element(By.NAME, loginPage_userName_posName).send_keys(self.loginout_parse.get("ui_account_1", "username")) + self.driver.find_element(By.NAME, loginPage_passwd_posName).send_keys(self.loginout_parse.get("ui_account_1", "passwd")) + self.driver.find_element(By.ID, loginPage_signIn_posId).click() + + def logout(self): + pass + + diff --git a/common/ui_common/profiles/Dos_detection.py b/common/ui_common/profiles/Dos_detection.py new file mode 100644 index 00000000..ada88436 --- /dev/null +++ b/common/ui_common/profiles/Dos_detection.py @@ -0,0 +1,248 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect + + +class Dos_detection: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + + def Dos_detection_case(self, data: {}): + """ + 测试用例调用函数, + :param demo_fixture: 传入driver + :param data: 测试数据。 + + :return: + """ + #self.driver = demo_fixture + self._create(data) #创建 + self._query(data, require_assertion=1, Name=self.random_name) #创建后查询 + if data["model"].strip().lower() == "modify": #修改测试时,执行修改方法 + self._modify(data) + self._query(data, require_assertion=2, ID=self.first_row_ID_content) # 修改后查询 + self._del() #删除数据 + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到shapingProfiles列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_shapingProfiles_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #页面跳转 + self._goto_subProfilePage() + #创建shapingProfiles + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_shapingProfiles_createButton_posId).click() + #在create dns shapingProfiles操作 + self.driver.find_element(By.ID, shapingProfilePage_input_Name_posId).send_keys(self.random_name) #输入名字 + #判断点击哪种类型 + self._select_type(data) + self._select_limits(data, model=0) + #点击ok + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_warningSaveYes_posCss).click() + return self.random_name + + @screenshot_on_failure + def _a(self, data: {}): + print(__name__) + 1 == 1 + return 444 + + @screenshot_on_failure + def _select_type(self, data: {}): + """ + 选择type类型点击 + :param data: + :return: + """ + type: str = data["type"].strip().lower() + argument: str = data["argument"].strip().lower() + if type == "generic": + element_type_pos = shapingProfilePage_radioButton_generic_posXpath + elif type == "fair share": + element_type_pos = shapingProfilePage_radioButton_fairShare_posXpath + if argument == "Max Min Host Fairness".lower(): + element_argument_pos = shapingProfilePage_radioButton_maxMinHostFairness_posXpath + else: + raise ValueError(f"用例参数argument:{argument}") + else: + element_type_pos = shapingProfilePage_radioButton_splitBy_posXpath + if argument == "Local Host".lower(): + element_argument_pos = shapingProfilePage_radioButton_localHost_posXpath + else: + raise ValueError(f"用例参数argument:{argument}") + #点击type类型 + self.driver.find_element(By.XPATH, element_type_pos).click() + #判断是否点击Argument + if type != "generic": + self.driver.find_element(By.XPATH, element_argument_pos).click() + + @screenshot_on_failure + def _select_limits(self, data: {}, model=0): + """ + 输入limits + :param data: + :param model: =0表示创建时调用。-1表示修改时调用 + :return: + """ + unitItem = data["unit"].strip().split("->")[model] + element_dropDown_unitItem = shapingProfilePage_drowDown_unitItem_posXpath.format(replaceName=unitItem) + #点击Unit并选择单位 + self.driver.find_element(By.ID, shapingProfilePage_inputSelect_unit_posId).click() + self.driver.find_element(By.XPATH, element_dropDown_unitItem).click() + #输入incoming、outgoing + input_incoming = data["incoming"].strip().split("->")[model] + input_outgoing = data["outgoing"].strip().split("->")[model] + self.driver.find_element(By.ID, shapingProfilePage_input_incoming_posId).clear() + self.driver.find_element(By.ID, shapingProfilePage_input_incoming_posId).send_keys(input_incoming) + self.driver.find_element(By.ID, shapingProfilePage_input_outgoing_posId).clear() + self.driver.find_element(By.ID, shapingProfilePage_input_outgoing_posId).send_keys(input_outgoing) + + @screenshot_on_failure + def _query(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None, + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_shapingProfiles_selectLabel_posId, listPage_profileSearch_shapingProfiles_dropDown_item_posXpath, + listPage_profileSearch_shapingProfiles_input_itemContent_posXpath, listPage_profileSearch_shapingProfiles_buttonSearch_posId, + listPage_profilTable_shapingProfiles_tableTbody_posXpath, listPage_profilTable_shapingProfiles_tableHeader_posXpath, **kwargs) + """ + #点击search查询框 + self.driver.find_element(By.ID, listPage_profileSearch_shapingProfiles_selectLabel_posId).click() + #循环输入查询内容 + for key, value in kwargs.items(): + dropdown_item_posXpath = listPage_profileSearch_shapingProfiles_dropDown_item_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, dropdown_item_posXpath).click() #点击下拉item + if key != "type": + input_item_posXpath = listPage_profileSearch_shapingProfiles_input_itemContent_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, input_item_posXpath).send_keys(value.strip()) #输入查询值 + else: + pass + # dropdown_typeItem_posXpath = listPage_profileSearch_dnsRecords_dropDown_typeItem_posXpath.format(replaceName=value.split("->")[0]) + # self.driver.find_element(By.XPATH, dropdown_typeItem_posXpath).click() #点击type的下拉item + #点击查询按钮 + element_search = self.driver.find_element(By.ID, listPage_profileSearch_shapingProfiles_buttonSearch_posId) + self.driver.execute_script("arguments[0].click()", element_search) #强制点击 + element_tbody = self.driver.find_element(By.XPATH, listPage_profilTable_shapingProfiles_tableTbody_posXpath) #找到所有的行,table的body + element_header = self.driver.find_element(By.XPATH, listPage_profilTable_shapingProfiles_tableHeader_posXpath) #查询table的header + #获取table header的text、th.class + headers = element_header.find_elements(By.XPATH, "th") #table header + rows = element_tbody.find_elements(By.XPATH, "tr") #table body + map_header_className = {} #表头名称和th.class的映射,为了从表body中取对应列的值{"ID":"33"} + for th in headers: + header_content = th.text.strip() + classNames = th.get_attribute("class").split() + for c_name in classNames: + if "el-table" in c_name: + tableBodyRowClassName = c_name + if header_content and tableBodyRowClassName: + map_header_className[header_content] = tableBodyRowClassName + #从第一行查询的结果中,取出需要断言的值、name、Type、Values + first_row = rows[0] + """ + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + first_row_Type_class = map_header_className["Type"] + first_row_Type_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Type_class}')]//span").text.strip() + first_row_IncomingOutgoing_class = map_header_className["Incoming/Outgoing"] + first_row_IncomingOutgoing_contents = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_IncomingOutgoing_class}')]//span").text.strip() + + print(first_row_id_content, first_row_Name_content, first_row_Type_content, first_row_IncomingOutgoing_contents) + #不同操作后的断言,创建后、修改后、无断言 + if require_assertion == 1: #直接创建后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.equal(first_row_Type_content, data["type"].strip(), msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["outgoing"].strip().split("->")[0] == "0": #为0时,直接断言Unlimit + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["outgoing"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["incoming"].strip().split("->")[0] == "0": + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["incoming"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.equal(first_row_Type_content, data["type"].split("->")[-1], msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["outgoing"].strip().split("->")[-1] == "0": #为0时,直接断言Unlimit + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["outgoing"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["incoming"].strip().split("->")[-1] == "0": + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["incoming"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_shapingProfiles_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_shapingProfiles_editButton_posId).click() + #根据修改数据,重新输入limits + self._select_limits(data, model=-1) + #点击ok + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_shapingProfiles_delButton_posId, listPage_dialogTips_shapingProfiles_button_yes_posCss, + listPage_dialogTips_shapingProfiles_button_no_posCss) + + create = _create + query = _query + modify = _modify + delete = _del diff --git a/common/ui_common/profiles/__init__.py b/common/ui_common/profiles/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/common/ui_common/profiles/__init__.py diff --git a/common/ui_common/profiles/__pycache__/__init__.cpython-38.pyc b/common/ui_common/profiles/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..12f4a2fb --- /dev/null +++ b/common/ui_common/profiles/__pycache__/__init__.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/dns_records.cpython-38.pyc b/common/ui_common/profiles/__pycache__/dns_records.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..5a164705 --- /dev/null +++ b/common/ui_common/profiles/__pycache__/dns_records.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/hijack_files.cpython-38.pyc b/common/ui_common/profiles/__pycache__/hijack_files.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..687f3e13 --- /dev/null +++ b/common/ui_common/profiles/__pycache__/hijack_files.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/profiles_public_operations.cpython-38.pyc b/common/ui_common/profiles/__pycache__/profiles_public_operations.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..ae34623c --- /dev/null +++ b/common/ui_common/profiles/__pycache__/profiles_public_operations.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/response_pages.cpython-38.pyc b/common/ui_common/profiles/__pycache__/response_pages.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..f8f10cef --- /dev/null +++ b/common/ui_common/profiles/__pycache__/response_pages.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/shaping_profiles.cpython-38.pyc b/common/ui_common/profiles/__pycache__/shaping_profiles.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..beae1dcf --- /dev/null +++ b/common/ui_common/profiles/__pycache__/shaping_profiles.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/ssl_decryption_keyrings.cpython-38.pyc b/common/ui_common/profiles/__pycache__/ssl_decryption_keyrings.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..11cf401b --- /dev/null +++ b/common/ui_common/profiles/__pycache__/ssl_decryption_keyrings.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/ssl_decryption_profiles.cpython-38.pyc b/common/ui_common/profiles/__pycache__/ssl_decryption_profiles.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..e26b49a4 --- /dev/null +++ b/common/ui_common/profiles/__pycache__/ssl_decryption_profiles.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/traffic_mirroring_profiles.cpython-38.pyc b/common/ui_common/profiles/__pycache__/traffic_mirroring_profiles.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..6a9287a9 --- /dev/null +++ b/common/ui_common/profiles/__pycache__/traffic_mirroring_profiles.cpython-38.pyc diff --git a/common/ui_common/profiles/dns_records.py b/common/ui_common/profiles/dns_records.py new file mode 100644 index 00000000..f07116c3 --- /dev/null +++ b/common/ui_common/profiles/dns_records.py @@ -0,0 +1,288 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect + + +class DnsRecords: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + + def dns_records_case(self, data: {}): + """ + 测试用例调用函数, + :param demo_fixture: 传入driver + :param data: 测试数据。 + 例如:create. + { + "model":"create", + "type":"A", + "values": + [ + "2.2.2.2", + "3.3.3.3", + "4.4.4.4" + ] + } + 例如:modify."12.12.12.12->34.45.67.54"表示修改前后数据,'->'为前后数据分隔符。在修改中,分隔符前为空表示新增数据。分隔符后为空表示删除数据。其它同理 + { + "ids": "创建多个类型A,再修改为多个类型A用例", + "model": "modify", + "type": "A->A", + "values": + [ + "12.12.12.12->34.45.67.54", + "13.13.31.13->", + "->65.123.34.56", + "14.14.14.41->56.43.46.64", + "->165.123.134.56" + ], + "description": "test-description->tesst modify desc" + } + :return: + """ + self._create(data) #创建 + self._search(data, require_assertion=1, Name=self.random_name) #创建后查询 + self._modify(data) + self._search(data, require_assertion=2, ID=self.first_row_ID_content) # 修改后查询 + self._del() #删除数据 + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到dnsRecords列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_dnsRecords_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #goto dnsRecords列表页 + self._goto_subProfilePage() #跳转页面 + #创建dns record + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_dnsRecords_createButton_posId).click() + #在create dns record profile操作 + self.driver.find_element(By.ID, dnsRecordsProfilePage_input_Name_posId).send_keys(self.random_name) #输入名字 + #判断点击哪种类型 + self._select_type(data, model=0) + #创建time操作 + self._ceate_item(data, model=0) + #输入description内容 + self.driver.find_element(By.ID, dnsRecordsProfilePage_textArea_Description_posId).send_keys(data["description"].split("->")[0]) + self.driver.find_element(By.CSS_SELECTOR, dnsRecordsProfilePage_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, dnsRecordsProfilePage_button_warningSaveYes_posCss).click() + return self.random_name + + def _select_type(self, data, model=0): + """ + 根据model参数,选择点击那种类型,0为创建函数使用,-1为编辑修改函数使用 + :param data: + :param model: + :return: + """ + type: str = data["type"].split("->")[model] #因为modify时,有->表示 + type = type.strip().lower() + if type == "a": + type_posId = dnsRecordsProfilePage_radioButton_typeA_posId + elif type == "aaaa": + type_posId = dnsRecordsProfilePage_radioButton_typeAAAA_posId + else: + type_posId = dnsRecordsProfilePage_radioButton_typeCNAME_posId + self.driver.find_element(By.ID, type_posId).click() + + def _ceate_item(self, data, model=0): + """ + 根据参数,选择创建item的方式,0为创建函数使用。-1为编辑修改函数使用且当type类型和创建时不一样。 + :param data: + :param model: + :return: + """ + items: list = data["values"] + flags = 0 #当一个非空数据时,不点击添加按钮 + for i in range(len(items)): + if items[i].split("->")[model] == "": #modify数据中->左侧为空(创建侧) + continue + #判断是否需要点击添加按钮 + if items[i].split("->")[model] != "": + flags += 1 #第一个非空标志 + if flags == 1: #遇到第一个分空数据,不用点击 + pass + else: #第二个后续的非空数据,点击添加 + self.driver.find_element(By.ID, dnsRecordsProfilePage_button_addItem_posId).click() + #添加item时,text()=空,xpath可以定位到 + if "replaceName" in dnsRecordsProfilePage_input_inputItemName_posXpath: + item_input_posCss = dnsRecordsProfilePage_input_inputItemName_posXpath.replace("replaceName", "") + else: + raise ValueError(f"replaceName not found in {dnsRecordsProfilePage_input_inputItemName_posXpath}") + if "replaceName" in dnsRecordsProfilePage_button_saveItemByName_posXpath: + item_save_posCss = dnsRecordsProfilePage_button_saveItemByName_posXpath.replace("replaceName", items[i].split("->")[model]) #->修改中会此表标识 + else: + raise ValueError(f"replaceName not found in {dnsRecordsProfilePage_button_saveItemByName_posXpath}") + #输出item、保存、添加下一个 + self.driver.find_element(By.XPATH, item_input_posCss).send_keys(items[i].split("->")[model]) + self.driver.find_element(By.XPATH, item_save_posCss).click() + + def _modify_item(self, data): + """ + 修改的item数据,type类型前后一样 + :param data: + :return: + """ + items: list = data["values"] + for i in range(len(items)): + if items[i].split("->")[-1] == "": #modify数据中->右侧为空(删除此数据) + element_item_del = dnsRecordsProfilePage_button_delItemByName_posXpath.replace("replaceName", items[i].split("->")[0]) + self.driver.find_element(By.XPATH, element_item_del).click() + continue + if items[i].split("->")[0] == "": #modify数据中->做侧为空(创建的数据为空,直接添加item) + self.driver.find_element(By.ID, dnsRecordsProfilePage_button_addItem_posId).click() #点击添加按钮 + # 添加item时,text()=空,xpath可以定位到 + item_input_posCss = dnsRecordsProfilePage_input_inputItemName_posXpath.replace("replaceName", "") + item_save_posCss = dnsRecordsProfilePage_button_saveItemByName_posXpath.replace("replaceName", items[i].split("->")[-1]) # ->修改中会此表标识 + # 输入item,保存 + self.driver.find_element(By.XPATH, item_input_posCss).send_keys(items[i].split("->")[-1]) + self.driver.find_element(By.XPATH, item_save_posCss).click() + continue + #直接编辑item项内容,在原有的item中编辑值 + item_edit_posCss = dnsRecordsProfilePage_button_editItemByName_posXpath.replace("replaceName", items[i].split("->")[0]) + item_input_posCss = dnsRecordsProfilePage_input_inputItemName_posXpath.replace("replaceName", items[i].split("->")[0]) + self.driver.find_element(By.XPATH, item_edit_posCss).click() + self.driver.find_element(By.XPATH, item_input_posCss).clear() + self.driver.find_element(By.XPATH, dnsRecordsProfilePage_input_inputItemName_posXpath.replace("replaceName", "")).send_keys(items[i].split("->")[-1]) + self.driver.find_element(By.XPATH, dnsRecordsProfilePage_button_saveItemByName_posXpath.replace("replaceName", items[i].split("->")[-1])).click() + + @screenshot_on_failure + def _search(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None,Type=None("A") + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_dnsRecords_selectLabel_posId, listPage_profileSearch_dnsRecords_dropDown_item_posXpath, + listPage_profileSearch_dnsRecords_input_itemContent_posXpath, listPage_profileSearch_dnsRecords_buttonSearch_posId, + listPage_profilTable_dnsRecords_tableTbody_posXpath, listPage_profilTable_dnsRecords_tableHeader_posXpath, + listPage_profileSearch_subProfiles_dropDown_typeItem_posXpath=listPage_profileSearch_dnsRecords_dropDown_typeItem_posXpath, **kwargs) + """ + #点击search查询框 + self.driver.find_element(By.ID, listPage_profileSearch_dnsRecords_selectLabel_posId).click() + #循环输入查询内容 + for key, value in kwargs.items(): + dropdown_item_posXpath = listPage_profileSearch_dnsRecords_dropDown_item_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, dropdown_item_posXpath).click() #点击下拉item + if key != "type": + input_item_posXpath = listPage_profileSearch_dnsRecords_input_itemContent_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, input_item_posXpath).send_keys(value.split("->")[0]) #输入查询值 + else: + dropdown_typeItem_posXpath = listPage_profileSearch_dnsRecords_dropDown_typeItem_posXpath.format(replaceName=value.split("->")[0]) + self.driver.find_element(By.XPATH, dropdown_typeItem_posXpath).click() #点击type的下拉item + #点击查询按钮 + element_search = self.driver.find_element(By.ID, listPage_profileSearch_dnsRecords_buttonSearch_posId) + self.driver.execute_script("arguments[0].click()", element_search) #强制点击 + element_tbody = self.driver.find_element(By.XPATH, listPage_profilTable_dnsRecords_tableTbody_posXpath) #找到所有的行,table的body + element_header = self.driver.find_element(By.XPATH, listPage_profilTable_dnsRecords_tableHeader_posXpath) #查询table的header + #获取table header的text、th.class + headers = element_header.find_elements(By.XPATH, "th") #table header + rows = element_tbody.find_elements(By.XPATH, "tr") #table body + map_header_className = {} #表头名称和th.class的映射,为了从表body中去对应列的值{"ID":"33"} + for th in headers: + header_content = th.text.strip() + classNames = th.get_attribute("class").split() + for c_name in classNames: + if "el-table" in c_name: + tableBodyRowClassName = c_name + if header_content and tableBodyRowClassName: + map_header_className[header_content] = tableBodyRowClassName + #从第一行查询的结果中,取出需要断言的值、name、Type、Values + first_row = rows[0] + """ + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + first_row_Type_class = map_header_className["Type"] + first_row_Type_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Type_class}')]//span").text.strip() + first_row_Values_class = map_header_className["Values"] + first_row_Values_contents = first_row.find_elements(By.XPATH, f"//td[contains(@class, '{first_row_Values_class}')]//span//span") + values_list = [] + for value in first_row_Values_contents: + values_list.append(value.text.strip()) + print(first_row_id_content, first_row_Name_content, first_row_Type_content, values_list) + #不同操作后的断言,创建后、修改后、无断言 + if require_assertion == 1: #直接创建后,使用的断言 + create_values_list = [i.split("->")[0] for i in data["values"] if i.split("->")[0] != ""] # 兼容modify中->的标识值 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.equal(first_row_Type_content, data["type"].split("->")[0], msg="所在行数{}".format(inspect.currentframe().f_lineno)) + for i in range(len(values_list)): + pytest_check.is_in(values_list[i], create_values_list, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + create_values_list = [i.split("->")[-1] for i in data["values"] if i.split("->")[-1] != ""] # modify中修改的数据->的右侧 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.equal(first_row_Type_content, data["type"].split("->")[-1], msg="所在行数{}".format(inspect.currentframe().f_lineno)) + for i in range(len(values_list)): + pytest_check.is_in(values_list[i], create_values_list, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_dnsRecords_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_dnsRecords_editButton_posId).click() + #根据修改数据,判断type类型 + self._select_type(data, model=-1) + if data["type"].split("->")[0].lower() != data["type"].split("->")[1].lower(): #创建和修改参数的type类型不一致 + self._ceate_item(data, model=-1) + else: + self._modify_item(data) + #修改description内容 + self.driver.find_element(By.ID, dnsRecordsProfilePage_textArea_Description_posId).clear() + self.driver.find_element(By.ID, dnsRecordsProfilePage_textArea_Description_posId).send_keys(data["description"].split("->")[-1]) + self.driver.find_element(By.CSS_SELECTOR, dnsRecordsProfilePage_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, dnsRecordsProfilePage_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, dnsRecordsProfilePage_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_dnsRecords_delButton_posId, listPage_dialogTips_dnsRecords_button_yes_posCss, + listPage_dialogTips_dnsRecords_button_no_posCss) + + create = _create + query = _search + modify = _modify + delete = _del diff --git a/common/ui_common/profiles/hijack_files.py b/common/ui_common/profiles/hijack_files.py new file mode 100644 index 00000000..82a031c5 --- /dev/null +++ b/common/ui_common/profiles/hijack_files.py @@ -0,0 +1,224 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect +import configparser +import os + + +class HijackFiles: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + + def hijackFiles_case(self, data: {}): + self._create(data) #创建 + self._query(data, require_assertion=1, Name=self.random_name) #创建后查询 + if data["model"].strip().lower() == "modify": #修改测试时,执行修改方法 + self._modify(data) + self._query(data, require_assertion=2, ID=self.first_row_ID_content) + self._del() + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到ssl_decryption_keyrings列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_hijackFiles_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #页面跳转 + self._goto_subProfilePage() + #创建 + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_hijackFiles_createButton_posId).click() + #在打开页面操作:输入name + self.driver.find_element(By.ID, hijackFiles_input_Name_posId).send_keys(self.random_name) + #页面其它选项操作 + self._operate_page(data, operation_type="create") + #点击OK + self.driver.find_element(By.CSS_SELECTOR, hijackFiles_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, hijackFiles_button_warningSaveYes_posCss).click() + return self.random_name + + def _operate_page(self, data: {}, operation_type="create"): + """ + 除name的其它选项操作,共创建、修改逻辑调用 + :param data: + :param operation_type: create modify。创建 修改时调用 + :return: + """ + if operation_type == "create": + data_index = 0 #新增数据索引 + else: + data_index = -1 #编辑数据索引 + no_modify = "不修改" + #解析输入data数据的数据 + #File文件上传操作 + file = self._get_value_from_data(data, key="file", data_index=data_index) #解析file文件名称 + if file != no_modify: #判断修改时不修改时跳过操作。 + file_abspath = self._abs_path(file) + #上传文件 + self.driver.find_element(By.XPATH, hijackFiles_input_fileUpLoad_posXpath).send_keys(file_abspath) + #download name 下载文件名称操作 + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="download_name", element_position=hijackFiles_switch_downLoadName_posXpath) + #file type 文件类型操作 + file_type = self._get_value_from_data(data, key="file_type", data_index=data_index) + if file_type != no_modify: #修改时不用修改数据直接跳过 + #点击type添加按钮 + self.driver.find_element(By.XPATH, hijackFiles_button_fileType_posXpath).click() + element_type_replace_name = {'gif': 'image/gif', 'jpeg': 'image/jpeg', 'png': 'image/png', 'svg+xml': 'image/svg+xml', + 'exe': 'application/x-msdos-program', 'apk': 'application/vnd.android.package-archive', 'html': 'text/html'} + if file_type not in element_type_replace_name.keys(): + raise f"文件类型错误。用例数据类型为:{file_type}, 可选择文件类型为:{list(element_type_replace_name.keys())}" + element_tablist_type = self.driver.find_element(By.XPATH, hijackFiles_tablist_fileType_posXpath.format(replaceName=element_type_replace_name[file_type])) + self.driver.execute_script("arguments[0].click()", element_tablist_type) # 强制点击 + + def _abs_path(self, file_name): + # 以下是要读取数据的名称 + conf = configparser.ConfigParser() + loginout_parse_dir = os.path.join(self.workdir, "config", "ui_conf", "importfile.ini") + conf.read(loginout_parse_dir, encoding="utf-8") + testdata = conf.get("profiles", "testdata") + ui_file = conf.get("profiles", "ui_file") + profiles = conf.get("profiles", "profiles") + hijack_files = conf.get("profiles", "hijack_files") + import_file_abs = os.path.join(self.workdir, testdata, ui_file, profiles, hijack_files, file_name) + import_file_abs = os.path.abspath(import_file_abs) + return import_file_abs + + def _get_value_from_data(self, data: {}, key="", data_index=0): + """ + 从data数据中,根据key提取值 + :param data: + :param key: + :param data_index: 0 -1 + :return: + """ + try: + switch_value: str = data[key].split("->")[data_index].strip().lower() #用例数据 + except Exception as e: + print(e) + return switch_value + + def _operate_switch(self, data: {}, data_index=0, no_modify="不修改", switch_name="", element_position=""): + """ + 页面中,开关状态操作,。 + :param data: + :param data_index: 0 -1来自上层 + :param no_modify:"不修改" 来自上次调用 + :param operation_type: create modify两个状态, + :param switch_name: 数据中开关名称 + :param elementPosition: 开关的定位 + :return: + """ + #解析输入data数据的数据 + switch_value: str = self._get_value_from_data(data, key=switch_name, data_index=data_index) #提取数据 Mirror Server Response + if switch_value != no_modify: #编辑时,有不修改则不用执行 + #先获取当前页面中开关状态 include_root_current_class : class="el-switch is-checked" 有is-checked当前状态为开,没有is-chedked当前状态为关 + swith_current_class = self.driver.find_element(By.XPATH, element_position).get_attribute("class") + if ("mirror" in switch_value) and ("server" in switch_value) and ("response" in switch_value): #数据中为Mirror Server Response,使用默认名称,不修改 + if "is-checked" in swith_current_class: #页面当前为开,不用点击开关 + pass + else: #页面当前为关,需要点击开关 + self.driver.find_element(By.XPATH, f"{element_position}/span[2]").click() + else: ##数据中为其它名称,则需要修改默认名称 + if "is-checked" in swith_current_class: #页面当前为开,需要先关闭开关,在输入值 + self.driver.find_element(By.XPATH, f"{element_position}/span[2]").click() + #输入修改名称值 + self.driver.find_element(By.XPATH, hijackFiles_input_downLoadName_posXpath).clear() + self.driver.find_element(By.XPATH, hijackFiles_input_downLoadName_posXpath).send_keys(switch_value) + + + @screenshot_on_failure + def _query(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None, + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_hijackFiles_selectLabel_posId, listPage_profileSearch_hijackFiles_dropDown_item_posXpath, + listPage_profileSearch_hijackFiles_input_itemContent_posXpath, listPage_profileSearch_hijackFiles_buttonSearch_posId, + listPage_profilTable_hijackFiles_tableTbody_posXpath, listPage_profilTable_hijackFiles_tableHeader_posXpath, **kwargs) + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + #print(map_header_className) + # 需要提取ID Name、Type 信息 + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + first_row_Type_class = map_header_className["Type"] + first_row_Type_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Type_class}')]//span").text + + print(first_row_id_content, first_row_Name_content, first_row_Type_content) + element_type_replace_name = {'gif': 'image/gif', 'jpeg': 'image/jpeg', 'png': 'image/png', 'svg+xml': 'image/svg+xml', + 'exe': 'application/x-msdos-program', 'apk': 'application/vnd.android.package-archive', 'html': 'text/html'} + #不同操作后的断言,创建后、修改后、无断言 + if require_assertion == 1: #直接创建后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + file_type = self._get_value_from_data(data, key="file_type", data_index=0) + pytest_check.equal(first_row_Type_content, element_type_replace_name[file_type], msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + file_type = self._get_value_from_data(data, key="file_type", data_index=-1) + if file_type != "不修改": + pytest_check.equal(first_row_Type_content, element_type_replace_name[file_type], msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_hijackFiles_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_hijackFiles_editButton_posId).click() + #解析修改数据 + self._operate_page(data, operation_type="edit") + #点击ok + self.driver.find_element(By.CSS_SELECTOR, hijackFiles_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, hijackFiles_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, hijackFiles_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_hijackFiles_delButton_posId, listPage_dialogTips_hijackFiles_button_yes_posCss, + listPage_dialogTips_hijackFiles_button_no_posCss) + + create = _create + query = _query + modify = _modify + delete = _del
\ No newline at end of file diff --git a/common/ui_common/profiles/profiles_public_operations.py b/common/ui_common/profiles/profiles_public_operations.py new file mode 100644 index 00000000..914f418d --- /dev/null +++ b/common/ui_common/profiles/profiles_public_operations.py @@ -0,0 +1,78 @@ +import time + +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +import random + + +class ProfilesPublicOperations: + def __init__(self, driver): + self.driver = driver + + def query(self, mainPage_profileSearch_selectLabel_posId, listPage_profileSearch_subProfiles_dropDown_item_posXpath, + listPage_profileSearch_subProfiles_input_itemContent_posXpath, mainPage_profileSearch_buttonSearch_posId, + listPage_profilTable_subProfiles_tableTbody_posXpath, listPage_profilTable_subProfiles_tableHeader_posXpath, + listPage_profileSearch_subProfiles_dropDown_typeItem_posXpath="", **kwargs): + """ + profiles模块中从点击查询到查询到结果使用方法,并返回第一行数据和表头、class的字典 + :param mainPage_profileSearch_selectLabel_posId: 查询框id + :param listPage_profileSearch_subProfiles_dropDown_item_posXpath: 下拉列表item的xpath + :param listPage_profileSearch_subProfiles_input_itemContent_posXpath: 选中item后,输入input的xpath + :param mainPage_profileSearch_buttonSearch_posId: 查询按钮id + :param listPage_profilTable_subProfiles_tableTbody_posXpath: 列表页body的部分xpath + :param listPage_profilTable_subProfiles_tableHeader_posXpath: 列表页header的部分xpath + :param listPage_profileSearch_subProfiles_dropDown_typeItem_posXpath: 如果有下拉列表item的枚举选项定位,需要增补 + :param kwargs: 需要查询的内容,来自调用函数 + :return: [first_row, map_header_className] + """ + #点击search查询框 + self.driver.find_element(By.ID, mainPage_profileSearch_selectLabel_posId).click() + #循环输入查询内容 + for key, value in kwargs.items(): + dropdown_item_posXpath = listPage_profileSearch_subProfiles_dropDown_item_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, dropdown_item_posXpath).click() #点击下拉item + if key != "type": + input_item_posXpath = listPage_profileSearch_subProfiles_input_itemContent_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, input_item_posXpath).send_keys(value.strip()) #输入查询值 + else: + dropdown_typeItem_posXpath = listPage_profileSearch_subProfiles_dropDown_typeItem_posXpath.format(replaceName=value.split("->")[0]) + self.driver.find_element(By.XPATH, dropdown_typeItem_posXpath).click() #点击type的下拉item + #点击查询按钮 + element_search = self.driver.find_element(By.ID, mainPage_profileSearch_buttonSearch_posId) + self.driver.execute_script("arguments[0].click()", element_search) #强制点击 + element_tbody = self.driver.find_element(By.XPATH, listPage_profilTable_subProfiles_tableTbody_posXpath) #找到所有的行,table的body + element_header = self.driver.find_element(By.XPATH, listPage_profilTable_subProfiles_tableHeader_posXpath) #查询table的header + #获取table header的text、th.class + headers = element_header.find_elements(By.XPATH, "th") #table header + rows = element_tbody.find_elements(By.XPATH, "tr") #table body + map_header_className = {} #表头名称和th.class的映射,为了从表body中取对应列的值{"ID":"33"} + for th in headers: + header_content = th.text.strip() + classNames = th.get_attribute("class").split() + for c_name in classNames: + if "el-table" in c_name: + tableBodyRowClassName = c_name + if header_content and tableBodyRowClassName: + map_header_className[header_content] = tableBodyRowClassName + #从第一行查询的结果中,取出需要断言的值、name + first_row = rows[0] + return [first_row, map_header_className] + + def delete(self, listPage_profile_subProfiles_delButton_posId, listPage_dialogTips_subProfiles_button_yes_posCss, + listPage_dialogTips_subProfiles_button_no_posCss): + """ + 直接删除函数, + :param listPage_profile_subProfiles_delButton_posId: 删除按钮id + :param listPage_dialogTips_subProfiles_button_yes_posCss: 提示删除框中yes定位css + :param listPage_dialogTips_subProfiles_button_no_posCss: 提示删除框中no定位css + :return: + """ + self.driver.find_element(By.ID, listPage_profile_subProfiles_delButton_posId).click() #点击删除按钮 + random_yes_or_no = random.randint(0, 1) + if random_yes_or_no == 0: #点击yes,删除 + self.driver.find_element(By.CSS_SELECTOR, listPage_dialogTips_subProfiles_button_yes_posCss).click() #直接删除 + else: + self.driver.find_element(By.CSS_SELECTOR, listPage_dialogTips_subProfiles_button_no_posCss).click() #先取消,再删除 + self.driver.find_element(By.ID, listPage_profile_subProfiles_delButton_posId).click() # 点击删除按钮 + self.driver.find_element(By.CSS_SELECTOR, listPage_dialogTips_subProfiles_button_yes_posCss).click() + time.sleep(0.5)
\ No newline at end of file diff --git a/common/ui_common/profiles/response_pages.py b/common/ui_common/profiles/response_pages.py new file mode 100644 index 00000000..2492def9 --- /dev/null +++ b/common/ui_common/profiles/response_pages.py @@ -0,0 +1,141 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect +import configparser +import os + + +class ResponsePages: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + + def response_page_case(self, data: {}): + self._create(data) #创建 + self._query(data, require_assertion=1, Name=self.random_name) #创建后查询 + if data["model"].strip().lower() == "modify": #修改测试时,执行修改方法 + self._modify(data) + self._query(data, require_assertion=2, ID=self.first_row_ID_content) + self._del() + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到responsePages列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_responsePages_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #页面跳转 + self._goto_subProfilePage() + #创建responsePages + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_responsePages_createButton_posId).click() + #在create resposne page页面操作 + self.driver.find_element(By.ID, responsePage_input_Name_posId).send_keys(self.random_name) + #上传文件 + create_file_ = data["file"].split("->")[0] #提取上传文件绝对路径 + create_file_abs = self._abs_path(create_file_) + self.driver.find_element(By.XPATH, responsePage_input_file_posXpath).send_keys(create_file_abs) + #点击OK + self.driver.find_element(By.CSS_SELECTOR, responsePage_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, responsePage_button_warningSaveYes_posCss).click() + return self.random_name + + def _abs_path(self, file_name): + # 以下是要读取数据的名称 + conf = configparser.ConfigParser() + loginout_parse_dir = os.path.join(self.workdir, "config", "ui_conf", "importfile.ini") + conf.read(loginout_parse_dir, encoding="utf-8") + testdata = conf.get("profiles", "testdata") + ui_file = conf.get("profiles", "ui_file") + profiles = conf.get("profiles", "profiles") + response_pages = conf.get("profiles", "response_pages") + import_file_abs = os.path.join(self.workdir, testdata, ui_file, profiles, response_pages, file_name) + import_file_abs = os.path.abspath(import_file_abs) + return import_file_abs + + @screenshot_on_failure + def _query(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None, + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_responsePages_selectLabel_posId, listPage_profileSearch_responsePages_dropDown_item_posXpath, + listPage_profileSearch_responsePages_input_itemContent_posXpath, listPage_profileSearch_responsePages_buttonSearch_posId, + listPage_profilTable_responsePages_tableTbody_posXpath, listPage_profilTable_responsePages_tableHeader_posXpath, **kwargs) + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + print(first_row_id_content, first_row_Name_content) + #不同操作后的断言,创建后、修改后、无断言 + + if require_assertion == 1: #直接创建后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_responsePages_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_responsePages_editButton_posId).click() + #根据修改数据,修改上次文件 + modify_file = data["file"].split("->")[-1] #提取上传文件绝对路径 + modify_file_abs = self._abs_path(modify_file) + self.driver.find_element(By.XPATH, responsePage_input_file_posXpath).send_keys(modify_file_abs) + #点击ok + self.driver.find_element(By.CSS_SELECTOR, responsePage_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, responsePage_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, responsePage_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_responsePages_delButton_posId, listPage_dialogTips_responsePages_button_yes_posCss, + listPage_dialogTips_responsePages_button_no_posCss) + + create = _create + query = _query + modify = _modify + delete = _del
\ No newline at end of file diff --git a/common/ui_common/profiles/shaping_profiles.py b/common/ui_common/profiles/shaping_profiles.py new file mode 100644 index 00000000..56a4d055 --- /dev/null +++ b/common/ui_common/profiles/shaping_profiles.py @@ -0,0 +1,248 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect + + +class ShapingProfiles: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + + def shaping_profiles_case(self, data: {}): + """ + 测试用例调用函数, + :param demo_fixture: 传入driver + :param data: 测试数据。 + + :return: + """ + #self.driver = demo_fixture + self._create(data) #创建 + self._query(data, require_assertion=1, Name=self.random_name) #创建后查询 + if data["model"].strip().lower() == "modify": #修改测试时,执行修改方法 + self._modify(data) + self._query(data, require_assertion=2, ID=self.first_row_ID_content) # 修改后查询 + self._del() #删除数据 + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到shapingProfiles列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_shapingProfiles_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #页面跳转 + self._goto_subProfilePage() + #创建shapingProfiles + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_shapingProfiles_createButton_posId).click() + #在create dns shapingProfiles操作 + self.driver.find_element(By.ID, shapingProfilePage_input_Name_posId).send_keys(self.random_name) #输入名字 + #判断点击哪种类型 + self._select_type(data) + self._select_limits(data, model=0) + #点击ok + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_warningSaveYes_posCss).click() + return self.random_name + + @screenshot_on_failure + def _a(self, data: {}): + print(__name__) + 1 == 1 + return 444 + + @screenshot_on_failure + def _select_type(self, data: {}): + """ + 选择type类型点击 + :param data: + :return: + """ + type: str = data["type"].strip().lower() + argument: str = data["argument"].strip().lower() + if type == "generic": + element_type_pos = shapingProfilePage_radioButton_generic_posXpath + elif type == "fair share": + element_type_pos = shapingProfilePage_radioButton_fairShare_posXpath + if argument == "Max Min Host Fairness".lower(): + element_argument_pos = shapingProfilePage_radioButton_maxMinHostFairness_posXpath + else: + raise ValueError(f"用例参数argument:{argument}") + else: + element_type_pos = shapingProfilePage_radioButton_splitBy_posXpath + if argument == "Local Host".lower(): + element_argument_pos = shapingProfilePage_radioButton_localHost_posXpath + else: + raise ValueError(f"用例参数argument:{argument}") + #点击type类型 + self.driver.find_element(By.XPATH, element_type_pos).click() + #判断是否点击Argument + if type != "generic": + self.driver.find_element(By.XPATH, element_argument_pos).click() + + @screenshot_on_failure + def _select_limits(self, data: {}, model=0): + """ + 输入limits + :param data: + :param model: =0表示创建时调用。-1表示修改时调用 + :return: + """ + unitItem = data["unit"].strip().split("->")[model] + element_dropDown_unitItem = shapingProfilePage_drowDown_unitItem_posXpath.format(replaceName=unitItem) + #点击Unit并选择单位 + self.driver.find_element(By.ID, shapingProfilePage_inputSelect_unit_posId).click() + self.driver.find_element(By.XPATH, element_dropDown_unitItem).click() + #输入incoming、outgoing + input_incoming = data["incoming"].strip().split("->")[model] + input_outgoing = data["outgoing"].strip().split("->")[model] + self.driver.find_element(By.ID, shapingProfilePage_input_incoming_posId).clear() + self.driver.find_element(By.ID, shapingProfilePage_input_incoming_posId).send_keys(input_incoming) + self.driver.find_element(By.ID, shapingProfilePage_input_outgoing_posId).clear() + self.driver.find_element(By.ID, shapingProfilePage_input_outgoing_posId).send_keys(input_outgoing) + + @screenshot_on_failure + def _query(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None, + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_shapingProfiles_selectLabel_posId, listPage_profileSearch_shapingProfiles_dropDown_item_posXpath, + listPage_profileSearch_shapingProfiles_input_itemContent_posXpath, listPage_profileSearch_shapingProfiles_buttonSearch_posId, + listPage_profilTable_shapingProfiles_tableTbody_posXpath, listPage_profilTable_shapingProfiles_tableHeader_posXpath, **kwargs) + """ + #点击search查询框 + self.driver.find_element(By.ID, listPage_profileSearch_shapingProfiles_selectLabel_posId).click() + #循环输入查询内容 + for key, value in kwargs.items(): + dropdown_item_posXpath = listPage_profileSearch_shapingProfiles_dropDown_item_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, dropdown_item_posXpath).click() #点击下拉item + if key != "type": + input_item_posXpath = listPage_profileSearch_shapingProfiles_input_itemContent_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, input_item_posXpath).send_keys(value.strip()) #输入查询值 + else: + pass + # dropdown_typeItem_posXpath = listPage_profileSearch_dnsRecords_dropDown_typeItem_posXpath.format(replaceName=value.split("->")[0]) + # self.driver.find_element(By.XPATH, dropdown_typeItem_posXpath).click() #点击type的下拉item + #点击查询按钮 + element_search = self.driver.find_element(By.ID, listPage_profileSearch_shapingProfiles_buttonSearch_posId) + self.driver.execute_script("arguments[0].click()", element_search) #强制点击 + element_tbody = self.driver.find_element(By.XPATH, listPage_profilTable_shapingProfiles_tableTbody_posXpath) #找到所有的行,table的body + element_header = self.driver.find_element(By.XPATH, listPage_profilTable_shapingProfiles_tableHeader_posXpath) #查询table的header + #获取table header的text、th.class + headers = element_header.find_elements(By.XPATH, "th") #table header + rows = element_tbody.find_elements(By.XPATH, "tr") #table body + map_header_className = {} #表头名称和th.class的映射,为了从表body中取对应列的值{"ID":"33"} + for th in headers: + header_content = th.text.strip() + classNames = th.get_attribute("class").split() + for c_name in classNames: + if "el-table" in c_name: + tableBodyRowClassName = c_name + if header_content and tableBodyRowClassName: + map_header_className[header_content] = tableBodyRowClassName + #从第一行查询的结果中,取出需要断言的值、name、Type、Values + first_row = rows[0] + """ + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + first_row_Type_class = map_header_className["Type"] + first_row_Type_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Type_class}')]//span").text.strip() + first_row_IncomingOutgoing_class = map_header_className["Incoming/Outgoing"] + first_row_IncomingOutgoing_contents = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_IncomingOutgoing_class}')]//span").text.strip() + + print(first_row_id_content, first_row_Name_content, first_row_Type_content, first_row_IncomingOutgoing_contents) + #不同操作后的断言,创建后、修改后、无断言 + if require_assertion == 1: #直接创建后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.equal(first_row_Type_content, data["type"].strip(), msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["outgoing"].strip().split("->")[0] == "0": #为0时,直接断言Unlimit + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["outgoing"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["incoming"].strip().split("->")[0] == "0": + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["incoming"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.equal(first_row_Type_content, data["type"].split("->")[-1], msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["outgoing"].strip().split("->")[-1] == "0": #为0时,直接断言Unlimit + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["outgoing"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["incoming"].strip().split("->")[-1] == "0": + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["incoming"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_shapingProfiles_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_shapingProfiles_editButton_posId).click() + #根据修改数据,重新输入limits + self._select_limits(data, model=-1) + #点击ok + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_shapingProfiles_delButton_posId, listPage_dialogTips_shapingProfiles_button_yes_posCss, + listPage_dialogTips_shapingProfiles_button_no_posCss) + + create = _create + query = _query + modify = _modify + delete = _del diff --git a/common/ui_common/profiles/ssl_decryption_keyrings.py b/common/ui_common/profiles/ssl_decryption_keyrings.py new file mode 100644 index 00000000..5e81b7a4 --- /dev/null +++ b/common/ui_common/profiles/ssl_decryption_keyrings.py @@ -0,0 +1,219 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect +import configparser +import os + + +class SSLDecryptionKeyrings: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + + def sslDecryptionKeyrings_case(self, data: {}): + self._create(data) #创建 + self._query(data, require_assertion=1, Name=self.random_name) #创建后查询 + if data["model"].strip().lower() == "modify": #修改测试时,执行修改方法 + self._modify(data) + self._query(data, require_assertion=2, ID=self.first_row_ID_content) + self._del() + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到ssl_decryption_keyrings列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_sslDecryptionKeyrings_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #页面跳转 + self._goto_subProfilePage() + #创建 + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_sslDecryptionKeyrings_createButton_posId).click() + #在create 创建页面操作 + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_Name_posId).send_keys(self.random_name) + #页面其它项操作函数 + self._operate_page(data, operation_type="create") + #点击OK + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionKeyrings_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionKeyrings_button_warningSaveYes_posCss).click() + return self.random_name + + def _operate_page(self, data: {}, operation_type="create"): + """ + 不包含name输入的其它操作,可以兼容新增、编辑使用 + :param data: + :opration_type:可选择值为create edit + :return: + """ + if operation_type == "create": + data_index = 0 #新增数据索引 + else: + data_index = -1 #编辑数据索引 + no_modify = "不修改" + #解析输入data数据、证书、私钥操作 + cert_name = data["certificate"].split("->")[data_index].strip() #"test_root_cert_catest.cer->" + if cert_name != no_modify: #需改数据时,需要执行 + cert_abspath = self._abs_path(cert_name) + self.driver.find_element(By.XPATH, sslDecryptionKeyrings_input_certificateFile_posXpath).send_keys(cert_abspath) #上传证书 + #私钥 + if data["private_key"].split("->")[data_index].strip() != no_modify: #修改私钥时执行 + if data["private_key"].split("->")[data_index].strip().startswith("PKF-"): #如果已PKF-开始,则是私钥 "PKF-test_root_key_catest.key->" + key_name = data["private_key"].split("->")[data_index].strip().lstrip("PKF-") + key_abspath = self._abs_path(key_name) + self.driver.find_element(By.ID, sslDecryptionKeyrings_radio_privateKeyFile_posId).click() + self.driver.find_element(By.XPATH, sslDecryptionKeyrings_input_privateKeyFile_posXpath).send_keys(key_abspath) #上传私钥 + else: #私钥是HSM形式, 例如:HSM-345 + slod_id = data["private_key"].split("->")[data_index].strip().lstrip("HSM-") + self.driver.find_element(By.ID, sslDecryptionKeyrings_radio_hsm_posId).click() + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_slotIdHSM_posId).send_keys(slod_id) #输入slot id + #证书时间选择 + reissue_expiry_hours: str = data["reissue_expiry_hours"].split("->")[data_index].strip() + if reissue_expiry_hours != no_modify: + if reissue_expiry_hours.startswith("MSC"): #'MSC' + self.driver.find_element(By.ID, sslDecryptionKeyrings_radio_mirrorServerCertificate_poId).click() + else: + self.driver.find_element(By.ID, sslDecryptionKeyrings_radio_customized_poId).click() + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_customized_poId).clear() + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_customized_poId).send_keys(reissue_expiry_hours.lstrip("C-")) #‘C-234' + #证书类型操作 + type = data["type"].split("->")[data_index].strip() + if type != no_modify: + type_index_dict = {"Root-Certificate": 0, "Intermediate-Certificate": 1, "End-entity": 2} + if type not in type_index_dict.keys(): + raise f"输入的证书类型参数错误。输出的参数:type={type}。可选择的输入参数值为:{list(type_index_dict.keys())}" + element_pos_type_droplist_item = sslDecryptionKeyrings_dropdown_certificateTypeSelect_poId.format(replaceIndex=type_index_dict[type]) + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_certificateType_poId).click() #点击类型列表选择框 + self.driver.find_element(By.ID, element_pos_type_droplist_item).click() #点击列表下拉参数具体选项 + pka = data["public_key_algorithm"].split("->")[data_index].strip() + #公钥算法 + if pka != no_modify: + pka_idex_dict = {"RSA-1024": 0, "RSA-2048": 1, "SECP-256r1": 2, "SECP-384r1": 3} #下拉列表定位索引 + if pka not in pka_idex_dict.keys(): + raise f"输入的公钥算法错误。输出的参数:pka={pka}。可选择的输入参数值为:{list(pka_idex_dict.keys())}" + element_pos_pka_droplist_item = sslDecryptionKeyrings_dropdown_publickKeyAlgorithmSelect_poId.format(replaceIndex=pka_idex_dict[pka]) + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_publickKeyAlgorithm_poId).click() + self.driver.find_element(By.ID, element_pos_pka_droplist_item).click() #点击公钥算法下拉选项定位 + #输入Certificate Revocation List + if data["certificate_revocation_list"].split("->")[data_index].strip() != no_modify: + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_certificateRevocationList_poId).clear() + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_certificateRevocationList_poId).send_keys(data["certificate_revocation_list"].split("->")[data_index].strip()) + include_root = data["include_root"].split("->")[data_index].strip().lower() #用例数据 + if include_root != no_modify: + #先获取页面中包含根证书当前状态 include_root_current_class : class="el-switch is-checked" 有is-checked当前状态为开,没有is-chedked当前状态为关 + include_root_current_class = self.driver.find_element(By.XPATH, sslDecryptionKeyrings_input_includeRoot_poXpath).find_element(By.XPATH, "parent::*").get_attribute("class") + if "on" == include_root: #开 + if "is-checked" in include_root_current_class: #页面当前为开,不用点击开关 + pass + else: #页面当前为关,需要点击开关 + self.driver.find_element(By.XPATH, sslDecryptionKeyrings_input_includeRoot_poXpath).click() + self.include_root_statue = "on" #修改时会使用判断 + else: #用例输入为关 + if "is-checked" in include_root_current_class: #页面当前为开,需要点击开关 + self.driver.find_element(By.XPATH, sslDecryptionKeyrings_input_includeRoot_poXpath).click() + self.include_root_statue = "on" # 修改时会使用判断 + else: #页面当前为关,不用点击开关 + pass + + def _abs_path(self, file_name): + # 以下是要读取数据的名称 + conf = configparser.ConfigParser() + loginout_parse_dir = os.path.join(self.workdir, "config", "ui_conf", "importfile.ini") + conf.read(loginout_parse_dir, encoding="utf-8") + testdata = conf.get("profiles", "testdata") + ui_file = conf.get("profiles", "ui_file") + profiles = conf.get("profiles", "profiles") + ssl_decryption_keyrings = conf.get("profiles", "ssl_decryption_keyrings") + import_file_abs = os.path.join(self.workdir, testdata, ui_file, profiles, ssl_decryption_keyrings, file_name) + import_file_abs = os.path.abspath(import_file_abs) + return import_file_abs + + @screenshot_on_failure + def _query(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None, + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_sslDecryptionKeyrings_selectLabel_posId, listPage_profileSearch_sslDecryptionKeyrings_dropDown_item_posXpath, + listPage_profileSearch_sslDecryptionKeyrings_input_itemContent_posXpath, listPage_profileSearch_sslDecryptionKeyrings_buttonSearch_posId, + listPage_profilTable_sslDecryptionKeyrings_tableTbody_posXpath, listPage_profilTable_sslDecryptionKeyrings_tableHeader_posXpath, **kwargs) + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + # 需要提取id、name、type、crl信息 + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + first_row_Type_class = map_header_className["Type"] + first_row_Type_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Type_class}')]//span").text.strip() + first_row_CRL_class = map_header_className["CRL"] + first_row_CRL_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_CRL_class}')]//span").text.strip() + + print(first_row_id_content, first_row_Name_content, first_row_Type_content, first_row_CRL_content) + #不同操作后的断言,创建后、修改后、无断言 + if require_assertion == 1: #直接创建后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_trafficMirroringProfiles_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_sslDecryptionKeyrings_editButton_posId).click() + #解析修改数据 + self._operate_page(data, operation_type="edit") + + #点击ok + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionKeyrings_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, sslDecryptionKeyrings_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionKeyrings_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_sslDecryptionKeyrings_delButton_posId, listPage_dialogTips_sslDecryptionKeyrings_button_yes_posCss, + listPage_dialogTips_sslDecryptionKeyrings_button_no_posCss) + + create = _create + query = _query + modify = _modify + delete = _del
\ No newline at end of file diff --git a/common/ui_common/profiles/ssl_decryption_profiles.py b/common/ui_common/profiles/ssl_decryption_profiles.py new file mode 100644 index 00000000..3acb1160 --- /dev/null +++ b/common/ui_common/profiles/ssl_decryption_profiles.py @@ -0,0 +1,252 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect + + +class SSLDecryptionProfiles: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + + def sslDecryptionProfiles_case(self, data: {}): + self._create(data) #创建 + self._query(data, require_assertion=1, Name=self.random_name) #创建后查询 + if data["model"].strip().lower() == "modify": #修改测试时,执行修改方法 + self._modify(data) + self._query(data, require_assertion=2, ID=self.first_row_ID_content) + self._del() + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到ssl_decryption_keyrings列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_sslDecryptionProfiles_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #页面跳转 + self._goto_subProfilePage() + #创建 + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_sslDecryptionProfiles_createButton_posId).click() + #在create 创建页面操作 + self.driver.find_element(By.ID, sslDecryptionProfiles_input_Name_posId).send_keys(self.random_name) + #页面其它选项操作 + self._operate_page(data, operation_type="create") + #点击OK + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionProfiles_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionProfiles_button_warningSaveYes_posCss).click() + return self.random_name + + def _operate_page(self, data: {}, operation_type="create"): + """""" + if operation_type == "create": + data_index = 0 #新增数据索引 + else: + data_index = -1 #编辑数据索引 + no_modify = "不修改" + #解析输入data数据的数据 + #页面开关操作 common name,issuer,selfSigned,expiryDate + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="common_name", element_position=sslDecryptionProfiles_switch_commonName_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="issuer", element_position=sslDecryptionProfiles_switch_issuer_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="self_signed", element_position=sslDecryptionProfiles_switch_selfSigned_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="expiry_date", element_position=sslDecryptionProfiles_switch_expiryDate_posXpath) + #Fail Action操作 + fail_action = self._get_value_from_data(data, key="fail_action", data_index=data_index) #用例数据提取 Pass-through Fail-close + if fail_action != no_modify: + if "pass-through" == fail_action: #点击pass through + self.driver.find_element(By.XPATH, sslDecryptionProfiles_radio_passThrough_posXpath).click() + else: #点击fail close + self.driver.find_element(By.XPATH, sslDecryptionProfiles_radio_failClose_posXpath).click() + #页面开关操作ev_certificate certificate_transparency mutual_authentication protocol_errors certificate_pinning certificate_not_installed allow_HTTP2 mirror_client_versions + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="ev_certificate", element_position=sslDecryptionProfiles_switch_evCert_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="certificate_transparency", element_position=sslDecryptionProfiles_switch_certificateTransparency_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="mutual_authentication", element_position=sslDecryptionProfiles_switch_mutualAuthentication_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="protocol_errors", element_position=sslDecryptionProfiles_switch_onProtocolErrors_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="certificate_pinning", element_position=sslDecryptionProfiles_switch_certificatePinning_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="certificate_not_installed", element_position=sslDecryptionProfiles_switch_certificateNotInstalled_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="mirror_client_versions", element_position=sslDecryptionProfiles_switch_mirrorClientVersions_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="allow_HTTP2", element_position=sslDecryptionProfiles_switch_allowHTTP2_posXpath) + #Min Max version操作 + mirror_client_versions = self._get_value_from_data(data, key="mirror_client_versions", data_index=data_index) #提取数据 + mirror_client_versions_class = self.driver.find_element(By.XPATH, sslDecryptionProfiles_switch_mirrorClientVersions_posXpath).get_attribute("class") #该开关当前属性状态 + min_version = self._get_value_from_data(data, key="min_client_version", data_index=data_index) + max_version = self._get_value_from_data(data, key="max_client_version", data_index=data_index) + if "is-checked" not in mirror_client_versions_class: #只有 当前状态为关时,才可以操作版本大小。 + version_index_list = ['sslv3.0', 'tlsv1.0', 'tlsv1.1', 'tlsv1.2', 'tlsv1.3'] + if min_version != no_modify: #编辑时不修改,则不用操作 + self.driver.find_element(By.XPATH, sslDecryptionProfiles_input_minVersion_posXpath).click() + element_pos_min_drop_down_item = sslDecryptionProfiles_dropDown_minVersion_posXpath.format(replaceIndex=version_index_list.index(min_version)) #组定位 + self.driver.find_element(By.XPATH, element_pos_min_drop_down_item).click() + if max_version != no_modify: #编辑时不修改,则不用操作 + self.driver.find_element(By.XPATH, sslDecryptionProfiles_input_maxVersion_posXpath).click() + element_pos_max_drop_down_item = sslDecryptionProfiles_dropDown_maxVersion_posXpath.format(replaceIndex=version_index_list.index(max_version)) #组定位 + self.driver.find_element(By.XPATH, element_pos_max_drop_down_item).click() + + def _get_value_from_data(self, data: {}, key="", data_index=0): + """ + 从data数据中,根据key提取值 + :param data: + :param key: + :param data_index: 0 -1 + :return: + """ + try: + switch_value: str = data[key].split("->")[data_index].strip().lower() #用例数据 + except Exception as e: + print(e) + return switch_value + + def _operate_switch(self, data: {}, data_index=0, no_modify="不修改", switch_name="", element_position=""): + """ + 页面中,开关状态操作。 + :param data: + :param data_index: 0 -1来自上层 + :param no_modify:"不修改" 来自上次调用 + :param operation_type: create modify两个状态, + :param switch_name: 数据中开关名称 + :param elementPosition: 开关的定位 + :return: + """ + #解析输入data数据的数据 + switch_value: str = self._get_value_from_data(data, key=switch_name, data_index=data_index) #提取数据 + if switch_value != no_modify: #编辑时,有不修改则不用执行 + #先获取当前页面中开关状态 include_root_current_class : class="el-switch is-checked" 有is-checked当前状态为开,没有is-chedked当前状态为关 + swith_current_class = self.driver.find_element(By.XPATH, element_position).get_attribute("class") + if "on" == switch_value: #数据中为开 + if "is-checked" in swith_current_class: #页面当前为开,不用点击开关 + pass + else: #页面当前为关,需要点击开关 + self.driver.find_element(By.XPATH, element_position).click() + else: #用例输入为关 + if "is-checked" in swith_current_class: #页面当前为开,需要点击开关 + self.driver.find_element(By.XPATH, element_position).click() + else: #页面当前为关,不用点击开关 + pass + + @screenshot_on_failure + def _query(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None, + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_sslDecryptionProfiles_selectLabel_posId, listPage_profileSearch_sslDecryptionProfiles_dropDown_item_posXpath, + listPage_profileSearch_sslDecryptionProfiles_input_itemContent_posXpath, listPage_profileSearch_sslDecryptionProfiles_buttonSearch_posId, + listPage_profilTable_sslDecryptionProfiles_tableTbody_posXpath, listPage_profilTable_sslDecryptionProfiles_tableHeader_posXpath, **kwargs) + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + #print(map_header_className) + # 需要提取id、name、type、Certificate Checks、Fail Action、Dynamic Bypass、Allow HTTP/2信息 + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + first_row_Certificate_Checks_class = map_header_className["Certificate Checks"] + first_row_Certificate_Checks_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Certificate_Checks_class}')]//span").text + first_row_Fail_Action_class = map_header_className["Fail Action"] + first_row_Fail_Action_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Fail_Action_class}')]//span").text + first_row_Dynamic_Bypass_class = map_header_className["Dynamic Bypass"] + first_row_Dynamic_Bypass_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Dynamic_Bypass_class}')]//span").text + first_row_Allow_HTTP2_class = map_header_className["Allow HTTP/2"] + first_row_Allow_HTTP2_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Allow_HTTP2_class}')]//span").text + + print(first_row_id_content, first_row_Name_content, first_row_Certificate_Checks_content, first_row_Fail_Action_content, first_row_Dynamic_Bypass_content, first_row_Allow_HTTP2_content) + #不同操作后的断言,创建后、修改后、无断言 + if require_assertion == 1: #直接创建后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + self_signed = self._get_value_from_data(data, key="self_signed", data_index=0) + common_name = self._get_value_from_data(data, key="common_name", data_index=0) + fail_action = self._get_value_from_data(data, key="fail_action", data_index=0) + allow_HTTP2 = self._get_value_from_data(data, key="fail_action", data_index=0) + certificate_pinning = self._get_value_from_data(data, key="certificate_pinning", data_index=0) + if self_signed == "on": + pytest_check.is_in("Self-signed", first_row_Certificate_Checks_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if common_name == "on": + pytest_check.is_in("Common Name", first_row_Certificate_Checks_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if fail_action == "pass-through": + pytest_check.is_in("Pass-through", first_row_Fail_Action_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif fail_action == "fail-close": + pytest_check.is_in("Fail-close", first_row_Fail_Action_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if certificate_pinning == "on": + pytest_check.is_in("Certificate Pinning", first_row_Dynamic_Bypass_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if allow_HTTP2 == "on": + pytest_check.is_in("Enabled", first_row_Allow_HTTP2_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + self_signed = self._get_value_from_data(data, key="self_signed", data_index=-1) + common_name = self._get_value_from_data(data, key="common_name", data_index=-1) + fail_action = self._get_value_from_data(data, key="fail_action", data_index=-1) + allow_HTTP2 = self._get_value_from_data(data, key="fail_action", data_index=-1) + certificate_pinning = self._get_value_from_data(data, key="certificate_pinning", data_index=-1) + if self_signed == "on": + pytest_check.is_in("Self-signed", first_row_Certificate_Checks_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if common_name == "on": + pytest_check.is_in("Common Name", first_row_Certificate_Checks_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if fail_action == "pass-through": + pytest_check.is_in("Pass-through", first_row_Fail_Action_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif fail_action == "fail-close": + pytest_check.is_in("Fail-close", first_row_Fail_Action_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if certificate_pinning == "on": + pytest_check.is_in("Certificate Pinning", first_row_Dynamic_Bypass_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if allow_HTTP2 == "on": + pytest_check.is_in("Enabled", first_row_Allow_HTTP2_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_sslDecryptionProfiles_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_sslDecryptionProfiles_editButton_posId).click() + #解析修改数据 + self._operate_page(data, operation_type="edit") + #点击ok + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionProfiles_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, sslDecryptionProfiles_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionProfiles_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_sslDecryptionProfiles_delButton_posId, listPage_dialogTips_sslDecryptionProfiles_button_yes_posCss, + listPage_dialogTips_sslDecryptionProfiles_button_no_posCss) + + create = _create + query = _query + modify = _modify + delete = _del
\ No newline at end of file diff --git a/common/ui_common/profiles/traffic_mirroring_profiles.py b/common/ui_common/profiles/traffic_mirroring_profiles.py new file mode 100644 index 00000000..22719f0e --- /dev/null +++ b/common/ui_common/profiles/traffic_mirroring_profiles.py @@ -0,0 +1,195 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect +import time + + +class TrafficMirroringProfiles: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + #todo + def traffic_morroring_profiles_case(self, data: {}): + self._create(data) #创建 + self._query(data, require_assertion=1, Name=self.random_name) #创建后查询 + if data["model"].strip().lower() == "modify": #修改测试时,执行修改方法 + self._modify(data) + self._query(data, require_assertion=2, ID=self.first_row_ID_content) + self._del() + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到trafficMirroringProfiles列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_trafficMirroringProfiles_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #页面跳转 + self._goto_subProfilePage() + #创建 + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_trafficMirroringProfiles_createButton_posId).click() + #在create 创建页面操作 + self.driver.find_element(By.ID, trafficMirroringProfiles_input_Name_posId).send_keys(self.random_name) + #解析输入的vlan id数据 + vlan_ids = data["vlan_id"] + vlan_ids_create = [] #创建的vlan id + for i in vlan_ids: + if i.strip().split("->")[0] != "": + vlan_ids_create.append(i.strip().split("->")[0]) + #循环输入vlan id + for j in range(len(vlan_ids_create)): + #输入ipnut + elements_vlan_ids_input = self.driver.find_elements(By.XPATH, trafficMirroringProfiles_input_vlanIdsInput_posXpath) + for element_vlan_id in elements_vlan_ids_input: + if element_vlan_id.get_attribute("value") == "": #创建时,只是往input.value=none中键入数据 + element_pos_by_id = element_vlan_id.get_attribute("id") + self.driver.find_element(By.ID, element_pos_by_id).send_keys(vlan_ids_create[j]) #输入vlan id的值 + break + if (len(vlan_ids_create) - 1) - j > 0: #点击add按钮比数据个数少一次 + self.driver.find_element(By.CSS_SELECTOR, trafficMirroringProfiles_button_vlanIdAdd_posCss).click() #点击add添加 + #点击OK + self.driver.find_element(By.CSS_SELECTOR, trafficMirroringProfiles_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, trafficMirroringProfiles_button_warningSaveYes_posCss).click() + return self.random_name + + @screenshot_on_failure + def _query(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None, + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_trafficMirroringProfiles_selectLabel_posId, listPage_profileSearch_trafficMirroringProfiles_dropDown_item_posXpath, + listPage_profileSearch_trafficMirroringProfiles_input_itemContent_posXpath, listPage_profileSearch_trafficMirroringProfiles_buttonSearch_posId, + listPage_profilTable_trafficMirroringProfiles_tableTbody_posXpath, listPage_profilTable_trafficMirroringProfiles_tableHeader_posXpath, **kwargs) + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + first_row_VLAN_ID_class = map_header_className["VLAN ID"] + first_row_VLAN_IDs_content = first_row.find_elements(By.XPATH, f"//td[contains(@class, '{first_row_VLAN_ID_class}')]//span//span") + first_row_VLAN_IDS_list = [] + for element_vlan_id in first_row_VLAN_IDs_content: + vlan_id_str = element_vlan_id.text.strip() + if "," in vlan_id_str and len(vlan_id_str) == 1: #跳过只是,的数据 + continue + first_row_VLAN_IDS_list.append(vlan_id_str.strip(",")) + print(first_row_id_content, first_row_Name_content, first_row_VLAN_IDS_list) + #不同操作后的断言,创建后、修改后、无断言 + + if require_assertion == 1: #直接创建后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + # 解析输入的vlan id数据,并断言使用 + vlan_ids = data["vlan_id"] + vlan_ids_create = [] # 创建的vlan id + for i in vlan_ids: + if i.strip().split("->")[0] != "": + vlan_ids_create.append(i.strip().split("->")[0]) + #断言vlan id + for vlan_id in first_row_VLAN_IDS_list: + pytest_check.is_in(vlan_id, vlan_ids_create, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_trafficMirroringProfiles_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_trafficMirroringProfiles_editButton_posId).click() + #从data数据中解析出修改数据、删除输出、新增数据 + modify_vlan_ids = [] + del_vlan_ids = [] + add_vlan_ids = [] + raw_vlan_ids = data["vlan_id"] #用例中输入的数据,->前的数据为创建,标识符后的数据为修改的数据 + for item in raw_vlan_ids: + if item.strip().split("->")[0] != "" and item.strip().split("->")[-1] != "": #提创建、取修改数据 + modify_vlan_ids.append(item.strip()) + elif item.strip().split("->")[-1] == "": #提取创建、删除数据 + del_vlan_ids.append(item.strip()) + else: #提取新增数据 + add_vlan_ids.append(item.strip()) + print(modify_vlan_ids, del_vlan_ids, add_vlan_ids) + #操作直接修改vlan id数据 + if len(modify_vlan_ids) != 0: + for modify_item in modify_vlan_ids: + elements_vlan_ids_input = self.driver.find_elements(By.XPATH, trafficMirroringProfiles_input_vlanIdsInput_posXpath) + for element_vlan_id in elements_vlan_ids_input: + if element_vlan_id.get_attribute("value").strip() == modify_item.split("->")[0]: #有需要修改的vlan id + element_vlan_id.clear() + element_vlan_id.send_keys(modify_item.split("->")[-1]) #修改数据 + time.sleep(0.2) + break + #操作直接删除vlan id数据 + if len(del_vlan_ids) != 0: + for del_item in del_vlan_ids: + elements_vlan_ids_input = self.driver.find_elements(By.XPATH, trafficMirroringProfiles_input_vlanIdsInput_posXpath) + for element_vlan_id in elements_vlan_ids_input: + if element_vlan_id.get_attribute("value").strip() == del_item.split("->")[0]: #有需要删除的vlan id + element_vlan_id.find_element(By.XPATH, r"parent::*/parent::*//i").click() #点击删除按钮 + time.sleep(0.2) + break + #操作新增vlan id数据 + if len(add_vlan_ids) != 0: + for add_item in add_vlan_ids: + self.driver.find_element(By.CSS_SELECTOR, trafficMirroringProfiles_button_vlanIdAdd_posCss).click() + elements_vlan_ids_input = self.driver.find_elements(By.XPATH, trafficMirroringProfiles_input_vlanIdsInput_posXpath) + for element_vlan_id in elements_vlan_ids_input: + if element_vlan_id.get_attribute("value") == "": #创建时,只是往input.value=none中键入数据 + element_vlan_id.send_keys(add_item.split("->")[-1]) + time.sleep(0.2) + break + #点击ok + self.driver.find_element(By.CSS_SELECTOR, trafficMirroringProfiles_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, trafficMirroringProfiles_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, trafficMirroringProfiles_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_trafficMirroringProfiles_delButton_posId, listPage_dialogTips_trafficMirroringProfiles_button_yes_posCss, + listPage_dialogTips_trafficMirroringProfiles_button_no_posCss) + + create = _create + query = _query + modify = _modify + delete = _del
\ No newline at end of file diff --git a/common/ui_read_data/__init__.py b/common/ui_read_data/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/common/ui_read_data/__init__.py diff --git a/common/ui_read_data/__pycache__/__init__.cpython-38.pyc b/common/ui_read_data/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..29d8cfa5 --- /dev/null +++ b/common/ui_read_data/__pycache__/__init__.cpython-38.pyc diff --git a/common/ui_read_data/__pycache__/read_data.cpython-38.pyc b/common/ui_read_data/__pycache__/read_data.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..8201539a --- /dev/null +++ b/common/ui_read_data/__pycache__/read_data.cpython-38.pyc diff --git a/common/ui_read_data/read_data.py b/common/ui_read_data/read_data.py new file mode 100644 index 00000000..52dea141 --- /dev/null +++ b/common/ui_read_data/read_data.py @@ -0,0 +1,72 @@ +import json +import os +from config.workpath import workdir + +class ReadData: + def __init__(self): + #json文件和测试文件目录 + self.workdir = workdir + self.testdata = "testdata" + self.ui_data = "ui_data" + self.profiles_data = "profiles_data" + # 以下是要读取数据的名称 + self.response_pages_name = "response_pages.json" + self.dns_records_name = "dns_records.json" + self.shaping_profile_name = "shaping_profiles.json" + + def _from_json(self, file): + """ + 从json中读取数据函数 + :param file: + :return: + """ + with open(file, "r", encoding="utf-8") as f: + data = json.load(f)["item"] + data = list(data) + return data + + def _abs_path(self, file_name): + """ + 重组路径 + :param file_name: + :return: + """ + file = os.path.join(self.workdir, self.testdata, self.ui_data, self.profiles_data, file_name) + return file + + @property + def read_response_pages(self): + file = self._abs_path(self.response_pages_name) + return self._from_json(file) + + @property + def read_dns_records(self): + file = self._abs_path(self.dns_records_name) + return self._from_json(file) + + @property + def read_shaping_profiles(self): + file = self._abs_path(self.shaping_profile_name) + return self._from_json(file) + + def read_data_profiles(self, file_name): + """ + 通用读取json数据方法 + :param file_name: + :return: + """ + file = self._abs_path(file_name) + return self._from_json(file) + + def generate_id(self, param): + """ + 测试用例中ids信息提取 + :param param: + :return: + """ + ids: str = param["ids"] + #print(ids) + return ids + +if __name__ == '__main__': + ReadData().read_dns_records
\ No newline at end of file |
