summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorzhaokun <[email protected]>2023-11-08 13:44:25 +0800
committerzhaokun <[email protected]>2023-11-08 13:44:25 +0800
commit4e683d5703daf29810097b9961b5ce02420202ea (patch)
tree4ad01d46a7417a14a8c8a9045e95d0387cf24388 /common
parent44ed57c3f0b5f83e2836aadeea34003f08867b08 (diff)
updatemain
Diffstat (limited to 'common')
-rw-r--r--common/__init__.py0
-rw-r--r--common/__pycache__/__init__.cpython-38.pycbin0 -> 130 bytes
-rw-r--r--common/__pycache__/demo_1.cpython-38.pycbin0 -> 1095 bytes
-rw-r--r--common/__pycache__/read_data.cpython-38.pycbin0 -> 776 bytes
-rw-r--r--common/demo_1.py23
-rw-r--r--common/driver_common/__init__.py0
-rw-r--r--common/driver_common/__pycache__/__init__.cpython-38.pycbin0 -> 144 bytes
-rw-r--r--common/driver_common/__pycache__/mywebdriver.cpython-38.pycbin0 -> 1879 bytes
-rw-r--r--common/driver_common/__pycache__/random_name.cpython-38.pycbin0 -> 1699 bytes
-rw-r--r--common/driver_common/__pycache__/screenshot.cpython-38.pycbin0 -> 1564 bytes
-rw-r--r--common/driver_common/mywebdriver.py58
-rw-r--r--common/driver_common/random_name.py48
-rw-r--r--common/driver_common/recovery.py25
-rw-r--r--common/driver_common/screenshot.py39
-rw-r--r--common/read_data.py16
-rw-r--r--common/ui_common/__init__.py0
-rw-r--r--common/ui_common/__pycache__/__init__.cpython-38.pycbin0 -> 140 bytes
-rw-r--r--common/ui_common/login_logout/__init__.py0
-rw-r--r--common/ui_common/login_logout/__pycache__/__init__.cpython-38.pycbin0 -> 153 bytes
-rw-r--r--common/ui_common/login_logout/__pycache__/loginout.cpython-38.pycbin0 -> 1495 bytes
-rw-r--r--common/ui_common/login_logout/loginout.py26
-rw-r--r--common/ui_common/profiles/Dos_detection.py248
-rw-r--r--common/ui_common/profiles/__init__.py0
-rw-r--r--common/ui_common/profiles/__pycache__/__init__.cpython-38.pycbin0 -> 152 bytes
-rw-r--r--common/ui_common/profiles/__pycache__/dns_records.cpython-38.pycbin0 -> 10203 bytes
-rw-r--r--common/ui_common/profiles/__pycache__/hijack_files.cpython-38.pycbin0 -> 8714 bytes
-rw-r--r--common/ui_common/profiles/__pycache__/profiles_public_operations.cpython-38.pycbin0 -> 3817 bytes
-rw-r--r--common/ui_common/profiles/__pycache__/response_pages.cpython-38.pycbin0 -> 5919 bytes
-rw-r--r--common/ui_common/profiles/__pycache__/shaping_profiles.cpython-38.pycbin0 -> 8361 bytes
-rw-r--r--common/ui_common/profiles/__pycache__/ssl_decryption_keyrings.cpython-38.pycbin0 -> 9127 bytes
-rw-r--r--common/ui_common/profiles/__pycache__/ssl_decryption_profiles.cpython-38.pycbin0 -> 10455 bytes
-rw-r--r--common/ui_common/profiles/__pycache__/traffic_mirroring_profiles.cpython-38.pycbin0 -> 7244 bytes
-rw-r--r--common/ui_common/profiles/dns_records.py288
-rw-r--r--common/ui_common/profiles/hijack_files.py224
-rw-r--r--common/ui_common/profiles/profiles_public_operations.py78
-rw-r--r--common/ui_common/profiles/response_pages.py141
-rw-r--r--common/ui_common/profiles/shaping_profiles.py248
-rw-r--r--common/ui_common/profiles/ssl_decryption_keyrings.py219
-rw-r--r--common/ui_common/profiles/ssl_decryption_profiles.py252
-rw-r--r--common/ui_common/profiles/traffic_mirroring_profiles.py195
-rw-r--r--common/ui_read_data/__init__.py0
-rw-r--r--common/ui_read_data/__pycache__/__init__.cpython-38.pycbin0 -> 143 bytes
-rw-r--r--common/ui_read_data/__pycache__/read_data.cpython-38.pycbin0 -> 2424 bytes
-rw-r--r--common/ui_read_data/read_data.py72
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
new file mode 100644
index 00000000..13af0213
--- /dev/null
+++ b/common/__pycache__/__init__.cpython-38.pyc
Binary files differ
diff --git a/common/__pycache__/demo_1.cpython-38.pyc b/common/__pycache__/demo_1.cpython-38.pyc
new file mode 100644
index 00000000..b74fe3a6
--- /dev/null
+++ b/common/__pycache__/demo_1.cpython-38.pyc
Binary files differ
diff --git a/common/__pycache__/read_data.cpython-38.pyc b/common/__pycache__/read_data.cpython-38.pyc
new file mode 100644
index 00000000..22ea7626
--- /dev/null
+++ b/common/__pycache__/read_data.cpython-38.pyc
Binary files differ
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
new file mode 100644
index 00000000..38bc323b
--- /dev/null
+++ b/common/driver_common/__pycache__/__init__.cpython-38.pyc
Binary files differ
diff --git a/common/driver_common/__pycache__/mywebdriver.cpython-38.pyc b/common/driver_common/__pycache__/mywebdriver.cpython-38.pyc
new file mode 100644
index 00000000..8e258f8b
--- /dev/null
+++ b/common/driver_common/__pycache__/mywebdriver.cpython-38.pyc
Binary files differ
diff --git a/common/driver_common/__pycache__/random_name.cpython-38.pyc b/common/driver_common/__pycache__/random_name.cpython-38.pyc
new file mode 100644
index 00000000..ce517551
--- /dev/null
+++ b/common/driver_common/__pycache__/random_name.cpython-38.pyc
Binary files differ
diff --git a/common/driver_common/__pycache__/screenshot.cpython-38.pyc b/common/driver_common/__pycache__/screenshot.cpython-38.pyc
new file mode 100644
index 00000000..1c1f63c7
--- /dev/null
+++ b/common/driver_common/__pycache__/screenshot.cpython-38.pyc
Binary files differ
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
new file mode 100644
index 00000000..3c247a2f
--- /dev/null
+++ b/common/ui_common/__pycache__/__init__.cpython-38.pyc
Binary files differ
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
new file mode 100644
index 00000000..d7ef9377
--- /dev/null
+++ b/common/ui_common/login_logout/__pycache__/__init__.cpython-38.pyc
Binary files differ
diff --git a/common/ui_common/login_logout/__pycache__/loginout.cpython-38.pyc b/common/ui_common/login_logout/__pycache__/loginout.cpython-38.pyc
new file mode 100644
index 00000000..56aba1be
--- /dev/null
+++ b/common/ui_common/login_logout/__pycache__/loginout.cpython-38.pyc
Binary files differ
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
new file mode 100644
index 00000000..12f4a2fb
--- /dev/null
+++ b/common/ui_common/profiles/__pycache__/__init__.cpython-38.pyc
Binary files differ
diff --git a/common/ui_common/profiles/__pycache__/dns_records.cpython-38.pyc b/common/ui_common/profiles/__pycache__/dns_records.cpython-38.pyc
new file mode 100644
index 00000000..5a164705
--- /dev/null
+++ b/common/ui_common/profiles/__pycache__/dns_records.cpython-38.pyc
Binary files differ
diff --git a/common/ui_common/profiles/__pycache__/hijack_files.cpython-38.pyc b/common/ui_common/profiles/__pycache__/hijack_files.cpython-38.pyc
new file mode 100644
index 00000000..687f3e13
--- /dev/null
+++ b/common/ui_common/profiles/__pycache__/hijack_files.cpython-38.pyc
Binary files differ
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
new file mode 100644
index 00000000..ae34623c
--- /dev/null
+++ b/common/ui_common/profiles/__pycache__/profiles_public_operations.cpython-38.pyc
Binary files differ
diff --git a/common/ui_common/profiles/__pycache__/response_pages.cpython-38.pyc b/common/ui_common/profiles/__pycache__/response_pages.cpython-38.pyc
new file mode 100644
index 00000000..f8f10cef
--- /dev/null
+++ b/common/ui_common/profiles/__pycache__/response_pages.cpython-38.pyc
Binary files differ
diff --git a/common/ui_common/profiles/__pycache__/shaping_profiles.cpython-38.pyc b/common/ui_common/profiles/__pycache__/shaping_profiles.cpython-38.pyc
new file mode 100644
index 00000000..beae1dcf
--- /dev/null
+++ b/common/ui_common/profiles/__pycache__/shaping_profiles.cpython-38.pyc
Binary files differ
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
new file mode 100644
index 00000000..11cf401b
--- /dev/null
+++ b/common/ui_common/profiles/__pycache__/ssl_decryption_keyrings.cpython-38.pyc
Binary files differ
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
new file mode 100644
index 00000000..e26b49a4
--- /dev/null
+++ b/common/ui_common/profiles/__pycache__/ssl_decryption_profiles.cpython-38.pyc
Binary files differ
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
new file mode 100644
index 00000000..6a9287a9
--- /dev/null
+++ b/common/ui_common/profiles/__pycache__/traffic_mirroring_profiles.cpython-38.pyc
Binary files differ
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
new file mode 100644
index 00000000..29d8cfa5
--- /dev/null
+++ b/common/ui_read_data/__pycache__/__init__.cpython-38.pyc
Binary files differ
diff --git a/common/ui_read_data/__pycache__/read_data.cpython-38.pyc b/common/ui_read_data/__pycache__/read_data.cpython-38.pyc
new file mode 100644
index 00000000..8201539a
--- /dev/null
+++ b/common/ui_read_data/__pycache__/read_data.cpython-38.pyc
Binary files differ
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