diff options
139 files changed, 4789 insertions, 0 deletions
diff --git a/.idea/aoto_selenium.iml b/.idea/aoto_selenium.iml new file mode 100644 index 00000000..dfd71bfe --- /dev/null +++ b/.idea/aoto_selenium.iml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="PYTHON_MODULE" version="4"> + <component name="NewModuleRootManager"> + <content url="file://$MODULE_DIR$" /> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> + <component name="PackageRequirementsSettings"> + <option name="requirementsPath" value="" /> + </component> + <component name="TestRunnerService"> + <option name="PROJECT_TEST_RUNNER" value="py.test" /> + </component> +</module>
\ No newline at end of file diff --git a/.idea/auto_tsg.iml b/.idea/auto_tsg.iml new file mode 100644 index 00000000..d0876a78 --- /dev/null +++ b/.idea/auto_tsg.iml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="PYTHON_MODULE" version="4"> + <component name="NewModuleRootManager"> + <content url="file://$MODULE_DIR$" /> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module>
\ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..79f1fc39 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,14 @@ +<component name="InspectionProjectProfileManager"> + <profile version="1.0"> + <option name="myName" value="Project Default" /> + <inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="ignoredPackages"> + <value> + <list size="1"> + <item index="0" class="java.lang.String" itemvalue="cryptography" /> + </list> + </value> + </option> + </inspection_tool> + </profile> +</component>
\ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 00000000..105ce2da --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ +<component name="InspectionProjectProfileManager"> + <settings> + <option name="USE_PROJECT_PROFILE" value="false" /> + <version value="1.0" /> + </settings> +</component>
\ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..5aa62326 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectModuleManager"> + <modules> + <module fileurl="file://$PROJECT_DIR$/.idea/aoto_selenium.iml" filepath="$PROJECT_DIR$/.idea/aoto_selenium.iml" /> + </modules> + </component> +</project>
\ No newline at end of file diff --git a/cases/__init__.py b/cases/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/cases/__init__.py diff --git a/cases/__pycache__/__init__.cpython-38.pyc b/cases/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..0124b67f --- /dev/null +++ b/cases/__pycache__/__init__.cpython-38.pyc diff --git a/cases/__pycache__/conftest.cpython-38-pytest-7.4.0.pyc b/cases/__pycache__/conftest.cpython-38-pytest-7.4.0.pyc Binary files differnew file mode 100644 index 00000000..ec51f6f1 --- /dev/null +++ b/cases/__pycache__/conftest.cpython-38-pytest-7.4.0.pyc diff --git a/cases/__pycache__/conftest.cpython-38.pyc b/cases/__pycache__/conftest.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..60126bc1 --- /dev/null +++ b/cases/__pycache__/conftest.cpython-38.pyc diff --git a/cases/__pycache__/test_1_demo.cpython-38-pytest-7.4.0.pyc b/cases/__pycache__/test_1_demo.cpython-38-pytest-7.4.0.pyc Binary files differnew file mode 100644 index 00000000..b0c9ad87 --- /dev/null +++ b/cases/__pycache__/test_1_demo.cpython-38-pytest-7.4.0.pyc diff --git a/cases/conftest.py b/cases/conftest.py new file mode 100644 index 00000000..567aee1d --- /dev/null +++ b/cases/conftest.py @@ -0,0 +1,96 @@ +import time +import pytest +from common.ui_common.login_logout.loginout import LogInOut +import time +import atexit +import sys +import os +import signal +import configparser +from config.workpath import workdir +from selenium import webdriver +from common.driver_common.mywebdriver import MyWebDriver +driver = None #全局变量用户保存webdirver实例 + +def my_driver(): + print("\n用例开始时执行。。。") + global driver + # 初始化,负责远程用户登录 + loginout_parse = configparser.ConfigParser() + loginout_parse_dir = os.path.join(workdir, "config", "ui_conf", "loginout.ini") + loginout_parse.read(loginout_parse_dir, encoding="utf-8") + remote_url = loginout_parse.get("remote_url", "url") + chrome_option = webdriver.ChromeOptions() + driver = MyWebDriver( + command_executor=remote_url, + options=chrome_option + ) + #driver.implicitly_wait(2) + driver.maximize_window() + return driver + +def setup(): + global driver + driver = my_driver() + loginout = LogInOut(driver) + loginout.login() + +def teardown(): + global driver + if driver: + print("\n用例结束时执行。。。") + driver.quit() + time.sleep(1) + +def demo_fixture(): + global driver + setup() + yield driver + teardown() + +def pytest_collection_modifyitems(items): + """ + 测试用例收集完成时,将收集到的name和nodeid的中文显示在控制台上,中文转换 + https://www.cnblogs.com/canglongdao/p/13418305.html + """ + for i in items: + i.name = i.name.encode("utf-8").decode("unicode_escape") + i._nodeid = i.nodeid.encode("utf-8").decode("unicode_escape") + +#处理ctrl+c中断 +def handle_interrupt(sinnum, frame): + global driver + print(driver, "主动中断") + if driver: + driver.close() + exit(1) + +#注册 Ctrl+C中断处理函数 +signal.signal(signal.SIGINT, handle_interrupt) + + +""" +# 自定义插件 +class CtrlCPlugin: + def __init__(self): + self.interrupted = False + + def pytest_runtest_protocol(self, item, nextitem): + if self.interrupted: + pytest.skip("Ctrl+C 中断") + +ctrl_c_plugin = CtrlCPlugin() + +# 注册插件 +def pytest_configure(config): + config.pluginmanager.register(ctrl_c_plugin) + +# 注册 Ctrl+C 中断处理函数 +def handle_interrupt(signum, frame): + ctrl_c_plugin.interrupted = True + signal.signal(signal.SIGINT, signal.SIG_DFL) # 恢复默认 Ctrl+C 处理 + +# 注册 Ctrl+C 中断处理函数 +signal.signal(signal.SIGINT, handle_interrupt) +"""
\ No newline at end of file diff --git a/cases/ui/__init__.py b/cases/ui/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/cases/ui/__init__.py diff --git a/cases/ui/__pycache__/__init__.cpython-38.pyc b/cases/ui/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..abb59e52 --- /dev/null +++ b/cases/ui/__pycache__/__init__.cpython-38.pyc diff --git a/cases/ui/fast_test/__init__.py b/cases/ui/fast_test/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/cases/ui/fast_test/__init__.py diff --git a/cases/ui/fast_test/__pycache__/__init__.cpython-38.pyc b/cases/ui/fast_test/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..d1ac4718 --- /dev/null +++ b/cases/ui/fast_test/__pycache__/__init__.cpython-38.pyc diff --git a/cases/ui/fast_test/__pycache__/test_fast.cpython-38-pytest-7.4.0.pyc b/cases/ui/fast_test/__pycache__/test_fast.cpython-38-pytest-7.4.0.pyc Binary files differnew file mode 100644 index 00000000..b7739ef8 --- /dev/null +++ b/cases/ui/fast_test/__pycache__/test_fast.cpython-38-pytest-7.4.0.pyc diff --git a/cases/ui/fast_test/test_fast.py b/cases/ui/fast_test/test_fast.py new file mode 100644 index 00000000..2522d5b9 --- /dev/null +++ b/cases/ui/fast_test/test_fast.py @@ -0,0 +1,217 @@ +# -*- coding: UTF-8 -*- +import time +import pytest +from common.ui_common.profiles.response_pages import ResponsePages +from common.ui_common.profiles.dns_records import DnsRecords +from common.ui_common.profiles.shaping_profiles import ShapingProfiles +from common.ui_common.profiles.traffic_mirroring_profiles import TrafficMirroringProfiles +from common.ui_common.profiles.ssl_decryption_keyrings import SSLDecryptionKeyrings +from common.ui_common.profiles.ssl_decryption_profiles import SSLDecryptionProfiles +from common.ui_common.profiles.hijack_files import HijackFiles +from common.ui_read_data.read_data import ReadData +from cases.conftest import demo_fixture + + +#data = ReadData() +""" +1.快速用例已包含: +profiles:dns records、shaping profiles +""" + +class TestFast: + # response pages 快速测试 + @pytest.mark.parametrize( + "data", + [ + { + "ids": "创建respose_page文件再修改", + "model": "modify", + "file": "testa.html->testb.html" + } + ], + ids=["创建respose_page文件再修改"] + ) + def test_responsePages_modify(self, demo_fixture, data): + responsePages = ResponsePages(demo_fixture) + responsePage_name = responsePages.create(data) + responsePage_id = responsePages.query(data, require_assertion=1, Name=responsePage_name) + responsePages.modify(data) + responsePages.query(data, require_assertion=2, ID=responsePage_id) + responsePages.delete() + + # dns records 快速测试 + @pytest.mark.parametrize( + "data", [ + { + "ids": "创建多类型A,再修改为CNAME用例", + "model": "modify", + "type": "A->CNAME", + "values": + [ + "112.12.32.12->test.sdgoc.sdwa.caom.com", + "53.23.234.21->", + "12.12.33.45->test.sodmao.asdo.com", + "->test.sddsg.sdsd.fco.cn" + ], + "description": "12.12.33.45->test.sodmao.asdo.com" + } + ], + ids=["创建多类型A,再修改为CNAME用例"] + ) + def test_dnsRecords_modify(self, demo_fixture, data): #外部方法调用测试(增、查、改、删) + dnsRecords = DnsRecords(demo_fixture) + dnsRecord_name = dnsRecords.create(data) + dnsRecord_id = dnsRecords.query(data, require_assertion=1, Name=dnsRecord_name) + dnsRecords.modify(data) + dnsRecords.query(data, require_assertion=2, ID=dnsRecord_id) + dnsRecords.delete() + + # trafficMirroringProfiles 快速测试 + @pytest.mark.parametrize( + "data", + [ + { + "ids": "创建vlanid再修改", + "model": "modify", + "vlan_id": + [ + "16->7", + "18->", + "->23", + "25->45", + "55->55" + ] + } + ], + ids=["创建vlanid再修改"] + ) + def test_trafficMirroringProfiles_modify(self, demo_fixture, data): + trafficMirroringProfiles = TrafficMirroringProfiles(demo_fixture) + trafficMirroringProfiles_name = trafficMirroringProfiles.create(data) + trafficMirroringProfiles_id = trafficMirroringProfiles.query(data, require_assertion=1, Name=trafficMirroringProfiles_name) + trafficMirroringProfiles.modify(data) + trafficMirroringProfiles.query(data, require_assertion=2, ID=trafficMirroringProfiles_id) + trafficMirroringProfiles.delete() + + #shaping profiles 快速测试 + @pytest.mark.parametrize( + "data", [ + { + "ids": "创建Fair_Share_bps再修改为Gps带宽", + "model": "modify", + "type": "Fair Share", + "argument": "Max Min Host Fairness", + "unit": "bps->Gbps", + "incoming": "670->856", + "outgoing": "550->543" + } + ], + ids=["创建Fair_Share_bps再修改为Gps带宽"] + ) + def test_shapingProfiles_modify(self, demo_fixture, data): #外部方法调用测试(增、查、改、删) + shapingProfiles = ShapingProfiles(demo_fixture) + shapingProfile_name = shapingProfiles.create(data) + shapingProfile_id = shapingProfiles.query(data, require_assertion=1, Name=shapingProfile_name) + shapingProfiles.modify(data) #修改 + shapingProfiles.query(data, require_assertion=2, ID=shapingProfile_id) + shapingProfiles.delete() + + #sslDecryptionKeyrings快速测试 + @pytest.mark.parametrize( + "data", + [ + { + "ids": "创建root_根证书PKA设置为RSA-2048再修改为中间证书PKA设置为RSA-1024", + "model": "modify", + "certificate": "test_root_cert_catest.cer->test_mid_cert_camiddletest.chain.pem", + "private_key": "PKF-test_root_key_catest.key->PKF-test_mid_key_camiddletest.key", + "reissue_expiry_hours": "MSC->C-120", + "type": "Root-Certificate->Intermediate-Certificate", + "public_key_algorithm": "RSA-2048->RSA-1024", + "certificate_revocation_list": "->不修改", + "include_root": "on->off" + } + ], + ids=["创建root_根证书PKA设置为RSA-2048再修改为中间证书PKA设置为RSA-1024"] + ) + def test_sslDecryptionKeyrings_modify(self, demo_fixture, data): + sslDecryptionKeyrings = SSLDecryptionKeyrings(demo_fixture) + sslDecryptionKeyrings_name = sslDecryptionKeyrings.create(data) + sslDecryptionKeyrings_id = sslDecryptionKeyrings.query(data, require_assertion=1, Name=sslDecryptionKeyrings_name) + sslDecryptionKeyrings.modify(data) + sslDecryptionKeyrings.query(data, require_assertion=2, ID=sslDecryptionKeyrings_id) + sslDecryptionKeyrings.delete() + + # sslDecryptionProfiles快速测试 + @pytest.mark.parametrize( + "data", + [ + { + "ids": "创建ssl_decryption_profiles_fail_action_on再修改common_name_off22", + "model": "modify", + "common_name": "on->off", + "issuer": "on-off>", + "self_signed": "on->不修改", + "expiry_date": "on->不修改", + "fail_action": "Pass-through->Fail-close", + "ev_certificate": "on->off", + "certificate_transparency": "on->不修改", + "mutual_authentication": "on->不修改", + "protocol_errors": "on->不修改", + "certificate_pinning": "on->off", + "certificate_not_installed": "on->", + "mirror_client_versions": "off->on", + "min_client_version": "TLSv1.2->不修改", + "max_client_version": "TLSv1.3->不修改", + "allow_HTTP2": "off->on" + } + ], + ids=["创建ssl_decryption_profiles_fail_action_on再修改common_name_off22"] + ) + def test_sslDecryptionProfiles_modify(self, demo_fixture, data): + sslDecryptionProfiles = SSLDecryptionProfiles(demo_fixture) + sslDecryptionProfiles_name = sslDecryptionProfiles.create(data) + sslDecryptionProfiles_id = sslDecryptionProfiles.query(data, require_assertion=1, Name=sslDecryptionProfiles_name) + sslDecryptionProfiles.modify(data) + sslDecryptionProfiles.query(data, require_assertion=2, ID=sslDecryptionProfiles_id) + sslDecryptionProfiles.delete() + + # HijackFiles 快速测试 + @pytest.mark.parametrize( + "data", + [ + { + "ids": "创建gif类型hijack_files数据再修改数据gif数据", + "model": "modify", + "file": "test_gif_1.gif->test_gif_2.gif", + "download_name": "test_gif_1.gif->Mirror Server Response", + "file_type": "gif->不修改" + } + ], + ids=["创建gif类型hijack_files数据再修改数据gif数据"] + ) + def test_hijackFiles_modify(self, demo_fixture, data): + hijackFiles = HijackFiles(demo_fixture) + hijackFiles_name = hijackFiles.create(data) + hijackFiles_id = hijackFiles.query(data, require_assertion=1, Name=hijackFiles_name) + hijackFiles.modify(data) + hijackFiles.query(data, require_assertion=2, ID=hijackFiles_id) + hijackFiles.delete() + +if __name__ == '__main__': + a = time.time() + print(111111111111) + pytest.main(['-sv', 'test_fast.py', '--check-max-tb=60000']) + + b = time.time() + c = b - a + print("用时:::", c) + print(3333333333333) + + """ + # 在测试文件的当前路径执行如下命令执行测试用例: + pytest –cache-clear -v pytest_json.py --alluredir ./allure + + # 执行如下命令生成测试报告(自动打开浏览器): + allure serve allure + """
\ No newline at end of file diff --git a/cases/ui/profiles/__init__.py b/cases/ui/profiles/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/cases/ui/profiles/__init__.py diff --git a/cases/ui/profiles/__pycache__/__init__.cpython-38.pyc b/cases/ui/profiles/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..c950d3a9 --- /dev/null +++ b/cases/ui/profiles/__pycache__/__init__.cpython-38.pyc diff --git a/cases/ui/profiles/__pycache__/test_dns_records.cpython-38-pytest-7.4.0.pyc b/cases/ui/profiles/__pycache__/test_dns_records.cpython-38-pytest-7.4.0.pyc Binary files differnew file mode 100644 index 00000000..dcd7460d --- /dev/null +++ b/cases/ui/profiles/__pycache__/test_dns_records.cpython-38-pytest-7.4.0.pyc diff --git a/cases/ui/profiles/__pycache__/test_hijack_files.cpython-38-pytest-7.4.0.pyc b/cases/ui/profiles/__pycache__/test_hijack_files.cpython-38-pytest-7.4.0.pyc Binary files differnew file mode 100644 index 00000000..73e33734 --- /dev/null +++ b/cases/ui/profiles/__pycache__/test_hijack_files.cpython-38-pytest-7.4.0.pyc diff --git a/cases/ui/profiles/__pycache__/test_response_pages.cpython-38-pytest-7.4.0.pyc b/cases/ui/profiles/__pycache__/test_response_pages.cpython-38-pytest-7.4.0.pyc Binary files differnew file mode 100644 index 00000000..9353cd88 --- /dev/null +++ b/cases/ui/profiles/__pycache__/test_response_pages.cpython-38-pytest-7.4.0.pyc diff --git a/cases/ui/profiles/__pycache__/test_shaping_profile_records.cpython-38-pytest-7.4.0.pyc b/cases/ui/profiles/__pycache__/test_shaping_profile_records.cpython-38-pytest-7.4.0.pyc Binary files differnew file mode 100644 index 00000000..4730eaef --- /dev/null +++ b/cases/ui/profiles/__pycache__/test_shaping_profile_records.cpython-38-pytest-7.4.0.pyc diff --git a/cases/ui/profiles/__pycache__/test_shaping_profiles.cpython-38-pytest-7.4.0.pyc b/cases/ui/profiles/__pycache__/test_shaping_profiles.cpython-38-pytest-7.4.0.pyc Binary files differnew file mode 100644 index 00000000..738b3a89 --- /dev/null +++ b/cases/ui/profiles/__pycache__/test_shaping_profiles.cpython-38-pytest-7.4.0.pyc diff --git a/cases/ui/profiles/__pycache__/test_ssl_decryption_keyrings.cpython-38-pytest-7.4.0.pyc b/cases/ui/profiles/__pycache__/test_ssl_decryption_keyrings.cpython-38-pytest-7.4.0.pyc Binary files differnew file mode 100644 index 00000000..cd532f89 --- /dev/null +++ b/cases/ui/profiles/__pycache__/test_ssl_decryption_keyrings.cpython-38-pytest-7.4.0.pyc diff --git a/cases/ui/profiles/__pycache__/test_ssl_decryption_profiles.cpython-38-pytest-7.4.0.pyc b/cases/ui/profiles/__pycache__/test_ssl_decryption_profiles.cpython-38-pytest-7.4.0.pyc Binary files differnew file mode 100644 index 00000000..7c8294d5 --- /dev/null +++ b/cases/ui/profiles/__pycache__/test_ssl_decryption_profiles.cpython-38-pytest-7.4.0.pyc diff --git a/cases/ui/profiles/__pycache__/test_traffic_mirroring_profiles.cpython-38-pytest-7.4.0.pyc b/cases/ui/profiles/__pycache__/test_traffic_mirroring_profiles.cpython-38-pytest-7.4.0.pyc Binary files differnew file mode 100644 index 00000000..d1c6904f --- /dev/null +++ b/cases/ui/profiles/__pycache__/test_traffic_mirroring_profiles.cpython-38-pytest-7.4.0.pyc diff --git a/cases/ui/profiles/test_Dos_detection_profiles.py b/cases/ui/profiles/test_Dos_detection_profiles.py new file mode 100644 index 00000000..4c84ac62 --- /dev/null +++ b/cases/ui/profiles/test_Dos_detection_profiles.py @@ -0,0 +1,68 @@ +# -*- coding: UTF-8 -*- +import time +import pytest +from common.ui_common.profiles.Dos_detection import Dos_detection +from common.ui_read_data.read_data import ReadData +from cases.conftest import demo_fixture + +data = ReadData() + + +class TestSSLDecryptionProfiles: + @pytest.mark.parametrize("data", data.read_data_profiles("ssl_decryption_profiles.json"), ids=data.generate_id) + def test_sslDecryptionProfiles(self, demo_fixture, data): + dos_detection = Dos_detection(demo_fixture) + dos_detection.Dos_detection_case(data) + + + @pytest.mark.parametrize( + "data", + [ + { + "ids": "创建ssl_decryption_profiles_fail_action_on再修改common_name_off22", + "model": "modify", + "common_name": "on->off", + "issuer": "on-off>", + "self_signed": "on->不修改", + "expiry_date": "on->不修改", + "fail_action": "Pass-through->不修改", + "ev_certificate": "on->off", + "certificate_transparency": "on->不修改", + "mutual_authentication": "on->不修改", + "protocol_errors": "on->不修改", + "certificate_pinning": "on->off", + "certificate_not_installed": "on->", + "mirror_client_versions": "off->off", + "min_client_version": "TLSv1.2->不修改", + "max_client_version": "TLSv1.3->不修改", + "allow_HTTP2": "off->on" + } + ], + ids=["创建ssl_decryption_profiles_fail_action_on再修改common_name_off22"] + ) + def test_sslDecryptionProfiles_modify(self, demo_fixture, data): + sslDecryptionProfiles = SSLDecryptionProfiles(demo_fixture) + sslDecryptionProfiles_name = sslDecryptionProfiles.create(data) + sslDecryptionProfiles_id = sslDecryptionProfiles.query(data, require_assertion=1, Name=sslDecryptionProfiles_name) + sslDecryptionProfiles.modify(data) + sslDecryptionProfiles.query(data, require_assertion=2, ID=sslDecryptionProfiles_id) + sslDecryptionProfiles.delete() + + +if __name__ == '__main__': + a = time.time() + print(111111111111) + pytest.main(['-sv', 'test_ssl_decryption_profiles.py', '--check-max-tb=60000']) + + b = time.time() + c = b - a + print("用时:::", c) + print(3333333333333) + + """ + # 在测试文件的当前路径执行如下命令执行测试用例: + pytest –cache-clear -v pytest_json.py --alluredir ./allure + + # 执行如下命令生成测试报告(自动打开浏览器): + allure serve allure + """
\ No newline at end of file diff --git a/cases/ui/profiles/test_dns_records.py b/cases/ui/profiles/test_dns_records.py new file mode 100644 index 00000000..8cc3040b --- /dev/null +++ b/cases/ui/profiles/test_dns_records.py @@ -0,0 +1,60 @@ +# -*- coding: UTF-8 -*- +import time +import pytest +from common.ui_common.profiles.dns_records import DnsRecords +from common.ui_read_data.read_data import ReadData +from cases.conftest import demo_fixture + +data = ReadData() + + +class TestDnsRecords: + @pytest.mark.parametrize("data", data.read_data_profiles("dns_records.json"), ids=data.generate_id) + def test_dnsRecords(self, demo_fixture, data): + dnsRecords = DnsRecords(demo_fixture) + dnsRecords.dns_records_case(data) + + @pytest.mark.parametrize( + "data", [ + { + "ids": "创建多类型A,再修改为CNAME用例", + "model": "modify", + "type": "A->CNAME", + "values": + [ + "112.12.32.12->test.sdgoc.sdwa.caom.com", + "53.23.234.21->", + "12.12.33.45->test.sodmao.asdo.com", + "->test.sddsg.sdsd.fco.cn" + ], + "description": "12.12.33.45->test.sodmao.asdo.com" + } + ] + ) + def test_dnsRecords_modify(self, demo_fixture, data): #外部方法调用测试(增、查、改、删) + dnsRecords = DnsRecords(demo_fixture) + dnsRecord_name = dnsRecords.create(data) + dnsRecord_id = dnsRecords.query(data, require_assertion=1, Name=dnsRecord_name) + dnsRecords.modify(data) + dnsRecords.query(data, require_assertion=2, ID=dnsRecord_id) + print(dnsRecord_name) + print(dnsRecord_id) + dnsRecords.delete() + +if __name__ == '__main__': + a = time.time() + print(111111111111) + pytest.main(['-sv', 'test_dns_records.py', '--check-max-tb=60000']) + + b = time.time() + c = b - a + print("用时:::", c) + print(3333333333333) + + """ + # 在测试文件的当前路径执行如下命令执行测试用例: + pytest –cache-clear -v pytest_json.py --alluredir ./allure + + # 执行如下命令生成测试报告(自动打开浏览器): + allure serve allure + """
\ No newline at end of file diff --git a/cases/ui/profiles/test_hijack_files.py b/cases/ui/profiles/test_hijack_files.py new file mode 100644 index 00000000..d92e7146 --- /dev/null +++ b/cases/ui/profiles/test_hijack_files.py @@ -0,0 +1,55 @@ +# -*- coding: UTF-8 -*- +import time +import pytest +from common.ui_common.profiles.hijack_files import HijackFiles +from common.ui_read_data.read_data import ReadData +from cases.conftest import demo_fixture + +data = ReadData() + + +class TestHijackFiles: + @pytest.mark.parametrize("data", data.read_data_profiles("hijack_files.json"), ids=data.generate_id) + def test_hijackFiles(self, demo_fixture, data): + hijackFiles = HijackFiles(demo_fixture) + hijackFiles.hijackFiles_case(data) + + @pytest.mark.parametrize( + "data", + [ + { + "ids": "创建gif类型hijack_files数据再修改数据gif数据", + "model": "modify", + "file": "test_gif_1.gif->test_gif_2.gif", + "download_name": "test_gif_1.gif->Mirror Server Response", + "file_type": "gif->不修改" + } + ], + ids=["创建gif类型hijack_files数据再修改数据gif数据"] + ) + def test_hijackFiles_modify(self, demo_fixture, data): + hijackFiles = HijackFiles(demo_fixture) + hijackFiles_name = hijackFiles.create(data) + hijackFiles_id = hijackFiles.query(data, require_assertion=1, Name=hijackFiles_name) + hijackFiles.modify(data) + hijackFiles.query(data, require_assertion=2, ID=hijackFiles_id) + hijackFiles.delete() + + +if __name__ == '__main__': + a = time.time() + print(111111111111) + pytest.main(['-sv', 'test_hijack_files.py', '--check-max-tb=60000']) + + b = time.time() + c = b - a + print("用时:::", c) + print(3333333333333) + + """ + # 在测试文件的当前路径执行如下命令执行测试用例: + pytest –cache-clear -v pytest_json.py --alluredir ./allure + + # 执行如下命令生成测试报告(自动打开浏览器): + allure serve allure + """
\ No newline at end of file diff --git a/cases/ui/profiles/test_response_pages.py b/cases/ui/profiles/test_response_pages.py new file mode 100644 index 00000000..935f3849 --- /dev/null +++ b/cases/ui/profiles/test_response_pages.py @@ -0,0 +1,53 @@ +# -*- coding: UTF-8 -*- +import time +import pytest +from common.ui_common.profiles.response_pages import ResponsePages +from common.ui_read_data.read_data import ReadData +from cases.conftest import demo_fixture + +data = ReadData() + + +class TestResponsePages: + @pytest.mark.parametrize("data", data.read_data_profiles("response_pages.json"), ids=data.generate_id) + def test_resposnePages(self, demo_fixture, data): + responsePages = ResponsePages(demo_fixture) + responsePages.response_page_case(data) + + @pytest.mark.parametrize( + "data", + [ + { + "ids": "创建respose_page文件再修改", + "model": "modify", + "file": "testa.html->testb.html" + } + ] + ) + def test_responsePages_modify(self, demo_fixture, data): + responsePages = ResponsePages(demo_fixture) + responsePage_name = responsePages.create(data) + responsePage_id = responsePages.query(data, require_assertion=1, Name=responsePage_name) + responsePages.modify(data) + responsePages.query(data, require_assertion=2, ID=responsePage_id) + print(responsePage_id, responsePage_name) + responsePages.delete() + + +if __name__ == '__main__': + a = time.time() + print(111111111111) + pytest.main(['-sv', 'test_response_pages.py', '--check-max-tb=60000']) + + b = time.time() + c = b - a + print("用时:::", c) + print(3333333333333) + + """ + # 在测试文件的当前路径执行如下命令执行测试用例: + pytest –cache-clear -v pytest_json.py --alluredir ./allure + + # 执行如下命令生成测试报告(自动打开浏览器): + allure serve allure + """
\ No newline at end of file diff --git a/cases/ui/profiles/test_shaping_profiles.py b/cases/ui/profiles/test_shaping_profiles.py new file mode 100644 index 00000000..08104d9f --- /dev/null +++ b/cases/ui/profiles/test_shaping_profiles.py @@ -0,0 +1,79 @@ +# -*- coding: UTF-8 -*- +import time +import pytest +from common.ui_common.profiles.shaping_profiles import ShapingProfiles +from common.ui_read_data.read_data import ReadData +from cases.conftest import demo_fixture + +data = ReadData() + + +class TestShapingProfiles: + @pytest.mark.parametrize("data", data.read_data_profiles("shaping_profiles.json"), ids=data.generate_id) + def test_shapingProfiles(self, demo_fixture, data): + shapingProfiles = ShapingProfiles(demo_fixture) + shapingProfiles.shaping_profiles_case(data) + + @pytest.mark.parametrize( + "data", [ + { + "ids": "创建Generic_bps用例", + "model": "create", + "type": "Generic", + "argument": "", + "unit": "bps->", + "incoming": "876->", + "outgoing": "543->" + } + ] + ) + def test_shapingProfiles_create(self, demo_fixture, data): #外部方法调用测试(增、查、删) + shapingProfiles = ShapingProfiles(demo_fixture) + shapingProfile_name = shapingProfiles.create(data) + shapingProfile_id = shapingProfiles.query(data, Name=shapingProfile_name) + print(shapingProfile_name) + print(shapingProfile_id) + shapingProfiles.delete() + + @pytest.mark.parametrize( + "data", [ + { + "ids": "创建Fair_Share_bps再修改为Gps带宽", + "model": "modify", + "type": "Fair Share", + "argument": "Max Min Host Fairness", + "unit": "bps->Gbps", + "incoming": "670->856", + "outgoing": "550->543" + } + ] + ) + def test_shapingProfiles_modify(self, demo_fixture, data): #外部方法调用测试(增、查、改、删) + shapingProfiles = ShapingProfiles(demo_fixture) + shapingProfile_name = shapingProfiles.create(data) + shapingProfile_id = shapingProfiles.query(data, require_assertion=1, Name=shapingProfile_name) + shapingProfiles.modify(data) #修改 + shapingProfiles.query(data, require_assertion=2, ID=shapingProfile_id) + print(shapingProfile_name) + print(shapingProfile_id) + shapingProfiles.delete() + + + +if __name__ == '__main__': + a = time.time() + print(111111111111) + pytest.main(['-sv', 'test_shaping_profiles.py', '--check-max-tb=60000']) + + b = time.time() + c = b - a + print("用时:::", c) + print(3333333333333) + + """ + # 在测试文件的当前路径执行如下命令执行测试用例: + pytest –cache-clear -v pytest_json.py --alluredir ./allure + + # 执行如下命令生成测试报告(自动打开浏览器): + allure serve allure + """
\ No newline at end of file diff --git a/cases/ui/profiles/test_ssl_decryption_keyrings.py b/cases/ui/profiles/test_ssl_decryption_keyrings.py new file mode 100644 index 00000000..f069034d --- /dev/null +++ b/cases/ui/profiles/test_ssl_decryption_keyrings.py @@ -0,0 +1,59 @@ +# -*- coding: UTF-8 -*- +import time +import pytest +from common.ui_common.profiles.ssl_decryption_keyrings import SSLDecryptionKeyrings +from common.ui_read_data.read_data import ReadData +from cases.conftest import demo_fixture + +data = ReadData() + + +class TestSSLDecryptionKeyrings: + @pytest.mark.parametrize("data", data.read_data_profiles("ssl_decryption_keyrings.json"), ids=data.generate_id) + def test_sslDecryptionKeyrings(self, demo_fixture, data): + sslDecryptionKeyrings = SSLDecryptionKeyrings(demo_fixture) + sslDecryptionKeyrings.sslDecryptionKeyrings_case(data) + + @pytest.mark.parametrize( + "data", + [ + { + "ids": "创建root_根证书PKA设置为RSA-2048再修改为中间证书PKA设置为RSA-1024", + "model": "modify", + "certificate": "test_root_cert_catest.cer->test_mid_cert_camiddletest.chain.pem", + "private_key": "PKF-test_root_key_catest.key->PKF-test_mid_key_camiddletest.key", + "reissue_expiry_hours": "MSC->C-120", + "type": "Root-Certificate->Intermediate-Certificate", + "public_key_algorithm": "RSA-2048->RSA-1024", + "certificate_revocation_list": "->不修改", + "include_root": "on->off" + } + ], + ids=["创建root_根证书PKA设置为RSA-2048再修改为中间证书PKA设置为RSA-1024"] + ) + def test_sslDecryptionKeyrings_modify(self, demo_fixture, data): + sslDecryptionKeyrings = SSLDecryptionKeyrings(demo_fixture) + sslDecryptionKeyrings_name = sslDecryptionKeyrings.create(data) + sslDecryptionKeyrings_id = sslDecryptionKeyrings.query(data, require_assertion=1, Name=sslDecryptionKeyrings_name) + sslDecryptionKeyrings.modify(data) + sslDecryptionKeyrings.query(data, require_assertion=2, ID=sslDecryptionKeyrings_id) + sslDecryptionKeyrings.delete() + + +if __name__ == '__main__': + a = time.time() + print(111111111111) + pytest.main(['-sv', 'test_ssl_decryption_keyrings.py', '--check-max-tb=60000']) + + b = time.time() + c = b - a + print("用时:::", c) + print(3333333333333) + + """ + # 在测试文件的当前路径执行如下命令执行测试用例: + pytest –cache-clear -v pytest_json.py --alluredir ./allure + + # 执行如下命令生成测试报告(自动打开浏览器): + allure serve allure + """
\ No newline at end of file diff --git a/cases/ui/profiles/test_ssl_decryption_profiles.py b/cases/ui/profiles/test_ssl_decryption_profiles.py new file mode 100644 index 00000000..0e50b461 --- /dev/null +++ b/cases/ui/profiles/test_ssl_decryption_profiles.py @@ -0,0 +1,67 @@ +# -*- coding: UTF-8 -*- +import time +import pytest +from common.ui_common.profiles.ssl_decryption_profiles import SSLDecryptionProfiles +from common.ui_read_data.read_data import ReadData +from cases.conftest import demo_fixture + +data = ReadData() + + +class TestSSLDecryptionProfiles: + @pytest.mark.parametrize("data", data.read_data_profiles("ssl_decryption_profiles.json"), ids=data.generate_id) + def test_sslDecryptionProfiles(self, demo_fixture, data): + sslDecryptionProfiles = SSLDecryptionProfiles(demo_fixture) + sslDecryptionProfiles.sslDecryptionProfiles_case(data) + + @pytest.mark.parametrize( + "data", + [ + { + "ids": "创建ssl_decryption_profiles_fail_action_on再修改common_name_off22", + "model": "modify", + "common_name": "on->off", + "issuer": "on-off>", + "self_signed": "on->不修改", + "expiry_date": "on->不修改", + "fail_action": "Pass-through->不修改", + "ev_certificate": "on->off", + "certificate_transparency": "on->不修改", + "mutual_authentication": "on->不修改", + "protocol_errors": "on->不修改", + "certificate_pinning": "on->off", + "certificate_not_installed": "on->", + "mirror_client_versions": "off->off", + "min_client_version": "TLSv1.2->不修改", + "max_client_version": "TLSv1.3->不修改", + "allow_HTTP2": "off->on" + } + ], + ids=["创建ssl_decryption_profiles_fail_action_on再修改common_name_off22"] + ) + def test_sslDecryptionProfiles_modify(self, demo_fixture, data): + sslDecryptionProfiles = SSLDecryptionProfiles(demo_fixture) + sslDecryptionProfiles_name = sslDecryptionProfiles.create(data) + sslDecryptionProfiles_id = sslDecryptionProfiles.query(data, require_assertion=1, Name=sslDecryptionProfiles_name) + sslDecryptionProfiles.modify(data) + sslDecryptionProfiles.query(data, require_assertion=2, ID=sslDecryptionProfiles_id) + sslDecryptionProfiles.delete() + + +if __name__ == '__main__': + a = time.time() + print(111111111111) + pytest.main(['-sv', 'test_ssl_decryption_profiles.py', '--check-max-tb=60000']) + + b = time.time() + c = b - a + print("用时:::", c) + print(3333333333333) + + """ + # 在测试文件的当前路径执行如下命令执行测试用例: + pytest –cache-clear -v pytest_json.py --alluredir ./allure + + # 执行如下命令生成测试报告(自动打开浏览器): + allure serve allure + """
\ No newline at end of file diff --git a/cases/ui/profiles/test_traffic_mirroring_profiles.py b/cases/ui/profiles/test_traffic_mirroring_profiles.py new file mode 100644 index 00000000..17076a65 --- /dev/null +++ b/cases/ui/profiles/test_traffic_mirroring_profiles.py @@ -0,0 +1,60 @@ +# -*- coding: UTF-8 -*- +import time +import pytest +from common.ui_common.profiles.traffic_mirroring_profiles import TrafficMirroringProfiles +from common.ui_read_data.read_data import ReadData +from cases.conftest import demo_fixture + +data = ReadData() + + +class TestTrafficMirroringProfiles: + @pytest.mark.parametrize("data", data.read_data_profiles("traffic_mirroring_profiles.json"), ids=data.generate_id) + def test_trafficMirroringProfiles(self, demo_fixture, data): + trafficMirroringProfiles = TrafficMirroringProfiles(demo_fixture) + trafficMirroringProfiles.traffic_morroring_profiles_case(data) + + @pytest.mark.parametrize( + "data", + [ + { + "ids": "创建vlanid再修改", + "model": "modify", + "vlan_id": + [ + "16->7", + "18->", + "->23", + "25->45", + "55->55" + ] + } + ] + ) + def test_trafficMirroringProfiles_modify(self, demo_fixture, data): + trafficMirroringProfiles = TrafficMirroringProfiles(demo_fixture) + trafficMirroringProfiles_name = trafficMirroringProfiles.create(data) + trafficMirroringProfiles_id = trafficMirroringProfiles.query(data, require_assertion=1, Name=trafficMirroringProfiles_name) + trafficMirroringProfiles.modify(data) + trafficMirroringProfiles.query(data, require_assertion=2, ID=trafficMirroringProfiles_id) + print(trafficMirroringProfiles_id, trafficMirroringProfiles_name) + trafficMirroringProfiles.delete() + + +if __name__ == '__main__': + a = time.time() + print(111111111111) + pytest.main(['-sv', 'test_response_pages.py', '--check-max-tb=60000']) + + b = time.time() + c = b - a + print("用时:::", c) + print(3333333333333) + + """ + # 在测试文件的当前路径执行如下命令执行测试用例: + pytest –cache-clear -v pytest_json.py --alluredir ./allure + + # 执行如下命令生成测试报告(自动打开浏览器): + allure serve allure + """
\ No newline at end of file diff --git a/common/__init__.py b/common/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/common/__init__.py diff --git a/common/__pycache__/__init__.cpython-38.pyc b/common/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..13af0213 --- /dev/null +++ b/common/__pycache__/__init__.cpython-38.pyc diff --git a/common/__pycache__/demo_1.cpython-38.pyc b/common/__pycache__/demo_1.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..b74fe3a6 --- /dev/null +++ b/common/__pycache__/demo_1.cpython-38.pyc diff --git a/common/__pycache__/read_data.cpython-38.pyc b/common/__pycache__/read_data.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..22ea7626 --- /dev/null +++ b/common/__pycache__/read_data.cpython-38.pyc diff --git a/common/demo_1.py b/common/demo_1.py new file mode 100644 index 00000000..e5fcd4f7 --- /dev/null +++ b/common/demo_1.py @@ -0,0 +1,23 @@ +import pytest +import requests +import time + + +def demo1(): + assert 1 == 11 + +def demo2(data): + print(f"demo2使用数据{data}") + assert 2 == 2 + +class DemoA: + def __init__(self): + self.n = 1 + + def demo3(self, data): + print(f"demo3使用数据{data}") + assert 3 == 3 + + def demo4(self, data): + print(f"demo4使用数据{data}") + assert 4 == 4
\ No newline at end of file diff --git a/common/driver_common/__init__.py b/common/driver_common/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/common/driver_common/__init__.py diff --git a/common/driver_common/__pycache__/__init__.cpython-38.pyc b/common/driver_common/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..38bc323b --- /dev/null +++ b/common/driver_common/__pycache__/__init__.cpython-38.pyc diff --git a/common/driver_common/__pycache__/mywebdriver.cpython-38.pyc b/common/driver_common/__pycache__/mywebdriver.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..8e258f8b --- /dev/null +++ b/common/driver_common/__pycache__/mywebdriver.cpython-38.pyc diff --git a/common/driver_common/__pycache__/random_name.cpython-38.pyc b/common/driver_common/__pycache__/random_name.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..ce517551 --- /dev/null +++ b/common/driver_common/__pycache__/random_name.cpython-38.pyc diff --git a/common/driver_common/__pycache__/screenshot.cpython-38.pyc b/common/driver_common/__pycache__/screenshot.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..1c1f63c7 --- /dev/null +++ b/common/driver_common/__pycache__/screenshot.cpython-38.pyc diff --git a/common/driver_common/mywebdriver.py b/common/driver_common/mywebdriver.py new file mode 100644 index 00000000..cb8dadaf --- /dev/null +++ b/common/driver_common/mywebdriver.py @@ -0,0 +1,58 @@ +import time +import traceback +import inspect +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.support.wait import WebDriverWait +from typing import Optional + + +class MyWebDriver(webdriver.Remote): + def find_element(self, by=By.ID, value: Optional[str] = None, + find_before_wait_time=0.3, find_after_wait_time=0.3, wait_timeout=10): + if wait_timeout > 60: + wait_timeout = 60 + while wait_timeout > 0: + time.sleep(find_before_wait_time) + wait_timeout = wait_timeout - (find_before_wait_time if find_before_wait_time > 0 else 2.5) + try: + self.element = super().find_element(by, value) + except: + caller_info = inspect.stack()[1] + caller_filename = caller_info.filename + caller_line_number = caller_info.frame + caller_code_context = caller_info.code_context + print(caller_filename, caller_line_number, caller_code_context) + print(f"查找方法:{by};-->>", f"查找元素:{value}\n") + throw_assert = 1 + assert_info = traceback.format_exc() + continue + else: + time.sleep(find_after_wait_time) + throw_assert = 0 + break #找到则退出循环 + if throw_assert == 1: + print(assert_info) + raise + return self.element + + + +if __name__ == '__main__': + chrome_option = webdriver.ChromeOptions() + driver = MyWebDriver( + command_executor="http://192.168.64.34:4444", + options=chrome_option + ) + driver.implicitly_wait(5) + driver.get("http://192.168.44.72") + driver.find_element(By.NAME, "username1").send_keys("zcw3") + driver.find_element(By.NAME, "username").send_keys("zcw3") + driver.find_element(By.NAME, "username").send_keys("zcw3") + driver.find_element(By.NAME, "username").send_keys("zcw3") + driver.find_element(By.NAME, "password").send_keys("111111") + driver.find_element(By.NAME, "password").send_keys("111111") + driver.find_element(By.NAME, "password").send_keys("111111") + driver.find_element(By.NAME, "password").send_keys("111111") + + driver.quit() diff --git a/common/driver_common/random_name.py b/common/driver_common/random_name.py new file mode 100644 index 00000000..8f5327f0 --- /dev/null +++ b/common/driver_common/random_name.py @@ -0,0 +1,48 @@ +import random +import string +import time +import datetime + +class RandomName: + """ + 生成随机使用名称 + """ + def __init__(self, pro_name="test_uitemp", r_letter_count=8, r_number_count=8): + self.pro_name = pro_name + self.r_letter_count = r_letter_count + self.r_number_count = r_number_count + + def random_name(self): + letters = self.random_letter(self.r_letter_count) + numbers = self.random_number(self.r_number_count) + format_time = self.current_time() + r_name = f"{self.pro_name}_{letters}_{numbers}_{format_time}" + return r_name + + def random_letter(self, count=8): + temp_list = [] + for i in range(count): + temp_list.append(random.choice(string.ascii_letters)) + r_letter = "".join(temp_list) + #print(r_letter) + return r_letter + + def random_number(self, count=8): + temp_list = [] + for i in range(count): + temp_list.append(random.choice(string.digits)) + r_number = "".join(temp_list) + #print(r_number) + return r_number + + def current_time(self): + c_time = time.time() + formatted_time = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d-%H-%M-%S') + return formatted_time + +# r = RandomName() +# c = r.random_name() +# print(c) +# print(c) +# print(c) + diff --git a/common/driver_common/recovery.py b/common/driver_common/recovery.py new file mode 100644 index 00000000..b982faa9 --- /dev/null +++ b/common/driver_common/recovery.py @@ -0,0 +1,25 @@ +import configparser +from config.workpath import * +import requests + + +class Recovery: + """ + 自动回收异常时,产生的创建对象 + 从接口来删除对象 + """ + def __init__(self): + #初始化,负载远程用户登录 + self.loginout_parse = configparser.ConfigParser() + loginout_parse_dir = os.path.join(workdir, "config", "ui_conf", "loginout.ini") + self.loginout_parse.read(loginout_parse_dir, encoding="utf-8") + self.username = self.loginout_parse.get("ui_account_1", "username") + self.passwd = self.loginout_parse.get("ui_account_1", "passwd") + + def login_by_interface(self): + #todo + pass + + def del_profile(self): + # todo + pass diff --git a/common/driver_common/screenshot.py b/common/driver_common/screenshot.py new file mode 100644 index 00000000..84c00968 --- /dev/null +++ b/common/driver_common/screenshot.py @@ -0,0 +1,39 @@ +from selenium import webdriver +import shutil +import time, datetime +import os +import functools +from config.workpath import workdir + +#截图装饰器 +def screenshot_on_failure(func): + @functools.wraps(func) + def warpper(self, *args, **kwargs): + try: + return func(self, *args, **kwargs) + except: + driver = self.driver + if driver: + formatted_time = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d-%H-%M-%S') + file = "{}.png".format(formatted_time) + file_path = os.path.join(workdir, "results", "screenshot", file) + print(f"截图保存于:{file_path}") + driver.save_screenshot(file_path) + #删除历史7天前数据 + try: + clear_history(file_path) + except: + print("删除历史数据失败...") + raise + return warpper + +def clear_history(file_path, retain_time=3600*24*1): + time_now = time.time() + file_work = os.path.dirname(file_path) + data_list = [os.path.join(file_work, i) for i in os.listdir(file_work)] + for datapath in data_list: + if time_now - os.path.getctime(datapath) > retain_time: + try: + os.remove(datapath) + except: + shutil.rmtree(datapath) diff --git a/common/read_data.py b/common/read_data.py new file mode 100644 index 00000000..69d6478c --- /dev/null +++ b/common/read_data.py @@ -0,0 +1,16 @@ +import json + +class ReadData: + def __init__(self): + print(__file__) + + @property + def read_from_json(self): + with open("C:/zcw/aoto_selenium/testdata/demo1_data.json", "r") as f: + data = json.load(f)["item"] + data = list(data) + return data + + +if __name__ == '__main__': + ReadData().read_from_json
\ No newline at end of file diff --git a/common/ui_common/__init__.py b/common/ui_common/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/common/ui_common/__init__.py diff --git a/common/ui_common/__pycache__/__init__.cpython-38.pyc b/common/ui_common/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..3c247a2f --- /dev/null +++ b/common/ui_common/__pycache__/__init__.cpython-38.pyc diff --git a/common/ui_common/login_logout/__init__.py b/common/ui_common/login_logout/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/common/ui_common/login_logout/__init__.py diff --git a/common/ui_common/login_logout/__pycache__/__init__.cpython-38.pyc b/common/ui_common/login_logout/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..d7ef9377 --- /dev/null +++ b/common/ui_common/login_logout/__pycache__/__init__.cpython-38.pyc diff --git a/common/ui_common/login_logout/__pycache__/loginout.cpython-38.pyc b/common/ui_common/login_logout/__pycache__/loginout.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..56aba1be --- /dev/null +++ b/common/ui_common/login_logout/__pycache__/loginout.cpython-38.pyc diff --git a/common/ui_common/login_logout/loginout.py b/common/ui_common/login_logout/loginout.py new file mode 100644 index 00000000..f09ddcb2 --- /dev/null +++ b/common/ui_common/login_logout/loginout.py @@ -0,0 +1,26 @@ +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +import configparser +from config.workpath import * +from page_element.element_position import * + +class LogInOut: + def __init__(self, driver: MyWebDriver): + self.driver = driver + #初始化,负载远程用户登录 + self.loginout_parse = configparser.ConfigParser() + loginout_parse_dir = os.path.join(workdir, "config", "ui_conf", "loginout.ini") + self.loginout_parse.read(loginout_parse_dir, encoding="utf-8") + self.tsglogin_url = self.loginout_parse.get("tsg_url", "login_url") + + def login(self): + self.driver.get(self.tsglogin_url) + #输入账户和密码 + self.driver.find_element(By.NAME, loginPage_userName_posName).send_keys(self.loginout_parse.get("ui_account_1", "username")) + self.driver.find_element(By.NAME, loginPage_passwd_posName).send_keys(self.loginout_parse.get("ui_account_1", "passwd")) + self.driver.find_element(By.ID, loginPage_signIn_posId).click() + + def logout(self): + pass + + diff --git a/common/ui_common/profiles/Dos_detection.py b/common/ui_common/profiles/Dos_detection.py new file mode 100644 index 00000000..ada88436 --- /dev/null +++ b/common/ui_common/profiles/Dos_detection.py @@ -0,0 +1,248 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect + + +class Dos_detection: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + + def Dos_detection_case(self, data: {}): + """ + 测试用例调用函数, + :param demo_fixture: 传入driver + :param data: 测试数据。 + + :return: + """ + #self.driver = demo_fixture + self._create(data) #创建 + self._query(data, require_assertion=1, Name=self.random_name) #创建后查询 + if data["model"].strip().lower() == "modify": #修改测试时,执行修改方法 + self._modify(data) + self._query(data, require_assertion=2, ID=self.first_row_ID_content) # 修改后查询 + self._del() #删除数据 + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到shapingProfiles列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_shapingProfiles_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #页面跳转 + self._goto_subProfilePage() + #创建shapingProfiles + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_shapingProfiles_createButton_posId).click() + #在create dns shapingProfiles操作 + self.driver.find_element(By.ID, shapingProfilePage_input_Name_posId).send_keys(self.random_name) #输入名字 + #判断点击哪种类型 + self._select_type(data) + self._select_limits(data, model=0) + #点击ok + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_warningSaveYes_posCss).click() + return self.random_name + + @screenshot_on_failure + def _a(self, data: {}): + print(__name__) + 1 == 1 + return 444 + + @screenshot_on_failure + def _select_type(self, data: {}): + """ + 选择type类型点击 + :param data: + :return: + """ + type: str = data["type"].strip().lower() + argument: str = data["argument"].strip().lower() + if type == "generic": + element_type_pos = shapingProfilePage_radioButton_generic_posXpath + elif type == "fair share": + element_type_pos = shapingProfilePage_radioButton_fairShare_posXpath + if argument == "Max Min Host Fairness".lower(): + element_argument_pos = shapingProfilePage_radioButton_maxMinHostFairness_posXpath + else: + raise ValueError(f"用例参数argument:{argument}") + else: + element_type_pos = shapingProfilePage_radioButton_splitBy_posXpath + if argument == "Local Host".lower(): + element_argument_pos = shapingProfilePage_radioButton_localHost_posXpath + else: + raise ValueError(f"用例参数argument:{argument}") + #点击type类型 + self.driver.find_element(By.XPATH, element_type_pos).click() + #判断是否点击Argument + if type != "generic": + self.driver.find_element(By.XPATH, element_argument_pos).click() + + @screenshot_on_failure + def _select_limits(self, data: {}, model=0): + """ + 输入limits + :param data: + :param model: =0表示创建时调用。-1表示修改时调用 + :return: + """ + unitItem = data["unit"].strip().split("->")[model] + element_dropDown_unitItem = shapingProfilePage_drowDown_unitItem_posXpath.format(replaceName=unitItem) + #点击Unit并选择单位 + self.driver.find_element(By.ID, shapingProfilePage_inputSelect_unit_posId).click() + self.driver.find_element(By.XPATH, element_dropDown_unitItem).click() + #输入incoming、outgoing + input_incoming = data["incoming"].strip().split("->")[model] + input_outgoing = data["outgoing"].strip().split("->")[model] + self.driver.find_element(By.ID, shapingProfilePage_input_incoming_posId).clear() + self.driver.find_element(By.ID, shapingProfilePage_input_incoming_posId).send_keys(input_incoming) + self.driver.find_element(By.ID, shapingProfilePage_input_outgoing_posId).clear() + self.driver.find_element(By.ID, shapingProfilePage_input_outgoing_posId).send_keys(input_outgoing) + + @screenshot_on_failure + def _query(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None, + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_shapingProfiles_selectLabel_posId, listPage_profileSearch_shapingProfiles_dropDown_item_posXpath, + listPage_profileSearch_shapingProfiles_input_itemContent_posXpath, listPage_profileSearch_shapingProfiles_buttonSearch_posId, + listPage_profilTable_shapingProfiles_tableTbody_posXpath, listPage_profilTable_shapingProfiles_tableHeader_posXpath, **kwargs) + """ + #点击search查询框 + self.driver.find_element(By.ID, listPage_profileSearch_shapingProfiles_selectLabel_posId).click() + #循环输入查询内容 + for key, value in kwargs.items(): + dropdown_item_posXpath = listPage_profileSearch_shapingProfiles_dropDown_item_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, dropdown_item_posXpath).click() #点击下拉item + if key != "type": + input_item_posXpath = listPage_profileSearch_shapingProfiles_input_itemContent_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, input_item_posXpath).send_keys(value.strip()) #输入查询值 + else: + pass + # dropdown_typeItem_posXpath = listPage_profileSearch_dnsRecords_dropDown_typeItem_posXpath.format(replaceName=value.split("->")[0]) + # self.driver.find_element(By.XPATH, dropdown_typeItem_posXpath).click() #点击type的下拉item + #点击查询按钮 + element_search = self.driver.find_element(By.ID, listPage_profileSearch_shapingProfiles_buttonSearch_posId) + self.driver.execute_script("arguments[0].click()", element_search) #强制点击 + element_tbody = self.driver.find_element(By.XPATH, listPage_profilTable_shapingProfiles_tableTbody_posXpath) #找到所有的行,table的body + element_header = self.driver.find_element(By.XPATH, listPage_profilTable_shapingProfiles_tableHeader_posXpath) #查询table的header + #获取table header的text、th.class + headers = element_header.find_elements(By.XPATH, "th") #table header + rows = element_tbody.find_elements(By.XPATH, "tr") #table body + map_header_className = {} #表头名称和th.class的映射,为了从表body中取对应列的值{"ID":"33"} + for th in headers: + header_content = th.text.strip() + classNames = th.get_attribute("class").split() + for c_name in classNames: + if "el-table" in c_name: + tableBodyRowClassName = c_name + if header_content and tableBodyRowClassName: + map_header_className[header_content] = tableBodyRowClassName + #从第一行查询的结果中,取出需要断言的值、name、Type、Values + first_row = rows[0] + """ + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + first_row_Type_class = map_header_className["Type"] + first_row_Type_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Type_class}')]//span").text.strip() + first_row_IncomingOutgoing_class = map_header_className["Incoming/Outgoing"] + first_row_IncomingOutgoing_contents = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_IncomingOutgoing_class}')]//span").text.strip() + + print(first_row_id_content, first_row_Name_content, first_row_Type_content, first_row_IncomingOutgoing_contents) + #不同操作后的断言,创建后、修改后、无断言 + if require_assertion == 1: #直接创建后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.equal(first_row_Type_content, data["type"].strip(), msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["outgoing"].strip().split("->")[0] == "0": #为0时,直接断言Unlimit + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["outgoing"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["incoming"].strip().split("->")[0] == "0": + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["incoming"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.equal(first_row_Type_content, data["type"].split("->")[-1], msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["outgoing"].strip().split("->")[-1] == "0": #为0时,直接断言Unlimit + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["outgoing"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["incoming"].strip().split("->")[-1] == "0": + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["incoming"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_shapingProfiles_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_shapingProfiles_editButton_posId).click() + #根据修改数据,重新输入limits + self._select_limits(data, model=-1) + #点击ok + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_shapingProfiles_delButton_posId, listPage_dialogTips_shapingProfiles_button_yes_posCss, + listPage_dialogTips_shapingProfiles_button_no_posCss) + + create = _create + query = _query + modify = _modify + delete = _del diff --git a/common/ui_common/profiles/__init__.py b/common/ui_common/profiles/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/common/ui_common/profiles/__init__.py diff --git a/common/ui_common/profiles/__pycache__/__init__.cpython-38.pyc b/common/ui_common/profiles/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..12f4a2fb --- /dev/null +++ b/common/ui_common/profiles/__pycache__/__init__.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/dns_records.cpython-38.pyc b/common/ui_common/profiles/__pycache__/dns_records.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..5a164705 --- /dev/null +++ b/common/ui_common/profiles/__pycache__/dns_records.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/hijack_files.cpython-38.pyc b/common/ui_common/profiles/__pycache__/hijack_files.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..687f3e13 --- /dev/null +++ b/common/ui_common/profiles/__pycache__/hijack_files.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/profiles_public_operations.cpython-38.pyc b/common/ui_common/profiles/__pycache__/profiles_public_operations.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..ae34623c --- /dev/null +++ b/common/ui_common/profiles/__pycache__/profiles_public_operations.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/response_pages.cpython-38.pyc b/common/ui_common/profiles/__pycache__/response_pages.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..f8f10cef --- /dev/null +++ b/common/ui_common/profiles/__pycache__/response_pages.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/shaping_profiles.cpython-38.pyc b/common/ui_common/profiles/__pycache__/shaping_profiles.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..beae1dcf --- /dev/null +++ b/common/ui_common/profiles/__pycache__/shaping_profiles.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/ssl_decryption_keyrings.cpython-38.pyc b/common/ui_common/profiles/__pycache__/ssl_decryption_keyrings.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..11cf401b --- /dev/null +++ b/common/ui_common/profiles/__pycache__/ssl_decryption_keyrings.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/ssl_decryption_profiles.cpython-38.pyc b/common/ui_common/profiles/__pycache__/ssl_decryption_profiles.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..e26b49a4 --- /dev/null +++ b/common/ui_common/profiles/__pycache__/ssl_decryption_profiles.cpython-38.pyc diff --git a/common/ui_common/profiles/__pycache__/traffic_mirroring_profiles.cpython-38.pyc b/common/ui_common/profiles/__pycache__/traffic_mirroring_profiles.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..6a9287a9 --- /dev/null +++ b/common/ui_common/profiles/__pycache__/traffic_mirroring_profiles.cpython-38.pyc diff --git a/common/ui_common/profiles/dns_records.py b/common/ui_common/profiles/dns_records.py new file mode 100644 index 00000000..f07116c3 --- /dev/null +++ b/common/ui_common/profiles/dns_records.py @@ -0,0 +1,288 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect + + +class DnsRecords: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + + def dns_records_case(self, data: {}): + """ + 测试用例调用函数, + :param demo_fixture: 传入driver + :param data: 测试数据。 + 例如:create. + { + "model":"create", + "type":"A", + "values": + [ + "2.2.2.2", + "3.3.3.3", + "4.4.4.4" + ] + } + 例如:modify."12.12.12.12->34.45.67.54"表示修改前后数据,'->'为前后数据分隔符。在修改中,分隔符前为空表示新增数据。分隔符后为空表示删除数据。其它同理 + { + "ids": "创建多个类型A,再修改为多个类型A用例", + "model": "modify", + "type": "A->A", + "values": + [ + "12.12.12.12->34.45.67.54", + "13.13.31.13->", + "->65.123.34.56", + "14.14.14.41->56.43.46.64", + "->165.123.134.56" + ], + "description": "test-description->tesst modify desc" + } + :return: + """ + self._create(data) #创建 + self._search(data, require_assertion=1, Name=self.random_name) #创建后查询 + self._modify(data) + self._search(data, require_assertion=2, ID=self.first_row_ID_content) # 修改后查询 + self._del() #删除数据 + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到dnsRecords列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_dnsRecords_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #goto dnsRecords列表页 + self._goto_subProfilePage() #跳转页面 + #创建dns record + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_dnsRecords_createButton_posId).click() + #在create dns record profile操作 + self.driver.find_element(By.ID, dnsRecordsProfilePage_input_Name_posId).send_keys(self.random_name) #输入名字 + #判断点击哪种类型 + self._select_type(data, model=0) + #创建time操作 + self._ceate_item(data, model=0) + #输入description内容 + self.driver.find_element(By.ID, dnsRecordsProfilePage_textArea_Description_posId).send_keys(data["description"].split("->")[0]) + self.driver.find_element(By.CSS_SELECTOR, dnsRecordsProfilePage_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, dnsRecordsProfilePage_button_warningSaveYes_posCss).click() + return self.random_name + + def _select_type(self, data, model=0): + """ + 根据model参数,选择点击那种类型,0为创建函数使用,-1为编辑修改函数使用 + :param data: + :param model: + :return: + """ + type: str = data["type"].split("->")[model] #因为modify时,有->表示 + type = type.strip().lower() + if type == "a": + type_posId = dnsRecordsProfilePage_radioButton_typeA_posId + elif type == "aaaa": + type_posId = dnsRecordsProfilePage_radioButton_typeAAAA_posId + else: + type_posId = dnsRecordsProfilePage_radioButton_typeCNAME_posId + self.driver.find_element(By.ID, type_posId).click() + + def _ceate_item(self, data, model=0): + """ + 根据参数,选择创建item的方式,0为创建函数使用。-1为编辑修改函数使用且当type类型和创建时不一样。 + :param data: + :param model: + :return: + """ + items: list = data["values"] + flags = 0 #当一个非空数据时,不点击添加按钮 + for i in range(len(items)): + if items[i].split("->")[model] == "": #modify数据中->左侧为空(创建侧) + continue + #判断是否需要点击添加按钮 + if items[i].split("->")[model] != "": + flags += 1 #第一个非空标志 + if flags == 1: #遇到第一个分空数据,不用点击 + pass + else: #第二个后续的非空数据,点击添加 + self.driver.find_element(By.ID, dnsRecordsProfilePage_button_addItem_posId).click() + #添加item时,text()=空,xpath可以定位到 + if "replaceName" in dnsRecordsProfilePage_input_inputItemName_posXpath: + item_input_posCss = dnsRecordsProfilePage_input_inputItemName_posXpath.replace("replaceName", "") + else: + raise ValueError(f"replaceName not found in {dnsRecordsProfilePage_input_inputItemName_posXpath}") + if "replaceName" in dnsRecordsProfilePage_button_saveItemByName_posXpath: + item_save_posCss = dnsRecordsProfilePage_button_saveItemByName_posXpath.replace("replaceName", items[i].split("->")[model]) #->修改中会此表标识 + else: + raise ValueError(f"replaceName not found in {dnsRecordsProfilePage_button_saveItemByName_posXpath}") + #输出item、保存、添加下一个 + self.driver.find_element(By.XPATH, item_input_posCss).send_keys(items[i].split("->")[model]) + self.driver.find_element(By.XPATH, item_save_posCss).click() + + def _modify_item(self, data): + """ + 修改的item数据,type类型前后一样 + :param data: + :return: + """ + items: list = data["values"] + for i in range(len(items)): + if items[i].split("->")[-1] == "": #modify数据中->右侧为空(删除此数据) + element_item_del = dnsRecordsProfilePage_button_delItemByName_posXpath.replace("replaceName", items[i].split("->")[0]) + self.driver.find_element(By.XPATH, element_item_del).click() + continue + if items[i].split("->")[0] == "": #modify数据中->做侧为空(创建的数据为空,直接添加item) + self.driver.find_element(By.ID, dnsRecordsProfilePage_button_addItem_posId).click() #点击添加按钮 + # 添加item时,text()=空,xpath可以定位到 + item_input_posCss = dnsRecordsProfilePage_input_inputItemName_posXpath.replace("replaceName", "") + item_save_posCss = dnsRecordsProfilePage_button_saveItemByName_posXpath.replace("replaceName", items[i].split("->")[-1]) # ->修改中会此表标识 + # 输入item,保存 + self.driver.find_element(By.XPATH, item_input_posCss).send_keys(items[i].split("->")[-1]) + self.driver.find_element(By.XPATH, item_save_posCss).click() + continue + #直接编辑item项内容,在原有的item中编辑值 + item_edit_posCss = dnsRecordsProfilePage_button_editItemByName_posXpath.replace("replaceName", items[i].split("->")[0]) + item_input_posCss = dnsRecordsProfilePage_input_inputItemName_posXpath.replace("replaceName", items[i].split("->")[0]) + self.driver.find_element(By.XPATH, item_edit_posCss).click() + self.driver.find_element(By.XPATH, item_input_posCss).clear() + self.driver.find_element(By.XPATH, dnsRecordsProfilePage_input_inputItemName_posXpath.replace("replaceName", "")).send_keys(items[i].split("->")[-1]) + self.driver.find_element(By.XPATH, dnsRecordsProfilePage_button_saveItemByName_posXpath.replace("replaceName", items[i].split("->")[-1])).click() + + @screenshot_on_failure + def _search(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None,Type=None("A") + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_dnsRecords_selectLabel_posId, listPage_profileSearch_dnsRecords_dropDown_item_posXpath, + listPage_profileSearch_dnsRecords_input_itemContent_posXpath, listPage_profileSearch_dnsRecords_buttonSearch_posId, + listPage_profilTable_dnsRecords_tableTbody_posXpath, listPage_profilTable_dnsRecords_tableHeader_posXpath, + listPage_profileSearch_subProfiles_dropDown_typeItem_posXpath=listPage_profileSearch_dnsRecords_dropDown_typeItem_posXpath, **kwargs) + """ + #点击search查询框 + self.driver.find_element(By.ID, listPage_profileSearch_dnsRecords_selectLabel_posId).click() + #循环输入查询内容 + for key, value in kwargs.items(): + dropdown_item_posXpath = listPage_profileSearch_dnsRecords_dropDown_item_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, dropdown_item_posXpath).click() #点击下拉item + if key != "type": + input_item_posXpath = listPage_profileSearch_dnsRecords_input_itemContent_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, input_item_posXpath).send_keys(value.split("->")[0]) #输入查询值 + else: + dropdown_typeItem_posXpath = listPage_profileSearch_dnsRecords_dropDown_typeItem_posXpath.format(replaceName=value.split("->")[0]) + self.driver.find_element(By.XPATH, dropdown_typeItem_posXpath).click() #点击type的下拉item + #点击查询按钮 + element_search = self.driver.find_element(By.ID, listPage_profileSearch_dnsRecords_buttonSearch_posId) + self.driver.execute_script("arguments[0].click()", element_search) #强制点击 + element_tbody = self.driver.find_element(By.XPATH, listPage_profilTable_dnsRecords_tableTbody_posXpath) #找到所有的行,table的body + element_header = self.driver.find_element(By.XPATH, listPage_profilTable_dnsRecords_tableHeader_posXpath) #查询table的header + #获取table header的text、th.class + headers = element_header.find_elements(By.XPATH, "th") #table header + rows = element_tbody.find_elements(By.XPATH, "tr") #table body + map_header_className = {} #表头名称和th.class的映射,为了从表body中去对应列的值{"ID":"33"} + for th in headers: + header_content = th.text.strip() + classNames = th.get_attribute("class").split() + for c_name in classNames: + if "el-table" in c_name: + tableBodyRowClassName = c_name + if header_content and tableBodyRowClassName: + map_header_className[header_content] = tableBodyRowClassName + #从第一行查询的结果中,取出需要断言的值、name、Type、Values + first_row = rows[0] + """ + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + first_row_Type_class = map_header_className["Type"] + first_row_Type_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Type_class}')]//span").text.strip() + first_row_Values_class = map_header_className["Values"] + first_row_Values_contents = first_row.find_elements(By.XPATH, f"//td[contains(@class, '{first_row_Values_class}')]//span//span") + values_list = [] + for value in first_row_Values_contents: + values_list.append(value.text.strip()) + print(first_row_id_content, first_row_Name_content, first_row_Type_content, values_list) + #不同操作后的断言,创建后、修改后、无断言 + if require_assertion == 1: #直接创建后,使用的断言 + create_values_list = [i.split("->")[0] for i in data["values"] if i.split("->")[0] != ""] # 兼容modify中->的标识值 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.equal(first_row_Type_content, data["type"].split("->")[0], msg="所在行数{}".format(inspect.currentframe().f_lineno)) + for i in range(len(values_list)): + pytest_check.is_in(values_list[i], create_values_list, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + create_values_list = [i.split("->")[-1] for i in data["values"] if i.split("->")[-1] != ""] # modify中修改的数据->的右侧 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.equal(first_row_Type_content, data["type"].split("->")[-1], msg="所在行数{}".format(inspect.currentframe().f_lineno)) + for i in range(len(values_list)): + pytest_check.is_in(values_list[i], create_values_list, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_dnsRecords_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_dnsRecords_editButton_posId).click() + #根据修改数据,判断type类型 + self._select_type(data, model=-1) + if data["type"].split("->")[0].lower() != data["type"].split("->")[1].lower(): #创建和修改参数的type类型不一致 + self._ceate_item(data, model=-1) + else: + self._modify_item(data) + #修改description内容 + self.driver.find_element(By.ID, dnsRecordsProfilePage_textArea_Description_posId).clear() + self.driver.find_element(By.ID, dnsRecordsProfilePage_textArea_Description_posId).send_keys(data["description"].split("->")[-1]) + self.driver.find_element(By.CSS_SELECTOR, dnsRecordsProfilePage_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, dnsRecordsProfilePage_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, dnsRecordsProfilePage_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_dnsRecords_delButton_posId, listPage_dialogTips_dnsRecords_button_yes_posCss, + listPage_dialogTips_dnsRecords_button_no_posCss) + + create = _create + query = _search + modify = _modify + delete = _del diff --git a/common/ui_common/profiles/hijack_files.py b/common/ui_common/profiles/hijack_files.py new file mode 100644 index 00000000..82a031c5 --- /dev/null +++ b/common/ui_common/profiles/hijack_files.py @@ -0,0 +1,224 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect +import configparser +import os + + +class HijackFiles: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + + def hijackFiles_case(self, data: {}): + self._create(data) #创建 + self._query(data, require_assertion=1, Name=self.random_name) #创建后查询 + if data["model"].strip().lower() == "modify": #修改测试时,执行修改方法 + self._modify(data) + self._query(data, require_assertion=2, ID=self.first_row_ID_content) + self._del() + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到ssl_decryption_keyrings列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_hijackFiles_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #页面跳转 + self._goto_subProfilePage() + #创建 + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_hijackFiles_createButton_posId).click() + #在打开页面操作:输入name + self.driver.find_element(By.ID, hijackFiles_input_Name_posId).send_keys(self.random_name) + #页面其它选项操作 + self._operate_page(data, operation_type="create") + #点击OK + self.driver.find_element(By.CSS_SELECTOR, hijackFiles_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, hijackFiles_button_warningSaveYes_posCss).click() + return self.random_name + + def _operate_page(self, data: {}, operation_type="create"): + """ + 除name的其它选项操作,共创建、修改逻辑调用 + :param data: + :param operation_type: create modify。创建 修改时调用 + :return: + """ + if operation_type == "create": + data_index = 0 #新增数据索引 + else: + data_index = -1 #编辑数据索引 + no_modify = "不修改" + #解析输入data数据的数据 + #File文件上传操作 + file = self._get_value_from_data(data, key="file", data_index=data_index) #解析file文件名称 + if file != no_modify: #判断修改时不修改时跳过操作。 + file_abspath = self._abs_path(file) + #上传文件 + self.driver.find_element(By.XPATH, hijackFiles_input_fileUpLoad_posXpath).send_keys(file_abspath) + #download name 下载文件名称操作 + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="download_name", element_position=hijackFiles_switch_downLoadName_posXpath) + #file type 文件类型操作 + file_type = self._get_value_from_data(data, key="file_type", data_index=data_index) + if file_type != no_modify: #修改时不用修改数据直接跳过 + #点击type添加按钮 + self.driver.find_element(By.XPATH, hijackFiles_button_fileType_posXpath).click() + element_type_replace_name = {'gif': 'image/gif', 'jpeg': 'image/jpeg', 'png': 'image/png', 'svg+xml': 'image/svg+xml', + 'exe': 'application/x-msdos-program', 'apk': 'application/vnd.android.package-archive', 'html': 'text/html'} + if file_type not in element_type_replace_name.keys(): + raise f"文件类型错误。用例数据类型为:{file_type}, 可选择文件类型为:{list(element_type_replace_name.keys())}" + element_tablist_type = self.driver.find_element(By.XPATH, hijackFiles_tablist_fileType_posXpath.format(replaceName=element_type_replace_name[file_type])) + self.driver.execute_script("arguments[0].click()", element_tablist_type) # 强制点击 + + def _abs_path(self, file_name): + # 以下是要读取数据的名称 + conf = configparser.ConfigParser() + loginout_parse_dir = os.path.join(self.workdir, "config", "ui_conf", "importfile.ini") + conf.read(loginout_parse_dir, encoding="utf-8") + testdata = conf.get("profiles", "testdata") + ui_file = conf.get("profiles", "ui_file") + profiles = conf.get("profiles", "profiles") + hijack_files = conf.get("profiles", "hijack_files") + import_file_abs = os.path.join(self.workdir, testdata, ui_file, profiles, hijack_files, file_name) + import_file_abs = os.path.abspath(import_file_abs) + return import_file_abs + + def _get_value_from_data(self, data: {}, key="", data_index=0): + """ + 从data数据中,根据key提取值 + :param data: + :param key: + :param data_index: 0 -1 + :return: + """ + try: + switch_value: str = data[key].split("->")[data_index].strip().lower() #用例数据 + except Exception as e: + print(e) + return switch_value + + def _operate_switch(self, data: {}, data_index=0, no_modify="不修改", switch_name="", element_position=""): + """ + 页面中,开关状态操作,。 + :param data: + :param data_index: 0 -1来自上层 + :param no_modify:"不修改" 来自上次调用 + :param operation_type: create modify两个状态, + :param switch_name: 数据中开关名称 + :param elementPosition: 开关的定位 + :return: + """ + #解析输入data数据的数据 + switch_value: str = self._get_value_from_data(data, key=switch_name, data_index=data_index) #提取数据 Mirror Server Response + if switch_value != no_modify: #编辑时,有不修改则不用执行 + #先获取当前页面中开关状态 include_root_current_class : class="el-switch is-checked" 有is-checked当前状态为开,没有is-chedked当前状态为关 + swith_current_class = self.driver.find_element(By.XPATH, element_position).get_attribute("class") + if ("mirror" in switch_value) and ("server" in switch_value) and ("response" in switch_value): #数据中为Mirror Server Response,使用默认名称,不修改 + if "is-checked" in swith_current_class: #页面当前为开,不用点击开关 + pass + else: #页面当前为关,需要点击开关 + self.driver.find_element(By.XPATH, f"{element_position}/span[2]").click() + else: ##数据中为其它名称,则需要修改默认名称 + if "is-checked" in swith_current_class: #页面当前为开,需要先关闭开关,在输入值 + self.driver.find_element(By.XPATH, f"{element_position}/span[2]").click() + #输入修改名称值 + self.driver.find_element(By.XPATH, hijackFiles_input_downLoadName_posXpath).clear() + self.driver.find_element(By.XPATH, hijackFiles_input_downLoadName_posXpath).send_keys(switch_value) + + + @screenshot_on_failure + def _query(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None, + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_hijackFiles_selectLabel_posId, listPage_profileSearch_hijackFiles_dropDown_item_posXpath, + listPage_profileSearch_hijackFiles_input_itemContent_posXpath, listPage_profileSearch_hijackFiles_buttonSearch_posId, + listPage_profilTable_hijackFiles_tableTbody_posXpath, listPage_profilTable_hijackFiles_tableHeader_posXpath, **kwargs) + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + #print(map_header_className) + # 需要提取ID Name、Type 信息 + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + first_row_Type_class = map_header_className["Type"] + first_row_Type_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Type_class}')]//span").text + + print(first_row_id_content, first_row_Name_content, first_row_Type_content) + element_type_replace_name = {'gif': 'image/gif', 'jpeg': 'image/jpeg', 'png': 'image/png', 'svg+xml': 'image/svg+xml', + 'exe': 'application/x-msdos-program', 'apk': 'application/vnd.android.package-archive', 'html': 'text/html'} + #不同操作后的断言,创建后、修改后、无断言 + if require_assertion == 1: #直接创建后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + file_type = self._get_value_from_data(data, key="file_type", data_index=0) + pytest_check.equal(first_row_Type_content, element_type_replace_name[file_type], msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + file_type = self._get_value_from_data(data, key="file_type", data_index=-1) + if file_type != "不修改": + pytest_check.equal(first_row_Type_content, element_type_replace_name[file_type], msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_hijackFiles_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_hijackFiles_editButton_posId).click() + #解析修改数据 + self._operate_page(data, operation_type="edit") + #点击ok + self.driver.find_element(By.CSS_SELECTOR, hijackFiles_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, hijackFiles_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, hijackFiles_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_hijackFiles_delButton_posId, listPage_dialogTips_hijackFiles_button_yes_posCss, + listPage_dialogTips_hijackFiles_button_no_posCss) + + create = _create + query = _query + modify = _modify + delete = _del
\ No newline at end of file diff --git a/common/ui_common/profiles/profiles_public_operations.py b/common/ui_common/profiles/profiles_public_operations.py new file mode 100644 index 00000000..914f418d --- /dev/null +++ b/common/ui_common/profiles/profiles_public_operations.py @@ -0,0 +1,78 @@ +import time + +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +import random + + +class ProfilesPublicOperations: + def __init__(self, driver): + self.driver = driver + + def query(self, mainPage_profileSearch_selectLabel_posId, listPage_profileSearch_subProfiles_dropDown_item_posXpath, + listPage_profileSearch_subProfiles_input_itemContent_posXpath, mainPage_profileSearch_buttonSearch_posId, + listPage_profilTable_subProfiles_tableTbody_posXpath, listPage_profilTable_subProfiles_tableHeader_posXpath, + listPage_profileSearch_subProfiles_dropDown_typeItem_posXpath="", **kwargs): + """ + profiles模块中从点击查询到查询到结果使用方法,并返回第一行数据和表头、class的字典 + :param mainPage_profileSearch_selectLabel_posId: 查询框id + :param listPage_profileSearch_subProfiles_dropDown_item_posXpath: 下拉列表item的xpath + :param listPage_profileSearch_subProfiles_input_itemContent_posXpath: 选中item后,输入input的xpath + :param mainPage_profileSearch_buttonSearch_posId: 查询按钮id + :param listPage_profilTable_subProfiles_tableTbody_posXpath: 列表页body的部分xpath + :param listPage_profilTable_subProfiles_tableHeader_posXpath: 列表页header的部分xpath + :param listPage_profileSearch_subProfiles_dropDown_typeItem_posXpath: 如果有下拉列表item的枚举选项定位,需要增补 + :param kwargs: 需要查询的内容,来自调用函数 + :return: [first_row, map_header_className] + """ + #点击search查询框 + self.driver.find_element(By.ID, mainPage_profileSearch_selectLabel_posId).click() + #循环输入查询内容 + for key, value in kwargs.items(): + dropdown_item_posXpath = listPage_profileSearch_subProfiles_dropDown_item_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, dropdown_item_posXpath).click() #点击下拉item + if key != "type": + input_item_posXpath = listPage_profileSearch_subProfiles_input_itemContent_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, input_item_posXpath).send_keys(value.strip()) #输入查询值 + else: + dropdown_typeItem_posXpath = listPage_profileSearch_subProfiles_dropDown_typeItem_posXpath.format(replaceName=value.split("->")[0]) + self.driver.find_element(By.XPATH, dropdown_typeItem_posXpath).click() #点击type的下拉item + #点击查询按钮 + element_search = self.driver.find_element(By.ID, mainPage_profileSearch_buttonSearch_posId) + self.driver.execute_script("arguments[0].click()", element_search) #强制点击 + element_tbody = self.driver.find_element(By.XPATH, listPage_profilTable_subProfiles_tableTbody_posXpath) #找到所有的行,table的body + element_header = self.driver.find_element(By.XPATH, listPage_profilTable_subProfiles_tableHeader_posXpath) #查询table的header + #获取table header的text、th.class + headers = element_header.find_elements(By.XPATH, "th") #table header + rows = element_tbody.find_elements(By.XPATH, "tr") #table body + map_header_className = {} #表头名称和th.class的映射,为了从表body中取对应列的值{"ID":"33"} + for th in headers: + header_content = th.text.strip() + classNames = th.get_attribute("class").split() + for c_name in classNames: + if "el-table" in c_name: + tableBodyRowClassName = c_name + if header_content and tableBodyRowClassName: + map_header_className[header_content] = tableBodyRowClassName + #从第一行查询的结果中,取出需要断言的值、name + first_row = rows[0] + return [first_row, map_header_className] + + def delete(self, listPage_profile_subProfiles_delButton_posId, listPage_dialogTips_subProfiles_button_yes_posCss, + listPage_dialogTips_subProfiles_button_no_posCss): + """ + 直接删除函数, + :param listPage_profile_subProfiles_delButton_posId: 删除按钮id + :param listPage_dialogTips_subProfiles_button_yes_posCss: 提示删除框中yes定位css + :param listPage_dialogTips_subProfiles_button_no_posCss: 提示删除框中no定位css + :return: + """ + self.driver.find_element(By.ID, listPage_profile_subProfiles_delButton_posId).click() #点击删除按钮 + random_yes_or_no = random.randint(0, 1) + if random_yes_or_no == 0: #点击yes,删除 + self.driver.find_element(By.CSS_SELECTOR, listPage_dialogTips_subProfiles_button_yes_posCss).click() #直接删除 + else: + self.driver.find_element(By.CSS_SELECTOR, listPage_dialogTips_subProfiles_button_no_posCss).click() #先取消,再删除 + self.driver.find_element(By.ID, listPage_profile_subProfiles_delButton_posId).click() # 点击删除按钮 + self.driver.find_element(By.CSS_SELECTOR, listPage_dialogTips_subProfiles_button_yes_posCss).click() + time.sleep(0.5)
\ No newline at end of file diff --git a/common/ui_common/profiles/response_pages.py b/common/ui_common/profiles/response_pages.py new file mode 100644 index 00000000..2492def9 --- /dev/null +++ b/common/ui_common/profiles/response_pages.py @@ -0,0 +1,141 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect +import configparser +import os + + +class ResponsePages: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + + def response_page_case(self, data: {}): + self._create(data) #创建 + self._query(data, require_assertion=1, Name=self.random_name) #创建后查询 + if data["model"].strip().lower() == "modify": #修改测试时,执行修改方法 + self._modify(data) + self._query(data, require_assertion=2, ID=self.first_row_ID_content) + self._del() + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到responsePages列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_responsePages_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #页面跳转 + self._goto_subProfilePage() + #创建responsePages + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_responsePages_createButton_posId).click() + #在create resposne page页面操作 + self.driver.find_element(By.ID, responsePage_input_Name_posId).send_keys(self.random_name) + #上传文件 + create_file_ = data["file"].split("->")[0] #提取上传文件绝对路径 + create_file_abs = self._abs_path(create_file_) + self.driver.find_element(By.XPATH, responsePage_input_file_posXpath).send_keys(create_file_abs) + #点击OK + self.driver.find_element(By.CSS_SELECTOR, responsePage_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, responsePage_button_warningSaveYes_posCss).click() + return self.random_name + + def _abs_path(self, file_name): + # 以下是要读取数据的名称 + conf = configparser.ConfigParser() + loginout_parse_dir = os.path.join(self.workdir, "config", "ui_conf", "importfile.ini") + conf.read(loginout_parse_dir, encoding="utf-8") + testdata = conf.get("profiles", "testdata") + ui_file = conf.get("profiles", "ui_file") + profiles = conf.get("profiles", "profiles") + response_pages = conf.get("profiles", "response_pages") + import_file_abs = os.path.join(self.workdir, testdata, ui_file, profiles, response_pages, file_name) + import_file_abs = os.path.abspath(import_file_abs) + return import_file_abs + + @screenshot_on_failure + def _query(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None, + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_responsePages_selectLabel_posId, listPage_profileSearch_responsePages_dropDown_item_posXpath, + listPage_profileSearch_responsePages_input_itemContent_posXpath, listPage_profileSearch_responsePages_buttonSearch_posId, + listPage_profilTable_responsePages_tableTbody_posXpath, listPage_profilTable_responsePages_tableHeader_posXpath, **kwargs) + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + print(first_row_id_content, first_row_Name_content) + #不同操作后的断言,创建后、修改后、无断言 + + if require_assertion == 1: #直接创建后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_responsePages_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_responsePages_editButton_posId).click() + #根据修改数据,修改上次文件 + modify_file = data["file"].split("->")[-1] #提取上传文件绝对路径 + modify_file_abs = self._abs_path(modify_file) + self.driver.find_element(By.XPATH, responsePage_input_file_posXpath).send_keys(modify_file_abs) + #点击ok + self.driver.find_element(By.CSS_SELECTOR, responsePage_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, responsePage_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, responsePage_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_responsePages_delButton_posId, listPage_dialogTips_responsePages_button_yes_posCss, + listPage_dialogTips_responsePages_button_no_posCss) + + create = _create + query = _query + modify = _modify + delete = _del
\ No newline at end of file diff --git a/common/ui_common/profiles/shaping_profiles.py b/common/ui_common/profiles/shaping_profiles.py new file mode 100644 index 00000000..56a4d055 --- /dev/null +++ b/common/ui_common/profiles/shaping_profiles.py @@ -0,0 +1,248 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect + + +class ShapingProfiles: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + + def shaping_profiles_case(self, data: {}): + """ + 测试用例调用函数, + :param demo_fixture: 传入driver + :param data: 测试数据。 + + :return: + """ + #self.driver = demo_fixture + self._create(data) #创建 + self._query(data, require_assertion=1, Name=self.random_name) #创建后查询 + if data["model"].strip().lower() == "modify": #修改测试时,执行修改方法 + self._modify(data) + self._query(data, require_assertion=2, ID=self.first_row_ID_content) # 修改后查询 + self._del() #删除数据 + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到shapingProfiles列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_shapingProfiles_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #页面跳转 + self._goto_subProfilePage() + #创建shapingProfiles + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_shapingProfiles_createButton_posId).click() + #在create dns shapingProfiles操作 + self.driver.find_element(By.ID, shapingProfilePage_input_Name_posId).send_keys(self.random_name) #输入名字 + #判断点击哪种类型 + self._select_type(data) + self._select_limits(data, model=0) + #点击ok + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_warningSaveYes_posCss).click() + return self.random_name + + @screenshot_on_failure + def _a(self, data: {}): + print(__name__) + 1 == 1 + return 444 + + @screenshot_on_failure + def _select_type(self, data: {}): + """ + 选择type类型点击 + :param data: + :return: + """ + type: str = data["type"].strip().lower() + argument: str = data["argument"].strip().lower() + if type == "generic": + element_type_pos = shapingProfilePage_radioButton_generic_posXpath + elif type == "fair share": + element_type_pos = shapingProfilePage_radioButton_fairShare_posXpath + if argument == "Max Min Host Fairness".lower(): + element_argument_pos = shapingProfilePage_radioButton_maxMinHostFairness_posXpath + else: + raise ValueError(f"用例参数argument:{argument}") + else: + element_type_pos = shapingProfilePage_radioButton_splitBy_posXpath + if argument == "Local Host".lower(): + element_argument_pos = shapingProfilePage_radioButton_localHost_posXpath + else: + raise ValueError(f"用例参数argument:{argument}") + #点击type类型 + self.driver.find_element(By.XPATH, element_type_pos).click() + #判断是否点击Argument + if type != "generic": + self.driver.find_element(By.XPATH, element_argument_pos).click() + + @screenshot_on_failure + def _select_limits(self, data: {}, model=0): + """ + 输入limits + :param data: + :param model: =0表示创建时调用。-1表示修改时调用 + :return: + """ + unitItem = data["unit"].strip().split("->")[model] + element_dropDown_unitItem = shapingProfilePage_drowDown_unitItem_posXpath.format(replaceName=unitItem) + #点击Unit并选择单位 + self.driver.find_element(By.ID, shapingProfilePage_inputSelect_unit_posId).click() + self.driver.find_element(By.XPATH, element_dropDown_unitItem).click() + #输入incoming、outgoing + input_incoming = data["incoming"].strip().split("->")[model] + input_outgoing = data["outgoing"].strip().split("->")[model] + self.driver.find_element(By.ID, shapingProfilePage_input_incoming_posId).clear() + self.driver.find_element(By.ID, shapingProfilePage_input_incoming_posId).send_keys(input_incoming) + self.driver.find_element(By.ID, shapingProfilePage_input_outgoing_posId).clear() + self.driver.find_element(By.ID, shapingProfilePage_input_outgoing_posId).send_keys(input_outgoing) + + @screenshot_on_failure + def _query(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None, + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_shapingProfiles_selectLabel_posId, listPage_profileSearch_shapingProfiles_dropDown_item_posXpath, + listPage_profileSearch_shapingProfiles_input_itemContent_posXpath, listPage_profileSearch_shapingProfiles_buttonSearch_posId, + listPage_profilTable_shapingProfiles_tableTbody_posXpath, listPage_profilTable_shapingProfiles_tableHeader_posXpath, **kwargs) + """ + #点击search查询框 + self.driver.find_element(By.ID, listPage_profileSearch_shapingProfiles_selectLabel_posId).click() + #循环输入查询内容 + for key, value in kwargs.items(): + dropdown_item_posXpath = listPage_profileSearch_shapingProfiles_dropDown_item_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, dropdown_item_posXpath).click() #点击下拉item + if key != "type": + input_item_posXpath = listPage_profileSearch_shapingProfiles_input_itemContent_posXpath.format(replaceName=key) + self.driver.find_element(By.XPATH, input_item_posXpath).send_keys(value.strip()) #输入查询值 + else: + pass + # dropdown_typeItem_posXpath = listPage_profileSearch_dnsRecords_dropDown_typeItem_posXpath.format(replaceName=value.split("->")[0]) + # self.driver.find_element(By.XPATH, dropdown_typeItem_posXpath).click() #点击type的下拉item + #点击查询按钮 + element_search = self.driver.find_element(By.ID, listPage_profileSearch_shapingProfiles_buttonSearch_posId) + self.driver.execute_script("arguments[0].click()", element_search) #强制点击 + element_tbody = self.driver.find_element(By.XPATH, listPage_profilTable_shapingProfiles_tableTbody_posXpath) #找到所有的行,table的body + element_header = self.driver.find_element(By.XPATH, listPage_profilTable_shapingProfiles_tableHeader_posXpath) #查询table的header + #获取table header的text、th.class + headers = element_header.find_elements(By.XPATH, "th") #table header + rows = element_tbody.find_elements(By.XPATH, "tr") #table body + map_header_className = {} #表头名称和th.class的映射,为了从表body中取对应列的值{"ID":"33"} + for th in headers: + header_content = th.text.strip() + classNames = th.get_attribute("class").split() + for c_name in classNames: + if "el-table" in c_name: + tableBodyRowClassName = c_name + if header_content and tableBodyRowClassName: + map_header_className[header_content] = tableBodyRowClassName + #从第一行查询的结果中,取出需要断言的值、name、Type、Values + first_row = rows[0] + """ + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + first_row_Type_class = map_header_className["Type"] + first_row_Type_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Type_class}')]//span").text.strip() + first_row_IncomingOutgoing_class = map_header_className["Incoming/Outgoing"] + first_row_IncomingOutgoing_contents = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_IncomingOutgoing_class}')]//span").text.strip() + + print(first_row_id_content, first_row_Name_content, first_row_Type_content, first_row_IncomingOutgoing_contents) + #不同操作后的断言,创建后、修改后、无断言 + if require_assertion == 1: #直接创建后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.equal(first_row_Type_content, data["type"].strip(), msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["outgoing"].strip().split("->")[0] == "0": #为0时,直接断言Unlimit + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["outgoing"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["incoming"].strip().split("->")[0] == "0": + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["incoming"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[0], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.equal(first_row_Type_content, data["type"].split("->")[-1], msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["outgoing"].strip().split("->")[-1] == "0": #为0时,直接断言Unlimit + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["outgoing"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if data["incoming"].strip().split("->")[-1] == "0": + pytest_check.is_in("Unlimit", first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: + pytest_check.is_in(data["incoming"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + pytest_check.is_in(data["unit"].strip().split("->")[-1], first_row_IncomingOutgoing_contents, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_shapingProfiles_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_shapingProfiles_editButton_posId).click() + #根据修改数据,重新输入limits + self._select_limits(data, model=-1) + #点击ok + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, shapingProfilePage_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_shapingProfiles_delButton_posId, listPage_dialogTips_shapingProfiles_button_yes_posCss, + listPage_dialogTips_shapingProfiles_button_no_posCss) + + create = _create + query = _query + modify = _modify + delete = _del diff --git a/common/ui_common/profiles/ssl_decryption_keyrings.py b/common/ui_common/profiles/ssl_decryption_keyrings.py new file mode 100644 index 00000000..5e81b7a4 --- /dev/null +++ b/common/ui_common/profiles/ssl_decryption_keyrings.py @@ -0,0 +1,219 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect +import configparser +import os + + +class SSLDecryptionKeyrings: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + + def sslDecryptionKeyrings_case(self, data: {}): + self._create(data) #创建 + self._query(data, require_assertion=1, Name=self.random_name) #创建后查询 + if data["model"].strip().lower() == "modify": #修改测试时,执行修改方法 + self._modify(data) + self._query(data, require_assertion=2, ID=self.first_row_ID_content) + self._del() + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到ssl_decryption_keyrings列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_sslDecryptionKeyrings_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #页面跳转 + self._goto_subProfilePage() + #创建 + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_sslDecryptionKeyrings_createButton_posId).click() + #在create 创建页面操作 + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_Name_posId).send_keys(self.random_name) + #页面其它项操作函数 + self._operate_page(data, operation_type="create") + #点击OK + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionKeyrings_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionKeyrings_button_warningSaveYes_posCss).click() + return self.random_name + + def _operate_page(self, data: {}, operation_type="create"): + """ + 不包含name输入的其它操作,可以兼容新增、编辑使用 + :param data: + :opration_type:可选择值为create edit + :return: + """ + if operation_type == "create": + data_index = 0 #新增数据索引 + else: + data_index = -1 #编辑数据索引 + no_modify = "不修改" + #解析输入data数据、证书、私钥操作 + cert_name = data["certificate"].split("->")[data_index].strip() #"test_root_cert_catest.cer->" + if cert_name != no_modify: #需改数据时,需要执行 + cert_abspath = self._abs_path(cert_name) + self.driver.find_element(By.XPATH, sslDecryptionKeyrings_input_certificateFile_posXpath).send_keys(cert_abspath) #上传证书 + #私钥 + if data["private_key"].split("->")[data_index].strip() != no_modify: #修改私钥时执行 + if data["private_key"].split("->")[data_index].strip().startswith("PKF-"): #如果已PKF-开始,则是私钥 "PKF-test_root_key_catest.key->" + key_name = data["private_key"].split("->")[data_index].strip().lstrip("PKF-") + key_abspath = self._abs_path(key_name) + self.driver.find_element(By.ID, sslDecryptionKeyrings_radio_privateKeyFile_posId).click() + self.driver.find_element(By.XPATH, sslDecryptionKeyrings_input_privateKeyFile_posXpath).send_keys(key_abspath) #上传私钥 + else: #私钥是HSM形式, 例如:HSM-345 + slod_id = data["private_key"].split("->")[data_index].strip().lstrip("HSM-") + self.driver.find_element(By.ID, sslDecryptionKeyrings_radio_hsm_posId).click() + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_slotIdHSM_posId).send_keys(slod_id) #输入slot id + #证书时间选择 + reissue_expiry_hours: str = data["reissue_expiry_hours"].split("->")[data_index].strip() + if reissue_expiry_hours != no_modify: + if reissue_expiry_hours.startswith("MSC"): #'MSC' + self.driver.find_element(By.ID, sslDecryptionKeyrings_radio_mirrorServerCertificate_poId).click() + else: + self.driver.find_element(By.ID, sslDecryptionKeyrings_radio_customized_poId).click() + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_customized_poId).clear() + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_customized_poId).send_keys(reissue_expiry_hours.lstrip("C-")) #‘C-234' + #证书类型操作 + type = data["type"].split("->")[data_index].strip() + if type != no_modify: + type_index_dict = {"Root-Certificate": 0, "Intermediate-Certificate": 1, "End-entity": 2} + if type not in type_index_dict.keys(): + raise f"输入的证书类型参数错误。输出的参数:type={type}。可选择的输入参数值为:{list(type_index_dict.keys())}" + element_pos_type_droplist_item = sslDecryptionKeyrings_dropdown_certificateTypeSelect_poId.format(replaceIndex=type_index_dict[type]) + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_certificateType_poId).click() #点击类型列表选择框 + self.driver.find_element(By.ID, element_pos_type_droplist_item).click() #点击列表下拉参数具体选项 + pka = data["public_key_algorithm"].split("->")[data_index].strip() + #公钥算法 + if pka != no_modify: + pka_idex_dict = {"RSA-1024": 0, "RSA-2048": 1, "SECP-256r1": 2, "SECP-384r1": 3} #下拉列表定位索引 + if pka not in pka_idex_dict.keys(): + raise f"输入的公钥算法错误。输出的参数:pka={pka}。可选择的输入参数值为:{list(pka_idex_dict.keys())}" + element_pos_pka_droplist_item = sslDecryptionKeyrings_dropdown_publickKeyAlgorithmSelect_poId.format(replaceIndex=pka_idex_dict[pka]) + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_publickKeyAlgorithm_poId).click() + self.driver.find_element(By.ID, element_pos_pka_droplist_item).click() #点击公钥算法下拉选项定位 + #输入Certificate Revocation List + if data["certificate_revocation_list"].split("->")[data_index].strip() != no_modify: + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_certificateRevocationList_poId).clear() + self.driver.find_element(By.ID, sslDecryptionKeyrings_input_certificateRevocationList_poId).send_keys(data["certificate_revocation_list"].split("->")[data_index].strip()) + include_root = data["include_root"].split("->")[data_index].strip().lower() #用例数据 + if include_root != no_modify: + #先获取页面中包含根证书当前状态 include_root_current_class : class="el-switch is-checked" 有is-checked当前状态为开,没有is-chedked当前状态为关 + include_root_current_class = self.driver.find_element(By.XPATH, sslDecryptionKeyrings_input_includeRoot_poXpath).find_element(By.XPATH, "parent::*").get_attribute("class") + if "on" == include_root: #开 + if "is-checked" in include_root_current_class: #页面当前为开,不用点击开关 + pass + else: #页面当前为关,需要点击开关 + self.driver.find_element(By.XPATH, sslDecryptionKeyrings_input_includeRoot_poXpath).click() + self.include_root_statue = "on" #修改时会使用判断 + else: #用例输入为关 + if "is-checked" in include_root_current_class: #页面当前为开,需要点击开关 + self.driver.find_element(By.XPATH, sslDecryptionKeyrings_input_includeRoot_poXpath).click() + self.include_root_statue = "on" # 修改时会使用判断 + else: #页面当前为关,不用点击开关 + pass + + def _abs_path(self, file_name): + # 以下是要读取数据的名称 + conf = configparser.ConfigParser() + loginout_parse_dir = os.path.join(self.workdir, "config", "ui_conf", "importfile.ini") + conf.read(loginout_parse_dir, encoding="utf-8") + testdata = conf.get("profiles", "testdata") + ui_file = conf.get("profiles", "ui_file") + profiles = conf.get("profiles", "profiles") + ssl_decryption_keyrings = conf.get("profiles", "ssl_decryption_keyrings") + import_file_abs = os.path.join(self.workdir, testdata, ui_file, profiles, ssl_decryption_keyrings, file_name) + import_file_abs = os.path.abspath(import_file_abs) + return import_file_abs + + @screenshot_on_failure + def _query(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None, + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_sslDecryptionKeyrings_selectLabel_posId, listPage_profileSearch_sslDecryptionKeyrings_dropDown_item_posXpath, + listPage_profileSearch_sslDecryptionKeyrings_input_itemContent_posXpath, listPage_profileSearch_sslDecryptionKeyrings_buttonSearch_posId, + listPage_profilTable_sslDecryptionKeyrings_tableTbody_posXpath, listPage_profilTable_sslDecryptionKeyrings_tableHeader_posXpath, **kwargs) + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + # 需要提取id、name、type、crl信息 + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + first_row_Type_class = map_header_className["Type"] + first_row_Type_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Type_class}')]//span").text.strip() + first_row_CRL_class = map_header_className["CRL"] + first_row_CRL_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_CRL_class}')]//span").text.strip() + + print(first_row_id_content, first_row_Name_content, first_row_Type_content, first_row_CRL_content) + #不同操作后的断言,创建后、修改后、无断言 + if require_assertion == 1: #直接创建后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_trafficMirroringProfiles_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_sslDecryptionKeyrings_editButton_posId).click() + #解析修改数据 + self._operate_page(data, operation_type="edit") + + #点击ok + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionKeyrings_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, sslDecryptionKeyrings_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionKeyrings_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_sslDecryptionKeyrings_delButton_posId, listPage_dialogTips_sslDecryptionKeyrings_button_yes_posCss, + listPage_dialogTips_sslDecryptionKeyrings_button_no_posCss) + + create = _create + query = _query + modify = _modify + delete = _del
\ No newline at end of file diff --git a/common/ui_common/profiles/ssl_decryption_profiles.py b/common/ui_common/profiles/ssl_decryption_profiles.py new file mode 100644 index 00000000..3acb1160 --- /dev/null +++ b/common/ui_common/profiles/ssl_decryption_profiles.py @@ -0,0 +1,252 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect + + +class SSLDecryptionProfiles: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + + def sslDecryptionProfiles_case(self, data: {}): + self._create(data) #创建 + self._query(data, require_assertion=1, Name=self.random_name) #创建后查询 + if data["model"].strip().lower() == "modify": #修改测试时,执行修改方法 + self._modify(data) + self._query(data, require_assertion=2, ID=self.first_row_ID_content) + self._del() + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到ssl_decryption_keyrings列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_sslDecryptionProfiles_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #页面跳转 + self._goto_subProfilePage() + #创建 + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_sslDecryptionProfiles_createButton_posId).click() + #在create 创建页面操作 + self.driver.find_element(By.ID, sslDecryptionProfiles_input_Name_posId).send_keys(self.random_name) + #页面其它选项操作 + self._operate_page(data, operation_type="create") + #点击OK + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionProfiles_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionProfiles_button_warningSaveYes_posCss).click() + return self.random_name + + def _operate_page(self, data: {}, operation_type="create"): + """""" + if operation_type == "create": + data_index = 0 #新增数据索引 + else: + data_index = -1 #编辑数据索引 + no_modify = "不修改" + #解析输入data数据的数据 + #页面开关操作 common name,issuer,selfSigned,expiryDate + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="common_name", element_position=sslDecryptionProfiles_switch_commonName_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="issuer", element_position=sslDecryptionProfiles_switch_issuer_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="self_signed", element_position=sslDecryptionProfiles_switch_selfSigned_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="expiry_date", element_position=sslDecryptionProfiles_switch_expiryDate_posXpath) + #Fail Action操作 + fail_action = self._get_value_from_data(data, key="fail_action", data_index=data_index) #用例数据提取 Pass-through Fail-close + if fail_action != no_modify: + if "pass-through" == fail_action: #点击pass through + self.driver.find_element(By.XPATH, sslDecryptionProfiles_radio_passThrough_posXpath).click() + else: #点击fail close + self.driver.find_element(By.XPATH, sslDecryptionProfiles_radio_failClose_posXpath).click() + #页面开关操作ev_certificate certificate_transparency mutual_authentication protocol_errors certificate_pinning certificate_not_installed allow_HTTP2 mirror_client_versions + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="ev_certificate", element_position=sslDecryptionProfiles_switch_evCert_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="certificate_transparency", element_position=sslDecryptionProfiles_switch_certificateTransparency_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="mutual_authentication", element_position=sslDecryptionProfiles_switch_mutualAuthentication_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="protocol_errors", element_position=sslDecryptionProfiles_switch_onProtocolErrors_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="certificate_pinning", element_position=sslDecryptionProfiles_switch_certificatePinning_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="certificate_not_installed", element_position=sslDecryptionProfiles_switch_certificateNotInstalled_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="mirror_client_versions", element_position=sslDecryptionProfiles_switch_mirrorClientVersions_posXpath) + self._operate_switch(data, data_index=data_index, no_modify=no_modify, switch_name="allow_HTTP2", element_position=sslDecryptionProfiles_switch_allowHTTP2_posXpath) + #Min Max version操作 + mirror_client_versions = self._get_value_from_data(data, key="mirror_client_versions", data_index=data_index) #提取数据 + mirror_client_versions_class = self.driver.find_element(By.XPATH, sslDecryptionProfiles_switch_mirrorClientVersions_posXpath).get_attribute("class") #该开关当前属性状态 + min_version = self._get_value_from_data(data, key="min_client_version", data_index=data_index) + max_version = self._get_value_from_data(data, key="max_client_version", data_index=data_index) + if "is-checked" not in mirror_client_versions_class: #只有 当前状态为关时,才可以操作版本大小。 + version_index_list = ['sslv3.0', 'tlsv1.0', 'tlsv1.1', 'tlsv1.2', 'tlsv1.3'] + if min_version != no_modify: #编辑时不修改,则不用操作 + self.driver.find_element(By.XPATH, sslDecryptionProfiles_input_minVersion_posXpath).click() + element_pos_min_drop_down_item = sslDecryptionProfiles_dropDown_minVersion_posXpath.format(replaceIndex=version_index_list.index(min_version)) #组定位 + self.driver.find_element(By.XPATH, element_pos_min_drop_down_item).click() + if max_version != no_modify: #编辑时不修改,则不用操作 + self.driver.find_element(By.XPATH, sslDecryptionProfiles_input_maxVersion_posXpath).click() + element_pos_max_drop_down_item = sslDecryptionProfiles_dropDown_maxVersion_posXpath.format(replaceIndex=version_index_list.index(max_version)) #组定位 + self.driver.find_element(By.XPATH, element_pos_max_drop_down_item).click() + + def _get_value_from_data(self, data: {}, key="", data_index=0): + """ + 从data数据中,根据key提取值 + :param data: + :param key: + :param data_index: 0 -1 + :return: + """ + try: + switch_value: str = data[key].split("->")[data_index].strip().lower() #用例数据 + except Exception as e: + print(e) + return switch_value + + def _operate_switch(self, data: {}, data_index=0, no_modify="不修改", switch_name="", element_position=""): + """ + 页面中,开关状态操作。 + :param data: + :param data_index: 0 -1来自上层 + :param no_modify:"不修改" 来自上次调用 + :param operation_type: create modify两个状态, + :param switch_name: 数据中开关名称 + :param elementPosition: 开关的定位 + :return: + """ + #解析输入data数据的数据 + switch_value: str = self._get_value_from_data(data, key=switch_name, data_index=data_index) #提取数据 + if switch_value != no_modify: #编辑时,有不修改则不用执行 + #先获取当前页面中开关状态 include_root_current_class : class="el-switch is-checked" 有is-checked当前状态为开,没有is-chedked当前状态为关 + swith_current_class = self.driver.find_element(By.XPATH, element_position).get_attribute("class") + if "on" == switch_value: #数据中为开 + if "is-checked" in swith_current_class: #页面当前为开,不用点击开关 + pass + else: #页面当前为关,需要点击开关 + self.driver.find_element(By.XPATH, element_position).click() + else: #用例输入为关 + if "is-checked" in swith_current_class: #页面当前为开,需要点击开关 + self.driver.find_element(By.XPATH, element_position).click() + else: #页面当前为关,不用点击开关 + pass + + @screenshot_on_failure + def _query(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None, + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_sslDecryptionProfiles_selectLabel_posId, listPage_profileSearch_sslDecryptionProfiles_dropDown_item_posXpath, + listPage_profileSearch_sslDecryptionProfiles_input_itemContent_posXpath, listPage_profileSearch_sslDecryptionProfiles_buttonSearch_posId, + listPage_profilTable_sslDecryptionProfiles_tableTbody_posXpath, listPage_profilTable_sslDecryptionProfiles_tableHeader_posXpath, **kwargs) + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + #print(map_header_className) + # 需要提取id、name、type、Certificate Checks、Fail Action、Dynamic Bypass、Allow HTTP/2信息 + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + first_row_Certificate_Checks_class = map_header_className["Certificate Checks"] + first_row_Certificate_Checks_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Certificate_Checks_class}')]//span").text + first_row_Fail_Action_class = map_header_className["Fail Action"] + first_row_Fail_Action_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Fail_Action_class}')]//span").text + first_row_Dynamic_Bypass_class = map_header_className["Dynamic Bypass"] + first_row_Dynamic_Bypass_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Dynamic_Bypass_class}')]//span").text + first_row_Allow_HTTP2_class = map_header_className["Allow HTTP/2"] + first_row_Allow_HTTP2_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Allow_HTTP2_class}')]//span").text + + print(first_row_id_content, first_row_Name_content, first_row_Certificate_Checks_content, first_row_Fail_Action_content, first_row_Dynamic_Bypass_content, first_row_Allow_HTTP2_content) + #不同操作后的断言,创建后、修改后、无断言 + if require_assertion == 1: #直接创建后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + self_signed = self._get_value_from_data(data, key="self_signed", data_index=0) + common_name = self._get_value_from_data(data, key="common_name", data_index=0) + fail_action = self._get_value_from_data(data, key="fail_action", data_index=0) + allow_HTTP2 = self._get_value_from_data(data, key="fail_action", data_index=0) + certificate_pinning = self._get_value_from_data(data, key="certificate_pinning", data_index=0) + if self_signed == "on": + pytest_check.is_in("Self-signed", first_row_Certificate_Checks_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if common_name == "on": + pytest_check.is_in("Common Name", first_row_Certificate_Checks_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if fail_action == "pass-through": + pytest_check.is_in("Pass-through", first_row_Fail_Action_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif fail_action == "fail-close": + pytest_check.is_in("Fail-close", first_row_Fail_Action_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if certificate_pinning == "on": + pytest_check.is_in("Certificate Pinning", first_row_Dynamic_Bypass_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if allow_HTTP2 == "on": + pytest_check.is_in("Enabled", first_row_Allow_HTTP2_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + self_signed = self._get_value_from_data(data, key="self_signed", data_index=-1) + common_name = self._get_value_from_data(data, key="common_name", data_index=-1) + fail_action = self._get_value_from_data(data, key="fail_action", data_index=-1) + allow_HTTP2 = self._get_value_from_data(data, key="fail_action", data_index=-1) + certificate_pinning = self._get_value_from_data(data, key="certificate_pinning", data_index=-1) + if self_signed == "on": + pytest_check.is_in("Self-signed", first_row_Certificate_Checks_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if common_name == "on": + pytest_check.is_in("Common Name", first_row_Certificate_Checks_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if fail_action == "pass-through": + pytest_check.is_in("Pass-through", first_row_Fail_Action_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif fail_action == "fail-close": + pytest_check.is_in("Fail-close", first_row_Fail_Action_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if certificate_pinning == "on": + pytest_check.is_in("Certificate Pinning", first_row_Dynamic_Bypass_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + if allow_HTTP2 == "on": + pytest_check.is_in("Enabled", first_row_Allow_HTTP2_content, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_sslDecryptionProfiles_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_sslDecryptionProfiles_editButton_posId).click() + #解析修改数据 + self._operate_page(data, operation_type="edit") + #点击ok + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionProfiles_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, sslDecryptionProfiles_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, sslDecryptionProfiles_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_sslDecryptionProfiles_delButton_posId, listPage_dialogTips_sslDecryptionProfiles_button_yes_posCss, + listPage_dialogTips_sslDecryptionProfiles_button_no_posCss) + + create = _create + query = _query + modify = _modify + delete = _del
\ No newline at end of file diff --git a/common/ui_common/profiles/traffic_mirroring_profiles.py b/common/ui_common/profiles/traffic_mirroring_profiles.py new file mode 100644 index 00000000..22719f0e --- /dev/null +++ b/common/ui_common/profiles/traffic_mirroring_profiles.py @@ -0,0 +1,195 @@ +# -*- coding: UTF-8 -*- +from common.driver_common.mywebdriver import MyWebDriver +from selenium.webdriver.common.by import By +from config.workpath import workdir +from page_element.element_position import * +from common.driver_common.screenshot import screenshot_on_failure +from common.driver_common.random_name import RandomName +from common.ui_common.profiles.profiles_public_operations import ProfilesPublicOperations +import pytest_check +import inspect +import time + + +class TrafficMirroringProfiles: + def __init__(self, demo_fixture: MyWebDriver): + self.workdir = workdir + self.my_random = RandomName() + self.driver = demo_fixture + # 调用profiles公共方法操作、删除、查询, + self.profiles_po = ProfilesPublicOperations(self.driver) + #todo + def traffic_morroring_profiles_case(self, data: {}): + self._create(data) #创建 + self._query(data, require_assertion=1, Name=self.random_name) #创建后查询 + if data["model"].strip().lower() == "modify": #修改测试时,执行修改方法 + self._modify(data) + self._query(data, require_assertion=2, ID=self.first_row_ID_content) + self._del() + + @screenshot_on_failure + def _goto_subProfilePage(self): + # 菜单操作,定位到trafficMirroringProfiles列表页 + self.driver.find_element(By.CSS_SELECTOR, mainPage_navigationBar_logo_posCss).click() + self.driver.find_element(By.ID, mainPage_firstLevelMenu_profiles_posId).click() + self.driver.find_element(By.ID, mainPage_secondLevelMenu_trafficMirroringProfiles_posId).click() + + @screenshot_on_failure + def _create(self, data: {}): + #页面跳转 + self._goto_subProfilePage() + #创建 + #点击create + self.random_name = self.my_random.random_name() + self.driver.find_element(By.ID, listPage_profile_trafficMirroringProfiles_createButton_posId).click() + #在create 创建页面操作 + self.driver.find_element(By.ID, trafficMirroringProfiles_input_Name_posId).send_keys(self.random_name) + #解析输入的vlan id数据 + vlan_ids = data["vlan_id"] + vlan_ids_create = [] #创建的vlan id + for i in vlan_ids: + if i.strip().split("->")[0] != "": + vlan_ids_create.append(i.strip().split("->")[0]) + #循环输入vlan id + for j in range(len(vlan_ids_create)): + #输入ipnut + elements_vlan_ids_input = self.driver.find_elements(By.XPATH, trafficMirroringProfiles_input_vlanIdsInput_posXpath) + for element_vlan_id in elements_vlan_ids_input: + if element_vlan_id.get_attribute("value") == "": #创建时,只是往input.value=none中键入数据 + element_pos_by_id = element_vlan_id.get_attribute("id") + self.driver.find_element(By.ID, element_pos_by_id).send_keys(vlan_ids_create[j]) #输入vlan id的值 + break + if (len(vlan_ids_create) - 1) - j > 0: #点击add按钮比数据个数少一次 + self.driver.find_element(By.CSS_SELECTOR, trafficMirroringProfiles_button_vlanIdAdd_posCss).click() #点击add添加 + #点击OK + self.driver.find_element(By.CSS_SELECTOR, trafficMirroringProfiles_button_oK_posCss).click() + self.driver.find_element(By.CSS_SELECTOR, trafficMirroringProfiles_button_warningSaveYes_posCss).click() + return self.random_name + + @screenshot_on_failure + def _query(self, data: {}, require_assertion=0, **kwargs): + """ + 查询函数,根据输入的类型查询 + :param require_assertion: =0默认情况不需要断言,=1为创建后使用的断言预期,=2为编辑修改后使用的断言预期 + :param kwargs: 例如 :可以查询使用的关键字,ID=None,Name=None, + :return: + """ + #打开该列表 + self._goto_subProfilePage + #first_row查询到的第一行内容。map_header_className为需要使用的到字典,用来提取第一行的结果。 + first_row, map_header_className = \ + self.profiles_po.query(listPage_profileSearch_trafficMirroringProfiles_selectLabel_posId, listPage_profileSearch_trafficMirroringProfiles_dropDown_item_posXpath, + listPage_profileSearch_trafficMirroringProfiles_input_itemContent_posXpath, listPage_profileSearch_trafficMirroringProfiles_buttonSearch_posId, + listPage_profilTable_trafficMirroringProfiles_tableTbody_posXpath, listPage_profilTable_trafficMirroringProfiles_tableHeader_posXpath, **kwargs) + #第一行的勾选定位,给修改、删除使用 + self.first_row_checkBox_element = first_row.find_element(By.XPATH, "//span[@class='el-checkbox__input']") + self.first_row_ID_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']/span").text.strip() + first_row_id_content = first_row.find_element(By.XPATH, "//div[@class='table-status-item-id']//span").text.strip() + first_row_Name_class = map_header_className["Name"] + first_row_Name_content = first_row.find_element(By.XPATH, f"//td[contains(@class, '{first_row_Name_class}')]//span").text.strip() + first_row_VLAN_ID_class = map_header_className["VLAN ID"] + first_row_VLAN_IDs_content = first_row.find_elements(By.XPATH, f"//td[contains(@class, '{first_row_VLAN_ID_class}')]//span//span") + first_row_VLAN_IDS_list = [] + for element_vlan_id in first_row_VLAN_IDs_content: + vlan_id_str = element_vlan_id.text.strip() + if "," in vlan_id_str and len(vlan_id_str) == 1: #跳过只是,的数据 + continue + first_row_VLAN_IDS_list.append(vlan_id_str.strip(",")) + print(first_row_id_content, first_row_Name_content, first_row_VLAN_IDS_list) + #不同操作后的断言,创建后、修改后、无断言 + + if require_assertion == 1: #直接创建后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + # 解析输入的vlan id数据,并断言使用 + vlan_ids = data["vlan_id"] + vlan_ids_create = [] # 创建的vlan id + for i in vlan_ids: + if i.strip().split("->")[0] != "": + vlan_ids_create.append(i.strip().split("->")[0]) + #断言vlan id + for vlan_id in first_row_VLAN_IDS_list: + pytest_check.is_in(vlan_id, vlan_ids_create, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + elif require_assertion == 2 and data["model"].strip().lower() == "modify": #修改数据后,使用的断言 + pytest_check.equal(first_row_Name_content, self.random_name, msg="所在行数{}".format(inspect.currentframe().f_lineno)) + else: #不适用断言 + pass + #强制点击清空查询按钮 + element_clear = self.driver.find_element(By.ID, listPage_profileSearch_trafficMirroringProfiles_buttonClear_posId) + self.driver.execute_script("arguments[0].click()", element_clear) # 强制点击 + return self.first_row_ID_content + + @screenshot_on_failure + def _modify(self, data: {}): + """ + 修改数据,使用方法 + :param data: + :return: + """ + if data["model"].strip().lower() == "create": #如果是create参数用例,则不用执行修改方法 + return 0 + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + self.driver.find_element(By.ID, listPage_profile_trafficMirroringProfiles_editButton_posId).click() + #从data数据中解析出修改数据、删除输出、新增数据 + modify_vlan_ids = [] + del_vlan_ids = [] + add_vlan_ids = [] + raw_vlan_ids = data["vlan_id"] #用例中输入的数据,->前的数据为创建,标识符后的数据为修改的数据 + for item in raw_vlan_ids: + if item.strip().split("->")[0] != "" and item.strip().split("->")[-1] != "": #提创建、取修改数据 + modify_vlan_ids.append(item.strip()) + elif item.strip().split("->")[-1] == "": #提取创建、删除数据 + del_vlan_ids.append(item.strip()) + else: #提取新增数据 + add_vlan_ids.append(item.strip()) + print(modify_vlan_ids, del_vlan_ids, add_vlan_ids) + #操作直接修改vlan id数据 + if len(modify_vlan_ids) != 0: + for modify_item in modify_vlan_ids: + elements_vlan_ids_input = self.driver.find_elements(By.XPATH, trafficMirroringProfiles_input_vlanIdsInput_posXpath) + for element_vlan_id in elements_vlan_ids_input: + if element_vlan_id.get_attribute("value").strip() == modify_item.split("->")[0]: #有需要修改的vlan id + element_vlan_id.clear() + element_vlan_id.send_keys(modify_item.split("->")[-1]) #修改数据 + time.sleep(0.2) + break + #操作直接删除vlan id数据 + if len(del_vlan_ids) != 0: + for del_item in del_vlan_ids: + elements_vlan_ids_input = self.driver.find_elements(By.XPATH, trafficMirroringProfiles_input_vlanIdsInput_posXpath) + for element_vlan_id in elements_vlan_ids_input: + if element_vlan_id.get_attribute("value").strip() == del_item.split("->")[0]: #有需要删除的vlan id + element_vlan_id.find_element(By.XPATH, r"parent::*/parent::*//i").click() #点击删除按钮 + time.sleep(0.2) + break + #操作新增vlan id数据 + if len(add_vlan_ids) != 0: + for add_item in add_vlan_ids: + self.driver.find_element(By.CSS_SELECTOR, trafficMirroringProfiles_button_vlanIdAdd_posCss).click() + elements_vlan_ids_input = self.driver.find_elements(By.XPATH, trafficMirroringProfiles_input_vlanIdsInput_posXpath) + for element_vlan_id in elements_vlan_ids_input: + if element_vlan_id.get_attribute("value") == "": #创建时,只是往input.value=none中键入数据 + element_vlan_id.send_keys(add_item.split("->")[-1]) + time.sleep(0.2) + break + #点击ok + self.driver.find_element(By.CSS_SELECTOR, trafficMirroringProfiles_button_oK_posCss).click() + if self.driver.find_element(By.CSS_SELECTOR, trafficMirroringProfiles_button_warningSaveYes_posCss).is_displayed(): + self.driver.find_element(By.CSS_SELECTOR, trafficMirroringProfiles_button_warningSaveYes_posCss).click() + + @screenshot_on_failure + def _del(self): + """ + 默认删除查询到的第一个结果 + :return: + """ + #点击勾选第一行选择框 + self.first_row_checkBox_element.click() #变量来自查询函数 + #调用profiles的功能删除方法 + self.profiles_po.delete(listPage_profile_trafficMirroringProfiles_delButton_posId, listPage_dialogTips_trafficMirroringProfiles_button_yes_posCss, + listPage_dialogTips_trafficMirroringProfiles_button_no_posCss) + + create = _create + query = _query + modify = _modify + delete = _del
\ No newline at end of file diff --git a/common/ui_read_data/__init__.py b/common/ui_read_data/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/common/ui_read_data/__init__.py diff --git a/common/ui_read_data/__pycache__/__init__.cpython-38.pyc b/common/ui_read_data/__pycache__/__init__.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..29d8cfa5 --- /dev/null +++ b/common/ui_read_data/__pycache__/__init__.cpython-38.pyc diff --git a/common/ui_read_data/__pycache__/read_data.cpython-38.pyc b/common/ui_read_data/__pycache__/read_data.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..8201539a --- /dev/null +++ b/common/ui_read_data/__pycache__/read_data.cpython-38.pyc diff --git a/common/ui_read_data/read_data.py b/common/ui_read_data/read_data.py new file mode 100644 index 00000000..52dea141 --- /dev/null +++ b/common/ui_read_data/read_data.py @@ -0,0 +1,72 @@ +import json +import os +from config.workpath import workdir + +class ReadData: + def __init__(self): + #json文件和测试文件目录 + self.workdir = workdir + self.testdata = "testdata" + self.ui_data = "ui_data" + self.profiles_data = "profiles_data" + # 以下是要读取数据的名称 + self.response_pages_name = "response_pages.json" + self.dns_records_name = "dns_records.json" + self.shaping_profile_name = "shaping_profiles.json" + + def _from_json(self, file): + """ + 从json中读取数据函数 + :param file: + :return: + """ + with open(file, "r", encoding="utf-8") as f: + data = json.load(f)["item"] + data = list(data) + return data + + def _abs_path(self, file_name): + """ + 重组路径 + :param file_name: + :return: + """ + file = os.path.join(self.workdir, self.testdata, self.ui_data, self.profiles_data, file_name) + return file + + @property + def read_response_pages(self): + file = self._abs_path(self.response_pages_name) + return self._from_json(file) + + @property + def read_dns_records(self): + file = self._abs_path(self.dns_records_name) + return self._from_json(file) + + @property + def read_shaping_profiles(self): + file = self._abs_path(self.shaping_profile_name) + return self._from_json(file) + + def read_data_profiles(self, file_name): + """ + 通用读取json数据方法 + :param file_name: + :return: + """ + file = self._abs_path(file_name) + return self._from_json(file) + + def generate_id(self, param): + """ + 测试用例中ids信息提取 + :param param: + :return: + """ + ids: str = param["ids"] + #print(ids) + return ids + +if __name__ == '__main__': + ReadData().read_dns_records
\ No newline at end of file diff --git a/config/__pycache__/workpath.cpython-38.pyc b/config/__pycache__/workpath.cpython-38.pyc Binary files differnew file mode 100644 index 00000000..3fbd6862 --- /dev/null +++ b/config/__pycache__/workpath.cpython-38.pyc diff --git a/config/ui_conf/__init__.py b/config/ui_conf/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/config/ui_conf/__init__.py diff --git a/config/ui_conf/importfile.ini b/config/ui_conf/importfile.ini new file mode 100644 index 00000000..71747f2a --- /dev/null +++ b/config/ui_conf/importfile.ini @@ -0,0 +1,13 @@ +[profiles] #profiles中文件使用路径管理 +#profiles上传文件多层目录结构 +testdata = testdata +ui_file = ui_file +profiles = profiles +#response_pages上传文件目录 +response_pages = response_pages +#ssl_decryption_keyrings上传文件目录 +ssl_decryption_keyrings = ssl_decryption_keyrings +#hijack_files上传文件目录 +hijack_files = hijack_files +# insert_scripts 上传文件目录 +insert_scripts = insert_scripts
\ No newline at end of file diff --git a/config/ui_conf/loginout.ini b/config/ui_conf/loginout.ini new file mode 100644 index 00000000..59d9f7e1 --- /dev/null +++ b/config/ui_conf/loginout.ini @@ -0,0 +1,12 @@ +[remote_url] +url = http://192.168.64.34:4444 +#url = http://192.168.64.33:4444 + +[tsg_url] +login_url = http://192.168.44.72 + +[ui_account_1] +username = Auto_UI_Test_2 +passwd = Auto_UI_Test_2 +#username = admin +#passwd = admin
\ No newline at end of file diff --git a/config/workpath.py b/config/workpath.py new file mode 100644 index 00000000..48dd69a2 --- /dev/null +++ b/config/workpath.py @@ -0,0 +1,5 @@ +import os + + +#获取工作目录 +workdir = os.path.dirname(os.path.dirname(__file__)) diff --git a/main.py b/main.py new file mode 100644 index 00000000..c2a9aeb4 --- /dev/null +++ b/main.py @@ -0,0 +1,24 @@ +import pytest + + + + + + +if __name__ == '__main__': + print(223333) + pytest.main(["-s", "-v", "cases/ui"]) + print(55633) + + """ + # 在测试文件的当前路径执行如下命令执行测试用例: + --max + pytest –cache-clear -v pytest_json.py --alluredir ./allure + --check-max-tb 9000 #最大校验 + --reruns=1 #失败重运行次数 + pytest -cache-clear -sv ./cases/ui --check-max-tb 9000 --alluredir ./results/reports + pytest -cache-clear -sv ./cases/ui --check-max-tb 9000 --reruns=1 --alluredir ./results/reports + allure serve ./results/reports + # 执行如下命令生成测试报告(自动打开浏览器): + allure serve allure + """
\ No newline at end of file diff --git a/page_element/element_position.py b/page_element/element_position.py new file mode 100644 index 00000000..5312a561 --- /dev/null +++ b/page_element/element_position.py @@ -0,0 +1,278 @@ +#login page 登录页面 +loginPage_userName_posName = "username" +loginPage_passwd_posName = "password" +loginPage_signIn_posId = "login" + +#main页面 +##上导航栏 +mainPage_navigationBar_logo_posCss = ".tsg-img-logo" +#菜单栏================================菜单栏===================================菜单栏================================菜单栏==================================菜单栏========================菜单栏 +##菜单栏 +mainPage_firstLevelMenu_profiles_posId = "Profiles" #一级菜单Profiles +mainPage_secondLevelMenu_responsePages_posId = "Proxy_Profiles/Profile_ResponsePages" #二级菜单response pages +mainPage_secondLevelMenu_dnsRecords_posId = "Proxy_Profiles/DNS_record_profile" #二级菜单dns records +mainPage_secondLevelMenu_trafficMirroringProfiles_posId = "Proxy_Profiles/Profile_TrafficMirrorProfiles" #二级菜单traffic mirroring profiles +mainPage_secondLevelMenu_sslDecryptionKeyrings_posId = "Proxy_CertificateManagement/Certificate_Keyrings" #二级菜单ssl decryption keyrings +mainPage_secondLevelMenu_sslDecryptionProfiles_posId = "Proxy_Profiles/Profile_DecryptionProfile" #二级菜单ssl decryption Profiles +mainPage_secondLevelMenu_hijackFiles_posId = "Proxy_Profiles/Profile_HijackFiles" #二级菜单hijack files +mainPage_secondLevelMenu_insertScripts_posId = "Proxy_Profiles/Profile_Insert" #二级菜单insert scripts +mainPage_secondLevelMenu_shapingProfiles_posId = "Proxy_Profiles/ShapingProfile" #二级菜单shaping profiles + + +#Profiles 查询栏===================Profiles 查询栏=====================Profiles 查询栏=================Profiles 查询栏=======================Profiles 查询栏=================Profiles 查询栏 +##profiles模块查询栏 +mainPage_profileSearch_selectLabel_posId = "select-label" #查询框id +mainPage_profileSearch_buttonSearch_posId = "searchQuery" #查询按钮id +mainPage_profileSearch_buttonClear_posId = "searchClear" #清空查询按钮id + + +#Profiles DNS Records===================Profiles DNS Records====================Profiles DNS Records=================Profiles DNS Records=======================Profiles DNS Records=================Profiles DNS Records +#DNS Records list page 列表页 +listPage_profile_dnsRecords_createButton_posId = "app_create-_OperateBtns_ElRow_DNSRecordProfile_Home_App_anonymousComponent" #create按钮id +listPage_profile_dnsRecords_editButton_posId = "appEdit-_OperateBtns_ElRow_DNSRecordProfile_Home_App_anonymousComponent" #edit按钮id +listPage_profile_dnsRecords_delButton_posId = "appDel-_OperateBtns_ElRow_DNSRecordProfile_Home_App_anonymousComponent" #del按钮id +listPage_profileSearch_dnsRecords_selectLabel_posId = mainPage_profileSearch_selectLabel_posId #查询框id +listPage_profileSearch_dnsRecords_buttonSearch_posId = mainPage_profileSearch_buttonSearch_posId #查询按钮id +listPage_profileSearch_dnsRecords_buttonClear_posId = mainPage_profileSearch_buttonClear_posId #清空查询按钮id +listPage_profileSearch_dnsRecords_dropDown_item_posXpath = "//div[contains(@class,'el-scrollbar')]//span[normalize-space(text())='{replaceName}']" #下拉菜单定位 +listPage_profileSearch_dnsRecords_input_itemContent_posXpath = "//div[contains(@class,'ListItem')]//span[normalize-space(text())='{replaceName}']/ancestor::div[contains(@class,'ListItem')]//input" #输入item的值,replaceName替换实际查询值 +listPage_profileSearch_dnsRecords_dropDown_typeItem_posXpath = "//div[contains(@class,'select-popper')]//span[normalize-space(text())='{replaceName}']" #查询中type的下拉item定位,replaceName替换实际查询值 +listPage_profilTable_dnsRecords_tableTbody_posXpath = "//div[contains(@class,'ly-table1')]//tbody" #列表tabel body xpath +listPage_profilTable_dnsRecords_tableHeader_posXpath = "//div[contains(@class,'ly-table1')]//table[@class='el-table__header']//thead//tr" #列表table 表头xpath +#listPage->Tips dialog 列表页 tips对话框 +listPage_dialogTips_dnsRecords_button_yes_posCss = ".delComponents-ok span" #删除提示的Tips的yes按钮 +listPage_dialogTips_dnsRecords_button_no_posCss = ".delComponents-close span" #删除提示的Tips的close按钮 +#Create DNS Record Profile 和 Edit DNS Record Profile 新增和编辑页 +dnsRecordsProfilePage_input_Name_posId = "DNSRecordPrfileadd_Home_App_anonymousComponent_objectAdd_name" #name输入框id +dnsRecordsProfilePage_radioButton_typeA_posId = "objectAdd_ip0-_DNSRecordPrfileadd_Home_App_anonymousComponent" #A单选按钮id, +dnsRecordsProfilePage_radioButton_typeAAAA_posId = "objectAdd_ip1-_DNSRecordPrfileadd_Home_App_anonymousComponent" #AAAA单选按钮id +dnsRecordsProfilePage_radioButton_typeCNAME_posId = "objectAdd_ip2-_DNSRecordPrfileadd_Home_App_anonymousComponent" #CNAME单选按钮id +dnsRecordsProfilePage_input_searchFor_posId = "object_ip_search" #search for 输入框id +dnsRecordsProfilePage_button_addItem_posId = "temporary_form" #添加item按钮id +dnsRecordsProfilePage_input_inputItemName_posXpath = "//span[normalize-space(text())='replaceName' and contains(@class,'content-show')]/ancestor::div[@class='item-row']//input[@class='el-input__inner']" #item的输入框xpath, replaceNamew为替换内容 +dnsRecordsProfilePage_button_saveItemByName_posXpath = "//span[normalize-space(text())='replaceName' and contains(@class, 'content-show')]/ancestor::div[@class='item-row']//i[contains(@class, 'icon-save')]" #item的保存xpath, replaceNamew为替换内容 +dnsRecordsProfilePage_button_editItemByName_posXpath = "//span[normalize-space(text())='replaceName' and contains(@class,'content-show')]/ancestor::div[@class='item-row']//i[contains(@class, 'icon-Edit')]" #item的编辑按钮xpath, replaceNamew为替换内容 +dnsRecordsProfilePage_button_delItemByName_posXpath = "//span[normalize-space(text())='replaceName' and contains(@class,'content-show')]/ancestor::div[@class='item-row']//i[contains(@class, 'icon-Delete_X')]" #item的删除按钮, replaceNamew为替换内容 +dnsRecordsProfilePage_textArea_Description_posId = "DNSRecordPrfileadd_Home_App_anonymousComponent_objectAdd_description" #description文本输入区id +dnsRecordsProfilePage_button_warningSaveYes_posCss = ".el-message-box__btns .el-button--primary span" #提示保存ok按钮警告框 +dnsRecordsProfilePage_button_warningSaveCancel_posCss = ".el-message-box__btns .operation-cancel span" #提示保存取消按钮警告框 +dnsRecordsProfilePage_button_oK_posCss = "#dnsRecord_ok-_DNSRecordPrfileadd_Home_App_anonymousComponent span" #OK按钮css +dnsRecordsProfilePage_button_cancel_posCss = "#dnsRecord_cancel-_DNSRecordPrfileadd_Home_App_anonymousComponent span" #Cancel + + +#Profiles Response-Pages===================Profiles Response-Pages====================Profiles Response-Pages=================Profiles Response-Pages=======================Profiles Response-Pages=================Profiles Response-Pages +#Response Pages list page 列表页 +listPage_profile_responsePages_createButton_posId = "app_create-_OperateBtns_ElRow_Profile_ResponsePages_Home_App_anonymousComponent" #create按钮id +listPage_profile_responsePages_editButton_posId = "appEdit-_OperateBtns_ElRow_Profile_ResponsePages_Home_App_anonymousComponent" #edit按钮id +listPage_profile_responsePages_delButton_posId = "appDel-_OperateBtns_ElRow_Profile_ResponsePages_Home_App_anonymousComponent" #del按钮id +listPage_profileSearch_responsePages_selectLabel_posId = mainPage_profileSearch_selectLabel_posId #查询框id 定位形式一样 +listPage_profileSearch_responsePages_buttonSearch_posId = mainPage_profileSearch_buttonSearch_posId #查询按钮id 定位形式一样 +listPage_profileSearch_responsePages_buttonClear_posId = mainPage_profileSearch_buttonClear_posId #清空查询按钮id 定位形式一样 +listPage_profileSearch_responsePages_dropDown_item_posXpath = listPage_profileSearch_dnsRecords_dropDown_item_posXpath #下拉菜单定位 定位形式一样 +listPage_profileSearch_responsePages_input_itemContent_posXpath = listPage_profileSearch_dnsRecords_input_itemContent_posXpath #输入item的值,replaceName替换实际查询值 定位形式一样 +listPage_profilTable_responsePages_tableTbody_posXpath = listPage_profilTable_dnsRecords_tableTbody_posXpath #列表tabel body xpath 定位形式一样 +listPage_profilTable_responsePages_tableHeader_posXpath = listPage_profilTable_dnsRecords_tableHeader_posXpath #列表table 表头xpath 定位形式一样 +#listPage->Tips dialog 列表页 tips对话框 +listPage_dialogTips_responsePages_button_yes_posCss = listPage_dialogTips_dnsRecords_button_yes_posCss #删除提示的Tips的yes按钮 +listPage_dialogTips_responsePages_button_no_posCss = listPage_dialogTips_dnsRecords_button_no_posCss #删除提示的Tips的close按钮 +#Create Response Page 和 Edit Response Page 新增和编辑页 +responsePage_input_Name_posId = "responsepages_profileName" #name输入框id +responsePage_input_file_posXpath = "//*[@id='responseAddUpload']/parent::*//input" #File上次输入按钮 +responsePage_button_warningSaveYes_posCss = dnsRecordsProfilePage_button_warningSaveYes_posCss #提示保存按钮警告框OK按钮 +responsePage_button_warningSaveCancel_posCss = dnsRecordsProfilePage_button_warningSaveCancel_posCss #提示保存警告框Cancel按钮 +responsePage_button_oK_posCss = "#responseAddOk1 span" #OK按钮css +responsePage_button_cancel_posCss = "#responseAddCancel1 span" #Cancel按钮 + + +#Profiles traffic mirroring profiles===================Profiles traffic mirroring profiles====================Profiles traffic mirroring profiles=================Profiles traffic mirroring profiles=======================Profiles traffic mirroring profiles=================Profiles traffic mirroring profiles +#listPage->traffic mirroring profiles list page 列表页 +listPage_profile_trafficMirroringProfiles_createButton_posId = "app_create-_OperateBtns_ElRow_Profile_TrafficMirrorProfiles_Home_App_anonymousComponent" #create按钮id +listPage_profile_trafficMirroringProfiles_editButton_posId = "appEdit-_OperateBtns_ElRow_Profile_TrafficMirrorProfiles_Home_App_anonymousComponent" #edit按钮id +listPage_profile_trafficMirroringProfiles_delButton_posId = "appDel-_OperateBtns_ElRow_Profile_TrafficMirrorProfiles_Home_App_anonymousComponent" #del按钮id +listPage_profileSearch_trafficMirroringProfiles_selectLabel_posId = mainPage_profileSearch_selectLabel_posId #查询框id 定位形式一样 +listPage_profileSearch_trafficMirroringProfiles_buttonSearch_posId = mainPage_profileSearch_buttonSearch_posId #查询按钮id 定位形式一样 +listPage_profileSearch_trafficMirroringProfiles_buttonClear_posId = mainPage_profileSearch_buttonClear_posId #清空查询按钮id 定位形式一样 +listPage_profileSearch_trafficMirroringProfiles_dropDown_item_posXpath = listPage_profileSearch_dnsRecords_dropDown_item_posXpath #下拉菜单定位 定位形式一样 +listPage_profileSearch_trafficMirroringProfiles_input_itemContent_posXpath = listPage_profileSearch_dnsRecords_input_itemContent_posXpath #输入item的值,replaceName替换实际查询值 定位形式一样 +listPage_profilTable_trafficMirroringProfiles_tableTbody_posXpath = listPage_profilTable_dnsRecords_tableTbody_posXpath #列表tabel body xpath 定位形式一样 +listPage_profilTable_trafficMirroringProfiles_tableHeader_posXpath = listPage_profilTable_dnsRecords_tableHeader_posXpath #列表table 表头xpath 定位形式一样 +#listPage->Tips dialog 列表页 tips对话框 +listPage_dialogTips_trafficMirroringProfiles_button_yes_posCss = listPage_dialogTips_dnsRecords_button_yes_posCss #删除提示的Tips的yes按钮 +listPage_dialogTips_trafficMirroringProfiles_button_no_posCss = listPage_dialogTips_dnsRecords_button_no_posCss #删除提示的Tips的close按钮 +#Create traffic mirroring profile page 和 Edit traffic mirroring profile page 新增和编辑页 +trafficMirroringProfiles_input_Name_posId = "trafficmirror_profileName" #name输入框id +trafficMirroringProfiles_button_vlanIdAdd_posCss = "#addrTypeAdd i" #vlan id 添加按钮css +trafficMirroringProfiles_input_vlanIdsInput_posXpath = "//form//div[contains(@class, 'addel-form')]//input" #所有显示的vlan id的所有input定位,需要通过value二次处理,css +trafficMirroringProfiles_button_warningSaveYes_posCss = dnsRecordsProfilePage_button_warningSaveYes_posCss #提示保存按钮警告框OK按钮 +trafficMirroringProfiles_button_warningSaveCancel_posCss = dnsRecordsProfilePage_button_warningSaveCancel_posCss #提示保存警告框Cancel按钮 +trafficMirroringProfiles_button_oK_posCss = "#trafficMirrorProfile_ok span" #OK按钮css +trafficMirroringProfiles_button_cancel_posCss = "#trafficMirrorProfile_cancel span" #Cancel按钮 + + +#Profiles ssl decryption keyrings===================Profiles ssl decryption keyrings====================Profiles ssl decryption keyrings=================Profiles ssl decryption keyrings=======================Profiles ssl decryption keyrings +#listPage->ssl decryption keyrings list page 列表页 +listPage_profile_sslDecryptionKeyrings_createButton_posId = "app_create-_OperateBtns_ElRow_Certificate_Keyrings_Home_App_anonymousComponent" #create按钮id +listPage_profile_sslDecryptionKeyrings_editButton_posId = "appEdit-_OperateBtns_ElRow_Certificate_Keyrings_Home_App_anonymousComponent" #edit按钮id +listPage_profile_sslDecryptionKeyrings_delButton_posId = "appDel-_OperateBtns_ElRow_Certificate_Keyrings_Home_App_anonymousComponent" #del按钮id +listPage_profileSearch_sslDecryptionKeyrings_selectLabel_posId = mainPage_profileSearch_selectLabel_posId #查询框id 定位形式一样 +listPage_profileSearch_sslDecryptionKeyrings_buttonSearch_posId = mainPage_profileSearch_buttonSearch_posId #查询按钮id 定位形式一样 +listPage_profileSearch_sslDecryptionKeyrings_buttonClear_posId = mainPage_profileSearch_buttonClear_posId #清空查询按钮id 定位形式一样 +listPage_profileSearch_sslDecryptionKeyrings_dropDown_item_posXpath = listPage_profileSearch_dnsRecords_dropDown_item_posXpath #下拉菜单定位 定位形式一样 +listPage_profileSearch_sslDecryptionKeyrings_input_itemContent_posXpath = listPage_profileSearch_dnsRecords_input_itemContent_posXpath #输入item的值,replaceName替换实际查询值 定位形式一样 +listPage_profilTable_sslDecryptionKeyrings_tableTbody_posXpath = listPage_profilTable_dnsRecords_tableTbody_posXpath #列表tabel body xpath 定位形式一样 +listPage_profilTable_sslDecryptionKeyrings_tableHeader_posXpath = listPage_profilTable_dnsRecords_tableHeader_posXpath #列表table 表头xpath 定位形式一样 +#listPage->Tips dialog 列表页 tips对话框 +listPage_dialogTips_sslDecryptionKeyrings_button_yes_posCss = listPage_dialogTips_dnsRecords_button_yes_posCss #删除提示的Tips的yes按钮 +listPage_dialogTips_sslDecryptionKeyrings_button_no_posCss = listPage_dialogTips_dnsRecords_button_no_posCss #删除提示的Tips的close按钮 +#Create ssl decryption keyrings page 和 Edit ssl decryption keyrings page 新增和编辑页 +sslDecryptionKeyrings_input_Name_posId = "keyringsadd_name" #name输入框id +sslDecryptionKeyrings_input_certificateFile_posXpath = "//*[@id='keyringsadd_file']/parent::*//input" #证书上传按钮xpath +sslDecryptionKeyrings_radio_privateKeyFile_posId = "privateFile" #私钥单选按钮 +sslDecryptionKeyrings_radio_hsm_posId = "privateHSM" #私钥单选按钮 +sslDecryptionKeyrings_input_privateKeyFile_posXpath = "//*[@id='keyringsadd_file1']/parent::*//input" #证书上传按钮xpath +sslDecryptionKeyrings_input_slotIdHSM_posId = "keyringsadd_slotid" #slot id输入框定位id +sslDecryptionKeyrings_radio_mirrorServerCertificate_poId = "keyringsadd_default" #默认服务端证书时间单选按钮id +sslDecryptionKeyrings_radio_customized_poId = "keyringsadd_customized" #自定义时间单选按钮id +sslDecryptionKeyrings_input_customized_poId = "reissueExpiryDate" #自定义输入框id +sslDecryptionKeyrings_input_certificateType_poId = "certificateType_input" #证书类型选择输入框id +sslDecryptionKeyrings_dropdown_certificateTypeSelect_poId = "certificateType_select{replaceIndex}" #证书类型下拉列表item选择,replaceIndex为替换索引 +sslDecryptionKeyrings_input_publickKeyAlgorithm_poId = "keyringsadd_publicKeyAlgo" #公钥算法选择输入框id +sslDecryptionKeyrings_dropdown_publickKeyAlgorithmSelect_poId = "keyringsadd_publicKeyAlgoSelet{replaceIndex}" #公钥算术下拉列表item选择,replaceIndex为替换索引 +sslDecryptionKeyrings_input_certificateRevocationList_poId = "keyringsadd_crl" #Certificate Revocation List输入框id +sslDecryptionKeyrings_input_includeRoot_poXpath = "//*[@id='keyringsadd_includeRoot']/parent::*/span" #包含根证书输入框开关选择xpath +sslDecryptionKeyrings_button_warningSaveYes_posCss = dnsRecordsProfilePage_button_warningSaveYes_posCss #提示保存按钮警告框OK按钮 +sslDecryptionKeyrings_button_warningSaveCancel_posCss = dnsRecordsProfilePage_button_warningSaveCancel_posCss #提示保存警告框Cancel按钮 +sslDecryptionKeyrings_button_oK_posCss = "#keyringsadd_sub span" #OK按钮css +sslDecryptionKeyrings_button_cancel_posCss = "#keyringsadd_info span" #Cancel按钮 + + +#Profiles ssl decryption profiles===================Profiles ssl decryption profiles====================Profiles ssl decryption profiles=================Profiles ssl decryption profiles=======================Profiles ssl decryption profiles +#listPage->ssl decryption profiles list page 列表页 +listPage_profile_sslDecryptionProfiles_createButton_posId = "app_create-_OperateBtns_ElRow_Profile_Decryption_Profile_Home_App_anonymousComponent" #create按钮id +listPage_profile_sslDecryptionProfiles_editButton_posId = "appEdit-_OperateBtns_ElRow_Profile_Decryption_Profile_Home_App_anonymousComponent" #edit按钮id +listPage_profile_sslDecryptionProfiles_delButton_posId = "appDel-_OperateBtns_ElRow_Profile_Decryption_Profile_Home_App_anonymousComponent" #del按钮id +listPage_profileSearch_sslDecryptionProfiles_selectLabel_posId = mainPage_profileSearch_selectLabel_posId #查询框id 定位形式一样 +listPage_profileSearch_sslDecryptionProfiles_buttonSearch_posId = mainPage_profileSearch_buttonSearch_posId #查询按钮id 定位形式一样 +listPage_profileSearch_sslDecryptionProfiles_buttonClear_posId = mainPage_profileSearch_buttonClear_posId #清空查询按钮id 定位形式一样 +listPage_profileSearch_sslDecryptionProfiles_dropDown_item_posXpath = listPage_profileSearch_dnsRecords_dropDown_item_posXpath #下拉菜单定位 定位形式一样 +listPage_profileSearch_sslDecryptionProfiles_input_itemContent_posXpath = listPage_profileSearch_dnsRecords_input_itemContent_posXpath #输入item的值,replaceName替换实际查询值 定位形式一样 +listPage_profilTable_sslDecryptionProfiles_tableTbody_posXpath = listPage_profilTable_dnsRecords_tableTbody_posXpath #列表tabel body xpath 定位形式一样 +listPage_profilTable_sslDecryptionProfiles_tableHeader_posXpath = listPage_profilTable_dnsRecords_tableHeader_posXpath #列表table 表头xpath 定位形式一样 +#listPage->Tips dialog 列表页 tips对话框 +listPage_dialogTips_sslDecryptionProfiles_button_yes_posCss = listPage_dialogTips_dnsRecords_button_yes_posCss #删除提示的Tips的yes按钮 +listPage_dialogTips_sslDecryptionProfiles_button_no_posCss = listPage_dialogTips_dnsRecords_button_no_posCss #删除提示的Tips的close按钮 +#Create ssl decryption profiles page 和 Edit ssl decryption profiles page 新增和编辑页 +sslDecryptionProfiles_input_Name_posId = "decrytion_profileName" #name输入框id +sslDecryptionProfiles_switch_commonName_posXpath = "//*[@id='decryption-commenName']/parent::*" #common name 开关xpath +sslDecryptionProfiles_switch_issuer_posXpath = "//*[@id='decryption-issuer']/parent::*" #issuer 开关xpath +sslDecryptionProfiles_switch_selfSigned_posXpath = "//*[@id='decryption-signed']/parent::*" #decryption-signed 开关xpath +sslDecryptionProfiles_switch_expiryDate_posXpath = "//*[@id='decryption-expiration']/parent::*" #ddecryption-expiration 开关xpath +sslDecryptionProfiles_radio_failClose_posXpath = "//*[@id='decryptionfail-close']" #decryptionfail-close 点选按钮 Fail-close xpath +sslDecryptionProfiles_radio_passThrough_posXpath = "//*[@id='decryptionpass-through']" #decryptionpass-through 点选按钮 Pass-through xpath +sslDecryptionProfiles_switch_evCert_posXpath = "//*[@id='decryption-ev_cert']/parent::*" #ddecryption-expiration 开关xpath +sslDecryptionProfiles_switch_certificateTransparency_posXpath = "//*[@id='decryption-cert_transparency']/parent::*" #Certificate Transparency 开关xpath +sslDecryptionProfiles_switch_mutualAuthentication_posXpath = "//*[@id='decryption-client_cert_req']/parent::*" #Mutual Authentication 开关xpath +sslDecryptionProfiles_switch_onProtocolErrors_posXpath = "//*[@id='decryption-protocol_errors']/parent::*" #On Protocol Errors 开关xpath +sslDecryptionProfiles_switch_certificatePinning_posXpath = "//*[@id='decryption-pinning']/parent::*" #Certificate Pinning 开关xpath +sslDecryptionProfiles_switch_certificateNotInstalled_posXpath = "//*[@id='decryption-Certificate_Not_Installed']/parent::*" #Certificate Not Installed 开关xpath +sslDecryptionProfiles_switch_mirrorClientVersions_posXpath = "//*[@id='decryption-radio']/parent::*" #Mirror Client Versions 开关xpath +sslDecryptionProfiles_input_minVersion_posXpath = "//*[@id='decryption-radio']/ancestor::div[@class='decryption_from']/div[2]//i" #Min Version 下拉菜单xpath +sslDecryptionProfiles_dropDown_minVersion_posXpath = "//*[@id='pro_min{replaceIndex}']" #MMin Version 下拉列表中item选项定位 xpath。replaceIndex需要二次处理,替换为实际的索引。 +sslDecryptionProfiles_dropDown_maxVersion_posXpath = "//*[@id='pro_max{replaceIndex}']" #MMin Version 下拉列表中item选项定位 xpath。replaceIndex需要二次处理,替换为实际的索引。 +sslDecryptionProfiles_input_maxVersion_posXpath = "//*[@id='decryption-radio']/ancestor::div[@class='decryption_from']/div[3]//i" #Max Version 下拉菜单xpath +sslDecryptionProfiles_switch_allowHTTP2_posXpath = "//*[@id='decryption-allow_http2']/parent::*" #Allow HTTP2 开关xpath +sslDecryptionProfiles_button_warningSaveYes_posCss = dnsRecordsProfilePage_button_warningSaveYes_posCss #提示保存按钮警告框OK按钮 +slDecryptionProfiles_button_warningSaveCancel_posCss = dnsRecordsProfilePage_button_warningSaveCancel_posCss #提示保存警告框Cancel按钮 +sslDecryptionProfiles_button_oK_posCss = "#decryption-ok span" #OK按钮css +sslDecryptionProfiles_button_cancel_posCss = "#decryption-cancel span" #Cancel按钮 + + +#Profiles hijack files===================Profiles hijack files====================Profiles hijack files=================Profiles hijack files=======================Profiles hijack files +#listPage->hijack files list page 列表页 +listPage_profile_hijackFiles_createButton_posId = "app_create-_OperateBtns_ElRow_Profile_HijackFiles_Home_App_anonymousComponent" #create按钮id +listPage_profile_hijackFiles_editButton_posId = "appEdit-_OperateBtns_ElRow_Profile_HijackFiles_Home_App_anonymousComponent" #edit按钮id +listPage_profile_hijackFiles_delButton_posId = "appDel-_OperateBtns_ElRow_Profile_HijackFiles_Home_App_anonymousComponent" #del按钮id +listPage_profileSearch_hijackFiles_selectLabel_posId = mainPage_profileSearch_selectLabel_posId #查询框id 定位形式一样 +listPage_profileSearch_hijackFiles_buttonSearch_posId = mainPage_profileSearch_buttonSearch_posId #查询按钮id 定位形式一样 +listPage_profileSearch_hijackFiles_buttonClear_posId = mainPage_profileSearch_buttonClear_posId #清空查询按钮id 定位形式一样 +listPage_profileSearch_hijackFiles_dropDown_item_posXpath = listPage_profileSearch_dnsRecords_dropDown_item_posXpath #下拉菜单定位 定位形式一样 +listPage_profileSearch_hijackFiles_input_itemContent_posXpath = listPage_profileSearch_dnsRecords_input_itemContent_posXpath #输入item的值,replaceName替换实际查询值 定位形式一样 +listPage_profilTable_hijackFiles_tableTbody_posXpath = listPage_profilTable_dnsRecords_tableTbody_posXpath #列表tabel body xpath 定位形式一样 +listPage_profilTable_hijackFiles_tableHeader_posXpath = listPage_profilTable_dnsRecords_tableHeader_posXpath #列表table 表头xpath 定位形式一样 +#listPage->Tips dialog 列表页 tips对话框 +listPage_dialogTips_hijackFiles_button_yes_posCss = listPage_dialogTips_dnsRecords_button_yes_posCss #删除提示的Tips的yes按钮 +listPage_dialogTips_hijackFiles_button_no_posCss = listPage_dialogTips_dnsRecords_button_no_posCss #删除提示的Tips的close按钮 +#Create hijack files page 和 Edit hijack files page 新增和编辑页 +hijackFiles_input_Name_posId = "hijack_profileName" #name输入框id +hijackFiles_input_fileUpLoad_posXpath = "//*[@id='uploadFile']/parent::*//input" #input 上传文件xpath +hijackFiles_switch_downLoadName_posXpath = "//*[@id='contentNameChoose']/parent::*" #download name状态开关 xpath,点击操作其子元素改变状态 +hijackFiles_input_downLoadName_posXpath = "//*[@id='hijack_contentName']" #下载文件名称输入框 xpath +hijackFiles_button_fileType_posXpath = "//*[@id='hijackAddContentType']" #添加文件类型按钮 xpath +hijackFiles_tablist_fileType_posXpath = "//*[@class='right-show-edit']//span[normalize-space(text())='{replaceName}']" #右侧滑中type元素定位 xpath。需要二次处理,replaceName替换为类型名称 +hijackFiles_button_warningSaveYes_posCss = dnsRecordsProfilePage_button_warningSaveYes_posCss #提示保存按钮警告框OK按钮 +hijackFiles_button_warningSaveCancel_posCss = dnsRecordsProfilePage_button_warningSaveCancel_posCss #提示保存警告框Cancel按钮 +hijackFiles_button_oK_posCss = "#hijackAddOk1 span" #OK按钮css +hijackFiles_button_cancel_posCss = "#hijackAddCancel1 span" #Cancel按钮 + + +#Profiles insert scripts===================Profiles insert scripts====================Profiles insert scripts=================Profiles insert scripts=======================Profiles insert scripts +#listPage->insert scripts list page 列表页 +listPage_profile_insertScripts_createButton_posId = "app_create-_OperateBtns_ElRow_Profile_Insert_Home_App_anonymousComponent" #create按钮id +listPage_profile_insertScripts_editButton_posId = "appEdit-_OperateBtns_ElRow_Profile_Insert_Home_App_anonymousComponent" #edit按钮id +listPage_profile_insertScripts_delButton_posId = "appDel-_OperateBtns_ElRow_Profile_Insert_Home_App_anonymousComponent" #del按钮id +listPage_profileSearch_insertScripts_selectLabel_posId = mainPage_profileSearch_selectLabel_posId #查询框id 定位形式一样 +listPage_profileSearch_insertScripts_buttonSearch_posId = mainPage_profileSearch_buttonSearch_posId #查询按钮id 定位形式一样 +listPage_profileSearch_insertScripts_buttonClear_posId = mainPage_profileSearch_buttonClear_posId #清空查询按钮id 定位形式一样 +listPage_profileSearch_insertScripts_dropDown_item_posXpath = listPage_profileSearch_dnsRecords_dropDown_item_posXpath #下拉菜单定位 定位形式一样 +listPage_profileSearch_insertScripts_input_itemContent_posXpath = listPage_profileSearch_dnsRecords_input_itemContent_posXpath #输入item的值,replaceName替换实际查询值 定位形式一样 +listPage_profilTable_insertScripts_tableTbody_posXpath = listPage_profilTable_dnsRecords_tableTbody_posXpath #列表tabel body xpath 定位形式一样 +listPage_profilTable_insertScripts_tableHeader_posXpath = listPage_profilTable_dnsRecords_tableHeader_posXpath #列表table 表头xpath 定位形式一样 +#listPage->Tips dialog 列表页 tips对话框 +listPage_dialogTips_insertScripts_button_yes_posCss = listPage_dialogTips_dnsRecords_button_yes_posCss #删除提示的Tips的yes按钮 +listPage_dialogTips_insertScripts_button_no_posCss = listPage_dialogTips_dnsRecords_button_no_posCss #删除提示的Tips的close按钮 +#Create insert scripts page 和 Edit inserts script page 新增和编辑页 +insertScripts_input_Name_posId = "insert_profileName" #name输入框id +hijackFiles_input_scriptUpLoad_posXpath = "/*[@id='insertAddUpload']//input" #input 上传文件xpath +hijackFiles_input_scriptType_posXpath = "//*[@id='insert_select_format']" #input 文件类型选择xpath +hijackFiles_dropdown_jsItem_posXpath = "//*[@id='insert_select_formatjs']" #下拉菜单 js选项 xpath +hijackFiles_dropdown_cssItem_posXpath = "//*[@id='insert_select_formatcss']" #下拉菜单 js选项 xpath +hijackFiles_input_insertPosition_posXpath = "//*[@id='insert_select_insertOn']" #input insert position xpath +# todo +hijackFiles_dropdown_cssItem_posXpath = "//*[@id='insert_select_formatcss']" #下拉菜单 js选项 xpath + + +insertScripts_button_warningSaveYes_posCss = dnsRecordsProfilePage_button_warningSaveYes_posCss #提示保存按钮警告框OK按钮 +insertScripts_button_warningSaveCancel_posCss = dnsRecordsProfilePage_button_warningSaveCancel_posCss #提示保存警告框Cancel按钮 +insertScripts_button_oK_posCss = "#hijackAddOk1 span" #OK按钮css +insertScripts_button_cancel_posCss = "#hijackAddCancel1 span" #Cancel按钮 + + +#Profiles rofiles-Shaping=============Profiles rofiles-Shaping===================Profiles rofiles-Shaping====================Profiles rofiles-Shaping==================Profiles rofiles-Shaping==============Profiles rofiles-Shaping +#Shaping Profiles list page 列表页 +listPage_profile_shapingProfiles_createButton_posId = "app_create-_OperateBtns_ElRow_Profile_ShapingProfile_Home_App_anonymousComponent" #create按钮id +listPage_profile_shapingProfiles_editButton_posId = "appEdit-_OperateBtns_ElRow_Profile_ShapingProfile_Home_App_anonymousComponent" #edit按钮id +listPage_profile_shapingProfiles_delButton_posId = "appDel-_OperateBtns_ElRow_Profile_ShapingProfile_Home_App_anonymousComponent" #del按钮id +listPage_profileSearch_shapingProfiles_selectLabel_posId = mainPage_profileSearch_selectLabel_posId #查询框id 定位形式一样 +listPage_profileSearch_shapingProfiles_buttonSearch_posId = mainPage_profileSearch_buttonSearch_posId #查询按钮id 定位形式一样 +listPage_profileSearch_shapingProfiles_buttonClear_posId = mainPage_profileSearch_buttonClear_posId #清空查询按钮id 定位形式一样 +listPage_profileSearch_shapingProfiles_dropDown_item_posXpath = listPage_profileSearch_dnsRecords_dropDown_item_posXpath #下拉菜单定位 定位形式一样 +listPage_profileSearch_shapingProfiles_input_itemContent_posXpath = listPage_profileSearch_dnsRecords_input_itemContent_posXpath #输入item的值,replaceName替换实际查询值 定位形式一样 +listPage_profilTable_shapingProfiles_tableTbody_posXpath = listPage_profilTable_dnsRecords_tableTbody_posXpath #列表tabel body xpath 定位形式一样 +listPage_profilTable_shapingProfiles_tableHeader_posXpath = listPage_profilTable_dnsRecords_tableHeader_posXpath #列表table 表头xpath 定位形式一样 +#listPage->Tips dialog 列表页 tips对话框 +listPage_dialogTips_shapingProfiles_button_yes_posCss = "body>.el-dialog__wrapper .delComponents-ok span" #删除提示的Tips的yes按钮 +listPage_dialogTips_shapingProfiles_button_no_posCss = "body>.el-dialog__wrapper .delComponents-close span" #删除提示的Tips的close按钮 +#Create Shaping Profile 和 Edit Shaping Profile 新增和编辑页 +shapingProfilePage_input_Name_posId = "ShapingProfile_profileName" #name输入框id +shapingProfilePage_radioButton_generic_posXpath = "//div[@id='shaping_Splitby-_ShapingProfile_write_Home_App_anonymousComponent']//span[normalize-space(text())='Generic']" #Generic单选按钮Xpath +shapingProfilePage_radioButton_fairShare_posXpath = "//div[@id='shaping_Splitby-_ShapingProfile_write_Home_App_anonymousComponent']//span[normalize-space(text())='Fair Share']" #Fair Share单选按钮iXpath +shapingProfilePage_radioButton_splitBy_posXpath = "//div[@id='shaping_Splitby-_ShapingProfile_write_Home_App_anonymousComponent']//span[normalize-space(text())='Split By']" #Split By单选按钮Xpath +shapingProfilePage_radioButton_maxMinHostFairness_posXpath = "//div[@id='shaping_Splitby-_ShapingProfile_write_Home_App_anonymousComponent']//span[normalize-space(text())='Max Min Host Fairness']" #Max Min Host Fairness单选按钮Xpath +shapingProfilePage_radioButton_localHost_posXpath = "//div[@id='shaping_Splitby-_ShapingProfile_write_Home_App_anonymousComponent']//span[normalize-space(text())='Local Host']" #Host Fairness单选按钮Xpath +shapingProfilePage_inputSelect_unit_posId = "ShapingProfile-DirectionValue" #unit单位输入选择框id +shapingProfilePage_drowDown_unitItem_posXpath = "//div[contains(@class, 'el-select-dropdown')]//li//span[normalize-space(text())='{replaceName}']" #unit的下拉item定位,replaceName替换实际查询值 +shapingProfilePage_input_incoming_posId = "ShapingProfile-Incoming" #incoming输入框 id +shapingProfilePage_input_outgoing_posId = "ShapingProfile-Outgoing" #outgoing输入框 id +shapingProfilePage_button_warningSaveYes_posCss = dnsRecordsProfilePage_button_warningSaveYes_posCss #提示保存警告框 +shapingProfilePage_button_oK_posCss = "#runScriptOk1 span" #OK按钮css +shapingProfilePage_button_cancel_posCss = "#runScriptCancel1 span" #Cancel
\ No newline at end of file diff --git a/results/screenshot/2023-11-02-19-27-12.png b/results/screenshot/2023-11-02-19-27-12.png Binary files differnew file mode 100644 index 00000000..f929d2e8 --- /dev/null +++ b/results/screenshot/2023-11-02-19-27-12.png diff --git a/results/screenshot/2023-11-03-09-45-41.png b/results/screenshot/2023-11-03-09-45-41.png Binary files differnew file mode 100644 index 00000000..298ec851 --- /dev/null +++ b/results/screenshot/2023-11-03-09-45-41.png diff --git a/results/screenshot/2023-11-03-09-47-56.png b/results/screenshot/2023-11-03-09-47-56.png Binary files differnew file mode 100644 index 00000000..64dd4db5 --- /dev/null +++ b/results/screenshot/2023-11-03-09-47-56.png diff --git a/results/screenshot/2023-11-03-09-47-58.png b/results/screenshot/2023-11-03-09-47-58.png Binary files differnew file mode 100644 index 00000000..962524e6 --- /dev/null +++ b/results/screenshot/2023-11-03-09-47-58.png diff --git a/results/screenshot/2023-11-03-09-49-25.png b/results/screenshot/2023-11-03-09-49-25.png Binary files differnew file mode 100644 index 00000000..3690ca17 --- /dev/null +++ b/results/screenshot/2023-11-03-09-49-25.png diff --git a/results/screenshot/2023-11-03-09-49-28.png b/results/screenshot/2023-11-03-09-49-28.png Binary files differnew file mode 100644 index 00000000..95e244f3 --- /dev/null +++ b/results/screenshot/2023-11-03-09-49-28.png diff --git a/results/screenshot/2023-11-03-11-48-06.png b/results/screenshot/2023-11-03-11-48-06.png Binary files differnew file mode 100644 index 00000000..8bdee02c --- /dev/null +++ b/results/screenshot/2023-11-03-11-48-06.png diff --git a/results/screenshot/2023-11-03-14-27-31.png b/results/screenshot/2023-11-03-14-27-31.png Binary files differnew file mode 100644 index 00000000..d733ddcd --- /dev/null +++ b/results/screenshot/2023-11-03-14-27-31.png diff --git a/results/screenshot/2023-11-03-14-47-01.png b/results/screenshot/2023-11-03-14-47-01.png Binary files differnew file mode 100644 index 00000000..6fb073ec --- /dev/null +++ b/results/screenshot/2023-11-03-14-47-01.png diff --git a/results/screenshot/2023-11-03-18-09-46.png b/results/screenshot/2023-11-03-18-09-46.png Binary files differnew file mode 100644 index 00000000..f6d63b71 --- /dev/null +++ b/results/screenshot/2023-11-03-18-09-46.png diff --git a/results/screenshot/2023-11-03-18-10-48.png b/results/screenshot/2023-11-03-18-10-48.png Binary files differnew file mode 100644 index 00000000..d7ff1286 --- /dev/null +++ b/results/screenshot/2023-11-03-18-10-48.png diff --git a/temp/tess1.py b/temp/tess1.py new file mode 100644 index 00000000..cc02472c --- /dev/null +++ b/temp/tess1.py @@ -0,0 +1,16 @@ +a = "172.16.70.1" + +for i in range(1, 256): + a = "172.16.71.{}/index*".format(i) + print(a) + + +b = "http://www.yumi.com/\n" +#print(b*30) + +c = "kafka-operation.sh consumer-begin OBJECT-STATISTICS-METRIC" +d = "kafka-operation.sh comsumer-begin OBJECT-STATISTICS-METRIC" + +print(c == d) + +print("ssds{}".format([12,233,44]))
\ No newline at end of file diff --git a/temp/test4.py b/temp/test4.py new file mode 100644 index 00000000..d325049e --- /dev/null +++ b/temp/test4.py @@ -0,0 +1,124 @@ +import requests +import json +a = """ +191053 +191053 +191061 +191061 +191069 +191069 +191077 +191077 +191101 +191101 +191109 +191109 +191117 +191117 +191125 +191125 +191133 +191133 +191141 +191141 +191149 +191149 +191157 +191157 +191165 +191165 +191173 +191173 +191181 +191181 +191189 +191189 +191197 +191197 +191205 +191205 +191213 +191213 +191221 +191221 +191229 +191229 +191237 +191237 +191245 +191245 +191253 +191253 +191261 +191261 +191269 +191269 +191277 +191277 +191293 +191293 +191301 +191301 +191311 +191311 +191317 +191317 +191325 +191325 +191333 +191333 +191341 +191341 +191349 +191349 +191357 +191357 +191365 +191365 +191373 +191373 +191381 +191381 +191391 +191391 +191409 +191409 +191413 +191413 +191421 +191421 +191429 +191429""" +#print(a) +b = a.split() +c = ",".join(b) +#print(b) +#print(c) + +req_header = { + "Content-Type":"application/x-www-form-urlencoded" +} +data = { + "username": "zcw", + "password": "rmj7HMJYgTq9KlZyhOGj4Q==" +} +r_login = requests.post(url="http://192.168.44.72/v1/user/login", headers=req_header, data=data) + +token = r_login.json()["data"]["token"] +print(token) + +del_header = { + "Content-Type": "application/json", + "Authorization": token +} +del_data_json = { + "refuseCode": "true", + "objectIds": b, + "objectType": "apn", + "vsysId": 1 +} +del_data = json.dumps(del_data_json) + +r_del = requests.delete(url="http://192.168.44.72/v1/policy/object", headers=del_header, data=del_data) +print(r_del.status_code) +print(r_del.text)
\ No newline at end of file diff --git a/testdata/demo1_data.json b/testdata/demo1_data.json new file mode 100644 index 00000000..0dfde25f --- /dev/null +++ b/testdata/demo1_data.json @@ -0,0 +1,15 @@ +{ + "item": + [ + { + "a": 1, + "b": 2, + "expect": 3 + }, + { + "a": 3, + "b": 4, + "expect": 7 + } + ] +} diff --git a/testdata/json_data.json b/testdata/json_data.json new file mode 100644 index 00000000..ffdd918f --- /dev/null +++ b/testdata/json_data.json @@ -0,0 +1,31 @@ +{ + "item": + [ + { + "request": + { + "url": "http://192.168.44.72/v1/user/login", + "body": + { + "id":"111", + "username": "zcw", + "password": "Gg1Etyh7fs1y/v/K2XOJDg==" + } + }, + "response":"true" + }, + { + "request": + { + "url": "http://192.168.44.72/v1/user/login", + "body": + { + "id":"222", + "username": "zcw3", + "password": "Gg1Etyh7fs1y/v/K2XOJDg==" + } + }, + "response":"true" + } + ] +}
\ No newline at end of file diff --git a/testdata/ui_data/__init__.py b/testdata/ui_data/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/testdata/ui_data/__init__.py diff --git a/testdata/ui_data/profiles_data/DoS_detection_profiles.json b/testdata/ui_data/profiles_data/DoS_detection_profiles.json new file mode 100644 index 00000000..bc969470 --- /dev/null +++ b/testdata/ui_data/profiles_data/DoS_detection_profiles.json @@ -0,0 +1,16 @@ +{ + "comment": "shaping_profiles参数注解:item中为参数驱动测试,model可选为modify。'->'为创建修改数据分隔符,前为创建数据,后为修改数据。unit分隔符后为空则只创建数据,例如’bps->‘、'543->'。unit分隔符后非空,修改数据。544->表示不修改、654->456表示修改前后数据。", + "item": + [ + { + "ids": "创建Generic_bps用例", + "model": "create", + "attack_type": "DNS Flood->", + "target_IPs": [ + "1.1.1.1->" + ], + "packet_second": "0->", + "bits_second": "0->" + } + ] +} diff --git a/testdata/ui_data/profiles_data/__init__.py b/testdata/ui_data/profiles_data/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/testdata/ui_data/profiles_data/__init__.py diff --git a/testdata/ui_data/profiles_data/dns_records.json b/testdata/ui_data/profiles_data/dns_records.json new file mode 100644 index 00000000..801ac7b7 --- /dev/null +++ b/testdata/ui_data/profiles_data/dns_records.json @@ -0,0 +1,184 @@ +{ + "comment": "dns_records参数注解:item中为参数驱动测试,model可选为create、modify。type可选为A、AAAA、CNAME 。如果model=modify,例如:modify.'12.12.12.12->34.45.67.54'表示修改前后数据,'->'为前后数据分隔符。在修改中,分隔符前为空表示新增数据。分隔符后为空表示删除数据。其它同理。", + "item": + [ + { + "ids": "创建单个类型A用例", + "model": "create", + "type": "A", + "values": + [ + "45.23.122.223" + ], + "description": "test-description45.23.122.223" + }, + { + "ids": "创建单个类型A再修改为A用例", + "model": "modify", + "type": "A->A", + "values": + [ + "145.223.172.243->32.124.176.43" + ], + "description": "test-description32.124.176.43" + }, + { + "ids": "创建多个类型A用例", + "model": "create", + "type": "A", + "values": + [ + "2.2.2.2", + "3.3.3.3", + "4.4.4.4" + ], + "description": "test-description" + }, + { + "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" + }, + { + "ids": "创建单个类型AAAA用例", + "model": "create", + "type": "AAAA", + "values": + [ + "32:12aa::34cd" + ], + "description": "test-32:12aa::34cd" + }, + { + "ids": "创建单个类型AAAA,再修改为AAAA用例", + "model": "modify", + "type": "AAAA->AAAA", + "values": + [ + "32:12aa::34cd->1231:3452:5643::aa" + ], + "description": "test-1231:3452:5643::aa" + }, + { + "ids": "创建多个类型AAAA用例", + "model": "create", + "type": "AAAA", + "values": + [ + "32:12aa::34cd", + "4265:5688:3345::4325:4456", + "1234::3456:53aa" + ], + "description": "test-sa14265:5688:3345::4325:4456" + }, + { + + "ids": "创建多类型AAAA,再修改为AAAA用例", + "model": "modify", + "type": "AAAA->AAAA", + "values": + [ + "3322:12aa::34cd->1231:3452:5643::aa", + "3252:123a::347d->", + "3352:127a::844d->1231:3752:9643::86aa", + "->1431:7652:5333::64aa" + ], + "description": "test-ssa1231:3752:9643::86aa" + }, + { + "ids": "创建单个类型CNAME用例", + "model": "create", + "type": "CNAME", + "values": + [ + "test.sds.asd.com" + ], + "description": "test-test.sds.asd.com" + }, + { + "ids": "创建单个类型CNAME,再修改为CNAME用例", + "model": "modify", + "type": "CNAME->CNAME", + "values": + [ + "test.sttds.adssd.com->test.sda.ddss.gec.cn" + ], + "description": "test-test.sda.ddss.gec.cn" + }, + { + "ids": "创建多个类型CNAME用例", + "model": "create", + "type": "CNAME", + "values": + [ + "test.sttds.adssd.com", + "test.sttsdssds.addfeessd.com", + "test.sttee2wads.adsssssd.com" + ], + "description": "test-sa1test.sttee2wads.adsssssd.com" + }, + { + "ids": "创建多类型CNAME,再修改为CNAME用例", + "model": "modify", + "type": "CNAME->CNAME", + "values": + [ + "->test.sddsg.sdsssdd.fco.cn", + "test.ssdsdssds.addsd.com->test.sdgoc.sdwa.caom.com", + "->test.sddsg.sdsd.fcfgo.cn", + "test.sassdo.caom.com->", + "test.sdoas.comada.com->test.sodmao.asdo.com", + "->test.sddsg.sdsd.fco.cn" + ], + "description": "test-est.sddsg.sdsd.fco.cn" + }, + { + "ids": "创建多类型A,再修改为CNAME用例", + "model": "modify", + "type": "A->CNAME", + "values": + [ + "112.12.32.12->test.sdgoc.sdwa.caom.com", + "53.23.234.21->", + "12.12.33.45->test.sodmao.asdo.com", + "->test.sddsg.sdsd.fco.cn" + ], + "description": "12.12.33.45->test.sodmao.asdo.com" + }, + { + "ids": "创建多类型CNAME,再修改为CNAME用例", + "model": "modify", + "type": "AAAA->CNAME", + "values": + [ + "42::4532:2234->test.sdgoc.sdwa.caom.com", + "5342:5322:3234::3213->", + "aa11:3214::4521->test.sodmao.asdo.com", + "->test.sddsg.sdsd.fco.cn" + ], + "description": "test-aa11:3214::4521->test.sodmao.asdo.com" + }, + { + "ids": "创建多类型CNAME,再修改为A用例", + "model": "modify", + "type": "CNAME->A", + "values": + [ + "test.ssdsdssds.addsd.com->23.42.234.12", + "test.sassdo.caom.com->", + "test.sdoas.comada.com->53.65.156.176", + "->12.45.168.123" + ], + "description": "test-est.test.sdoas.comada.com->53.65.156.176" + } + ] +} diff --git a/testdata/ui_data/profiles_data/hijack_files.json b/testdata/ui_data/profiles_data/hijack_files.json new file mode 100644 index 00000000..d65f9b0c --- /dev/null +++ b/testdata/ui_data/profiles_data/hijack_files.json @@ -0,0 +1,49 @@ +{ + "comment": "标识符'->'参数注解:model可选参数create、modify。标识符'->'为前后数据分隔符,分隔符前为创建数据,后为修改数据。例如:16->7:表示创建及修改;18->不修改:表示只创建不修改;18->删除:表示删除;->18:表示修改为新增(创建时不输入)", + "comment2": "1.file:文件名称。2.download_name in (Mirror Server Response, 或者其它输入内容)。3.file_type in (gif,jpeg,png,svg+xml,exe,apk,html)", + "item": + [ + { + "ids": "创建gif类型hijack_files数据", + "model": "create", + "file": "test_gif_1.gif->", + "download_name": "Mirror Server Response->", + "file_type": "gif->" + }, + { + "ids": "创建gif类型hijack_files数据再修改数据gif数据", + "model": "modify", + "file": "test_gif_1.gif->test_gif_2.gif", + "download_name": "test_gif_1.gif->Mirror Server Response", + "file_type": "gif->不修改" + }, + { + "ids": "创建jpeg类型hijack_files数据", + "model": "create", + "file": "test_jpeg_1.jpeg->", + "download_name": "test_jpeg_1.jpeg->", + "file_type": "jpeg->" + }, + { + "ids": "创建png类型hijack_files数据再修改数据svg+xml数据", + "model": "modify", + "file": "test_png_1.png->test_svg_1.svg", + "download_name": "test_png_1.gif->name_test_svg_1.svg", + "file_type": "png->svg+xml" + }, + { + "ids": "创建exe类型hijack_files数据", + "model": "create", + "file": "test_exe_1.exe->", + "download_name": "test_name_exe_1.exe->", + "file_type": "exe->" + }, + { + "ids": "创建apk类型hijack_files数据再修改数据html数据", + "model": "modify", + "file": "test_apk_1.apk->test_html_1.html", + "download_name": "Mirror Server Response->不修改", + "file_type": "apk->html" + } + ] +} diff --git a/testdata/ui_data/profiles_data/insert_scripts.json b/testdata/ui_data/profiles_data/insert_scripts.json new file mode 100644 index 00000000..fab53d86 --- /dev/null +++ b/testdata/ui_data/profiles_data/insert_scripts.json @@ -0,0 +1,21 @@ +{ + "comment": "标识符'->'参数注解:model可选参数create、modify。标识符'->'为前后数据分隔符,分隔符前为创建数据,后为修改数据。例如:16->7:表示创建及修改;18->不修改:表示只创建不修改;18->删除:表示删除;->18:表示修改为新增(创建时不输入)", + "comment2": "1.script:文件名称。2.script_type in (js, css)。3.insert_position in (After Page Load, Before Page Load)", + "item": + [ + { + "ids": "创建js类型insert_files数据11", + "model": "create", + "script": "test_js_1.js->", + "script_type": "js->", + "insert_position": "After Page Load->" + }, + { + "ids": "创建css类型css数据22", + "model": "create", + "script": "test_css_1.css->", + "script_type": "css->", + "insert_position": "->" + } + ] +} diff --git a/testdata/ui_data/profiles_data/response_pages.json b/testdata/ui_data/profiles_data/response_pages.json new file mode 100644 index 00000000..606a0f17 --- /dev/null +++ b/testdata/ui_data/profiles_data/response_pages.json @@ -0,0 +1,17 @@ +{ + "comment": "Resposne_pages参数注解,model可选参数create、modify。file中'->'为前后数据分隔符,分隔符前为创建数据,后为修改数据。例如:testa.html->表示只创建数据、testa.html->testb.html表示创建和修改数据。", + + "item": + [ + { + "ids": "创建respose_page文件11", + "model": "create", + "file": "testa.html->" + }, + { + "ids": "创建respose_page文件再修改", + "model": "modify", + "file": "testa.html->testb.html" + } + ] +} diff --git a/testdata/ui_data/profiles_data/shaping_profiles.json b/testdata/ui_data/profiles_data/shaping_profiles.json new file mode 100644 index 00000000..d94dc3fa --- /dev/null +++ b/testdata/ui_data/profiles_data/shaping_profiles.json @@ -0,0 +1,69 @@ +{ + "comment": "shaping_profiles参数注解:item中为参数驱动测试,model可选为modify。'->'为创建修改数据分隔符,前为创建数据,后为修改数据。unit分隔符后为空则只创建数据,例如’bps->‘、'543->'。unit分隔符后非空,修改数据。544->表示不修改、654->456表示修改前后数据。", + "item": + [ + { + "ids": "创建Generic_bps用例", + "model": "create", + "type": "Generic", + "argument": "", + "unit": "bps->", + "incoming": "0->", + "outgoing": "0->" + }, + { + "ids": "创建Generic_bps用例", + "model": "create", + "type": "Generic", + "argument": "", + "unit": "bps->", + "incoming": "876->", + "outgoing": "543->" + }, + { + "ids": "创建Fair_Share_Kbps用例", + "model": "create", + "type": "Fair Share", + "argument": "Max Min Host Fairness", + "unit": "Kbps->", + "incoming": "345->", + "outgoing": "678->" + }, + { + "ids": "创建Split_By_Mbps用例", + "model": "create", + "type": "Split By", + "argument": "Local Host", + "unit": "Mbps->", + "incoming": "678->", + "outgoing": "565->" + }, + { + "ids": "创建Generic_Gbps再修改为bps带宽", + "model": "modify", + "type": "Generic", + "argument": "", + "unit": "Gbps->bps", + "incoming": "500->876", + "outgoing": "800->543" + }, + { + "ids": "创建Fair_Share_bps再修改为Gps带宽", + "model": "modify", + "type": "Fair Share", + "argument": "Max Min Host Fairness", + "unit": "bps->Gbps", + "incoming": "670->856", + "outgoing": "550->543" + }, + { + "ids": "创建Split_By_Mps再修改为Mps带宽", + "model": "modify", + "type": "Split By", + "argument": "Local Host", + "unit": "Mbps->Mbps", + "incoming": "640->576", + "outgoing": "250->533" + } + ] +} diff --git a/testdata/ui_data/profiles_data/ssl_decryption_keyrings.json b/testdata/ui_data/profiles_data/ssl_decryption_keyrings.json new file mode 100644 index 00000000..01623df2 --- /dev/null +++ b/testdata/ui_data/profiles_data/ssl_decryption_keyrings.json @@ -0,0 +1,63 @@ +{ + "comment": "标识符'->'参数注解:model可选参数create、modify。标识符'->'为前后数据分隔符,分隔符前为创建数据,后为修改数据。例如:16->7:表示创建及修改;18->不修改:表示只创建不修改", + "comment2": "可选值参考certificate和private_key为文件名称。private_key=‘HSM-***’表示选择HSM格式,private_key=‘PKF-***’上次key文件名称。reissue_expiry_hours=‘MSC’表示默认时间,reissue_expiry_hours=‘C-***表示自定义时间’", + "comnent3": "可选值参考:type in (Root-Certificate,Intermediate-Certificate,End-entity)。 public_key_algorithm in (RSA-1024,RSA-2048,SECP-256r1,SECP-384r1)。 include_root in (on,off)", + "item": + [ + { + "ids": "创建root_根证书PKA设置为RSA-20481", + "model": "create", + "certificate": "test_root_cert_catest.cer->", + "private_key": "PKF-test_root_key_catest.key->", + "reissue_expiry_hours": "MSC->", + "type": "Root-Certificate->", + "public_key_algorithm": "RSA-2048->", + "certificate_revocation_list": "http://www.example.ABCD.com->", + "include_root": "off->" + }, + { + "ids": "创建root_根证书PKA设置为RSA-2048只修改PKA为SECP-384r1", + "model": "modify", + "certificate": "test_root_cert_catest.cer->不修改", + "private_key": "PKF-test_root_key_catest.key->不修改", + "reissue_expiry_hours": "MSC->不修改", + "type": "Root-Certificate->不修改", + "public_key_algorithm": "RSA-2048->SECP-384r1", + "certificate_revocation_list": "http://www.example.ABCD.com->不修改", + "include_root": "on->off" + }, + { + "ids": "创建root_根证书PKA设置为RSA-2048再修改为中间证书PKA设置为RSA-10243", + "model": "modify", + "certificate": "test_root_cert_catest.cer->test_mid_cert_camiddletest.chain.pem", + "private_key": "PKF-test_root_key_catest.key->PKF-test_mid_key_camiddletest.key", + "reissue_expiry_hours": "MSC->C-120", + "type": "Root-Certificate->Intermediate-Certificate", + "public_key_algorithm": "RSA-2048->RSA-1024", + "certificate_revocation_list": "->不修改", + "include_root": "on->off" + }, + { + "ids": "创建mid_中间书PKA设置为SECP-256r1再修改为实体证书PKA设置为SECP-384r1", + "model": "modify", + "certificate": "test_mid_cert_camiddletest.chain.pem->test_end_cert_caentitytest.chain.pem", + "private_key": "PKF-test_mid_key_camiddletest.key->PKF-test_end_keycaentitytest.key", + "reissue_expiry_hours": "C400->C-320", + "type": "Intermediate-Certificate->End-entity", + "public_key_algorithm": "SECP-256r1->SECP-384r1", + "certificate_revocation_list": "http://www.example.ABCD.cn.cmo->http://www.TESTAA.abcd.cn.cmo", + "include_root": "on->off" + }, + { + "ids": "创建mid_中间证书PKA设置为SECP-256r1私钥为HSM", + "model": "create", + "certificate": "test_mid_cert_camiddletest.chain.pem->", + "private_key": "HSM-453->", + "reissue_expiry_hours": "MSC->", + "type": "Intermediate-Certificate->", + "public_key_algorithm": "RSA-2048->", + "certificate_revocation_list": "http://www.www.ww->", + "include_root": "off->" + } + ] +} diff --git a/testdata/ui_data/profiles_data/ssl_decryption_profiles.json b/testdata/ui_data/profiles_data/ssl_decryption_profiles.json new file mode 100644 index 00000000..a8ab38ab --- /dev/null +++ b/testdata/ui_data/profiles_data/ssl_decryption_profiles.json @@ -0,0 +1,64 @@ +{ + "comment": "标识符'->'参数注解:model可选参数create、modify。标识符'->'为前后数据分隔符,分隔符前为创建数据,后为修改数据。例如:16->7:表示创建及修改;18->不修改:表示只创建不修改;18->删除:表示删除;->18:表示修改为新增(创建时不输入)", + "comment2": "开关的取值为:1.on、off。2.fail_action in (Fail-close,Pass-through)。3.min_client_version、max_client_version in (SSLv3.0,TLSv1.0,TLSv1.1,TLSv1.2,TLSv1.3)", + "item": + [ + { + "ids": "创建ssl_decryption_profiles_fail_action_on11", + "model": "create", + "common_name":"on->", + "issuer":"off->", + "self_signed":"off->", + "expiry_date":"on->", + "fail_action":"Pass-through->", + "ev_certificate":"on->", + "certificate_transparency":"on->", + "mutual_authentication":"on->", + "protocol_errors":"on->", + "certificate_pinning":"on->", + "certificate_not_installed":"on->", + "mirror_client_versions":"off->", + "min_client_version":"TLSv1.0->", + "max_client_version":"TLSv1.2->", + "allow_HTTP2":"off->" + }, + { + "ids": "创建ssl_decryption_profiles_fail_action_on再修改common_name_off22", + "model": "modify", + "common_name":"on->off", + "issuer":"on-off>", + "self_signed":"on->不修改", + "expiry_date":"on->不修改", + "fail_action":"Pass-through->不修改", + "ev_certificate":"on->off", + "certificate_transparency":"on->不修改", + "mutual_authentication":"on->不修改", + "protocol_errors":"on->不修改", + "certificate_pinning":"on->off", + "certificate_not_installed":"on->", + "mirror_client_versions":"off->off", + "min_client_version":"TLSv1.2->不修改", + "max_client_version":"TLSv1.3->不修改", + "allow_HTTP2":"off->on" + }, + { + "ids": "创建ssl_decryption_profiles_fail_action_on33", + "model": "create", + "common_name":"on->", + "issuer":"on->", + "self_signed":"on->", + "expiry_date":"on->", + "fail_action":"Pass-through->", + "ev_certificate":"off->", + "certificate_transparency":"off->", + "mutual_authentication":"on->", + "protocol_errors":"on->", + "certificate_pinning":"on->", + "certificate_not_installed":"off->", + "mirror_client_versions":"on->", + "min_client_version":"TLSv1.0->", + "max_client_version":"TLSv1.2->", + "allow_HTTP2":"on->" + } + ] +} diff --git a/testdata/ui_data/profiles_data/traffic_mirroring_profiles.json b/testdata/ui_data/profiles_data/traffic_mirroring_profiles.json new file mode 100644 index 00000000..934c3a04 --- /dev/null +++ b/testdata/ui_data/profiles_data/traffic_mirroring_profiles.json @@ -0,0 +1,44 @@ +{ + "comment": "traffic mirroring profiles参数注解,model可选参数create、modify。vlan_id为列表参数,标识符'->'为前后数据分隔符,分隔符前为创建数据,后为修改数据。例如:16->7:表示创建及修改;18->:表示只创建不修改;->23:表示修改中新增", + + "item": + [ + { + "ids": "创建traffic_mirroring_profiles_多vlanid", + "model": "create", + "vlan_id": + [ + "6->", + "58->" + ] + }, + { + "ids": "创建vlanid再修改", + "model": "modify", + "vlan_id": + [ + "16->7", + "18->", + "->23", + "25->45", + "55->55" + ] + }, + { + "ids": "创建一个vlanid", + "model": "create", + "vlan_id": + [ + "35->" + ] + }, + { + "ids": "创建一个vlanid再修改", + "model": "create", + "vlan_id": + [ + "45->25" + ] + } + ] +} diff --git a/testdata/ui_file/__init__.py b/testdata/ui_file/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/testdata/ui_file/__init__.py diff --git a/testdata/ui_file/profiles/__init__.py b/testdata/ui_file/profiles/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/testdata/ui_file/profiles/__init__.py diff --git a/testdata/ui_file/profiles/hijack_files/__init__.py b/testdata/ui_file/profiles/hijack_files/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/testdata/ui_file/profiles/hijack_files/__init__.py diff --git a/testdata/ui_file/profiles/hijack_files/test_apk_1.apk b/testdata/ui_file/profiles/hijack_files/test_apk_1.apk Binary files differnew file mode 100644 index 00000000..c96c8ce8 --- /dev/null +++ b/testdata/ui_file/profiles/hijack_files/test_apk_1.apk diff --git a/testdata/ui_file/profiles/hijack_files/test_exe_1.exe b/testdata/ui_file/profiles/hijack_files/test_exe_1.exe Binary files differnew file mode 100644 index 00000000..e33f7250 --- /dev/null +++ b/testdata/ui_file/profiles/hijack_files/test_exe_1.exe diff --git a/testdata/ui_file/profiles/hijack_files/test_gif_1.gif b/testdata/ui_file/profiles/hijack_files/test_gif_1.gif Binary files differnew file mode 100644 index 00000000..8a8d19e6 --- /dev/null +++ b/testdata/ui_file/profiles/hijack_files/test_gif_1.gif diff --git a/testdata/ui_file/profiles/hijack_files/test_gif_2.gif b/testdata/ui_file/profiles/hijack_files/test_gif_2.gif Binary files differnew file mode 100644 index 00000000..042ac791 --- /dev/null +++ b/testdata/ui_file/profiles/hijack_files/test_gif_2.gif diff --git a/testdata/ui_file/profiles/hijack_files/test_html_1.html b/testdata/ui_file/profiles/hijack_files/test_html_1.html new file mode 100644 index 00000000..9cee60cd --- /dev/null +++ b/testdata/ui_file/profiles/hijack_files/test_html_1.html @@ -0,0 +1,185 @@ +<html> +<head> + <title>新建网页</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> + <meta name="description" content=""/> + <meta name="keywords" content=""/> + + <script type="text/javascript"> + //① 绘制地图 + function Map() { + //私有成员(不会随便发生变化) + var w = 800; + var h = 400; + + //成员方法,绘制地图 + this.showmap = function () { + //创建div、设置css样式、追加给body + var tu = document.createElement('div'); + + tu.style.width = w + "px"; + tu.style.height = h + "px"; + tu.style.backgroundImage = "url(./12.jpg)"; + + document.body.appendChild(tu); + } + } + + //② 绘制食物 + function Food() { + var len = 20; + //把食物(权值)坐标声明为公开的,以便在外部访问 + this.xFood = 0; + this.yFood = 0; + this.piece = null; //页面上唯一的食物对象 + //绘制 + this.showfood = function () { + //创建div、设置css样式、追加给body + if (this.piece === null) { + this.piece = document.createElement('div'); + this.piece.style.width = this.piece.style.height = len + "px"; + this.piece.style.backgroundColor = "green"; + this.piece.style.position = "absolute"; + + document.body.appendChild(this.piece); + } + //食物设置绝对定位(position/left/top) + //食物位置“随机”摆放 + //移动步进值:20px + //食物“权值”坐标: X轴(0-39) Y轴(0-19) + //食物真实坐标:权值坐标 * 步进值 + this.xFood = Math.floor(Math.random() * 40); //0-39的随机数 + this.yFood = Math.floor(Math.random() * 20); //0-19的随机数 + + this.piece.style.left = this.xFood * len + "px"; + this.piece.style.top = this.yFood * len + "px"; + + } + } + + //③ 小蛇 + function Snake() { + var len = 20; + this.redirect = "right"; //默认向右边移动 + //后期snakebody要变化,因此声明为公开的(每个蛇节:[x坐标,y坐标,颜色,蛇节对象]) + this.snakebody = [[0, 1, 'green', null], [1, 1, 'green', null], [2, 1, 'green', null], [3, 1, 'red', null]]; + //a.绘制小蛇 + this.showsnake = function () { + //遍历小蛇的各个蛇节,并依次创建即可 + for (var i = 0; i < this.snakebody.length; i++) { + //this.snakebody[i]//代表每个蛇节 + //创建蛇节div + if (this.snakebody[i][3] === null) {//判断没有创建对应的蛇节 + this.snakebody[i][3] = document.createElement('div'); + //设置css样式(宽度、高度、颜色) + this.snakebody[i][3].style.width = this.snakebody[i][3].style.height = len + "px"; + this.snakebody[i][3].style.backgroundColor = this.snakebody[i][2]; + //绝对定位及位置 + this.snakebody[i][3].style.position = "absolute"; + //把蛇节追加给body + document.body.appendChild(this.snakebody[i][3]); + } + this.snakebody[i][3].style.left = this.snakebody[i][0] * len + "px"; + this.snakebody[i][3].style.top = this.snakebody[i][1] * len + "px"; + } + } + + //b.移动小蛇 + this.movesnake = function () { + //非蛇头蛇节(当前蛇节的新坐标 是"下个蛇节"的旧坐标) + for (var i = 0; i < this.snakebody.length - 1; i++) { + this.snakebody[i][0] = this.snakebody[i + 1][0]; + this.snakebody[i][1] = this.snakebody[i + 1][1]; + } + if (this.redirect == "right") { + //蛇头x坐标递增 + this.snakebody[this.snakebody.length - 1][0] += 1; + } + if (this.redirect == "left") { + //蛇头x坐标递减 + this.snakebody[this.snakebody.length - 1][0] -= 1; + } + if (this.redirect == "up") { + //蛇头y坐标递减 + this.snakebody[this.snakebody.length - 1][1] -= 1; + } + if (this.redirect == "down") { + //蛇头y坐标递增 + this.snakebody[this.snakebody.length - 1][1] += 1; + } + + //判断蛇头碰到食物 + //蛇头坐标 + var xSnake = this.snakebody[this.snakebody.length - 1][0]; + var ySnake = this.snakebody[this.snakebody.length - 1][1]; + //食物坐标food.xFood/food.yFood; + if (xSnake == food.xFood && ySnake == food.yFood) { + //吃食物增加蛇节 + var newjie = [this.snakebody[0][0], this.snakebody[0][1], 'green', null]; + this.snakebody.unshift(newjie);//把newjie放到数组的第一个位置去 + + //原食物消失,重新生成一个食物 + food.showfood(); + } + + //控制小蛇在地图范围内移动 + if (xSnake < 0 || xSnake > 39 || ySnake < 0 || ySnake > 19) { + alert('game over'); + clearInterval(mytime); + return false; + } + //吃到自己判断(蛇头坐标与其他蛇节坐标一致) + for (var k = 0; k < this.snakebody.length - 1; k++) { + if (this.snakebody[k][0] == xSnake && this.snakebody[k][1] == ySnake) { + alert('game over kill you by yourself'); + clearInterval(mytime); + return false; + } + } + + //根据新坐标绘制小蛇 + this.showsnake(); + } + } + + window.onload = function () { + var map = new Map(); + map.showmap(); + + food = new Food();//声明为全局的以便在该加载事件函数外部访问 + food.showfood(); + + snake = new Snake();//声明为全局的snake对象 + snake.showsnake(); + + //移动小蛇 + //setInterval(全局变量,时间) + mytime = setInterval("snake.movesnake()", 200); + + //设置键盘事件,控制器小蛇移动方向 + document.onkeydown = function (evt) { + var num = evt.keyCode;//通过事件对象获得数值码,进而知道被触发键子 + if (num == 38) { + snake.redirect = "up"; + } + if (num == 40) { + snake.redirect = "down"; + } + if (num == 37) { + snake.redirect = "left"; + } + if (num == 39) { + snake.redirect = "right"; + } + } + } + </script> +<!-- + <style type="text/css"> + body { + margin: 0; + } + </style> --> +</head> +<body></body> +</html> diff --git a/testdata/ui_file/profiles/hijack_files/test_jpeg_1.jpeg b/testdata/ui_file/profiles/hijack_files/test_jpeg_1.jpeg Binary files differnew file mode 100644 index 00000000..c96c8ce8 --- /dev/null +++ b/testdata/ui_file/profiles/hijack_files/test_jpeg_1.jpeg diff --git a/testdata/ui_file/profiles/hijack_files/test_png_1.png b/testdata/ui_file/profiles/hijack_files/test_png_1.png Binary files differnew file mode 100644 index 00000000..76e778e0 --- /dev/null +++ b/testdata/ui_file/profiles/hijack_files/test_png_1.png diff --git a/testdata/ui_file/profiles/hijack_files/test_svg_1.svg b/testdata/ui_file/profiles/hijack_files/test_svg_1.svg Binary files differnew file mode 100644 index 00000000..e33f7250 --- /dev/null +++ b/testdata/ui_file/profiles/hijack_files/test_svg_1.svg diff --git a/testdata/ui_file/profiles/insert_scripts/__init__.py b/testdata/ui_file/profiles/insert_scripts/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/testdata/ui_file/profiles/insert_scripts/__init__.py diff --git a/testdata/ui_file/profiles/insert_scripts/test_css_1.css b/testdata/ui_file/profiles/insert_scripts/test_css_1.css new file mode 100644 index 00000000..4b928372 --- /dev/null +++ b/testdata/ui_file/profiles/insert_scripts/test_css_1.css @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>菜鸟教程(runoob.com)</title> +<style> +body { + background-color:red; +} +h1 { + color:red; + text-align:center; +} +p { + font-family:"Times New Roman"; + font-size:20px; +} +</style> +</head> + +<body> + +<h1>CSS 实例!</h1> +<p>这是一个段落。</p> + +</body> +</html>
\ No newline at end of file diff --git a/testdata/ui_file/profiles/insert_scripts/test_css_2.css b/testdata/ui_file/profiles/insert_scripts/test_css_2.css new file mode 100644 index 00000000..08fd48b5 --- /dev/null +++ b/testdata/ui_file/profiles/insert_scripts/test_css_2.css @@ -0,0 +1,3 @@ +body{ + background:red !important; +}
\ No newline at end of file diff --git a/testdata/ui_file/profiles/insert_scripts/test_js_1.js b/testdata/ui_file/profiles/insert_scripts/test_js_1.js new file mode 100644 index 00000000..4f110c37 --- /dev/null +++ b/testdata/ui_file/profiles/insert_scripts/test_js_1.js @@ -0,0 +1 @@ +alert("鎵цjavascript!");
\ No newline at end of file diff --git a/testdata/ui_file/profiles/insert_scripts/test_js_2.js b/testdata/ui_file/profiles/insert_scripts/test_js_2.js new file mode 100644 index 00000000..6e7bffe1 --- /dev/null +++ b/testdata/ui_file/profiles/insert_scripts/test_js_2.js @@ -0,0 +1 @@ +alert("Hello World");
\ No newline at end of file diff --git a/testdata/ui_file/profiles/response_pages/__init__.py b/testdata/ui_file/profiles/response_pages/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/testdata/ui_file/profiles/response_pages/__init__.py diff --git a/testdata/ui_file/profiles/response_pages/testa.html b/testdata/ui_file/profiles/response_pages/testa.html new file mode 100644 index 00000000..a490e611 --- /dev/null +++ b/testdata/ui_file/profiles/response_pages/testa.html @@ -0,0 +1,56 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + +<head> + +<meta charset="UTF-8" http-equiv="Content-Type" content="text/html; charset=utf-8" /> + +<title>404-对不起!您访问的页面不存在</title> + +<style type="text/css"> + +.head404{ width:580px; height:234px; margin:50px auto 0 auto; background:url(https://www.daixiaorui.com/Public/images/head404.png) no-repeat; } + +.txtbg404{ width:499px; height:169px; margin:10px auto 0 auto; background:url(https://www.daixiaorui.com/Public/images/txtbg404.png) no-repeat;} + +.txtbg404 .txtbox{ width:390px; position:relative; top:30px; left:60px;color:#eee; font-size:13px;} + +.txtbg404 .txtbox p {margin:5px 0; line-height:18px;} + +.txtbg404 .txtbox .paddingbox { padding-top:15px;} + +.txtbg404 .txtbox p a { color:#eee; text-decoration:none;} + +.txtbg404 .txtbox p a:hover { color:#FC9D1D; text-decoration:underline;} + +</style> + +</head> + + + +<body bgcolor="#494949"> + + <div class="head404"></div> + + <div class="txtbg404"> + + <div class="txtbox"> + + <p>对不起,您请求的页面不存在、或已被删除、或暂时不可用</p> + + <p class="paddingbox">请点击以下链接继续浏览网页</p> + + <p>》<a style="cursor:pointer" onclick="history.back()">返回上一页面</a></p> + + <p>》<a href="https://www.daixiaorui.com">返回网站首页</a></p> + + </div> + + </div> + +</body> + +</html> +</html> diff --git a/testdata/ui_file/profiles/response_pages/testb.html b/testdata/ui_file/profiles/response_pages/testb.html new file mode 100644 index 00000000..9fd8aa96 --- /dev/null +++ b/testdata/ui_file/profiles/response_pages/testb.html @@ -0,0 +1,56 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + +<head> + +<meta charset="UTF-8" http-equiv="Content-Type" content="text/html; charset=utf-8" /> + +<title>404 sorry! The page you visited does not exist</title> + +<style type="text/css"> + +.head404{ width:580px; height:234px; margin:50px auto 0 auto; background:url(https://www.daixiaorui.com/Public/images/head404.png) no-repeat; } + +.txtbg404{ width:499px; height:169px; margin:10px auto 0 auto; background:url(https://www.daixiaorui.com/Public/images/txtbg404.png) no-repeat;} + +.txtbg404 .txtbox{ width:390px; position:relative; top:30px; left:60px;color:#eee; font-size:13px;} + +.txtbg404 .txtbox p {margin:5px 0; line-height:18px;} + +.txtbg404 .txtbox .paddingbox { padding-top:15px;} + +.txtbg404 .txtbox p a { color:#eee; text-decoration:none;} + +.txtbg404 .txtbox p a:hover { color:#FC9D1D; text-decoration:underline;} + +</style> + +</head> + + + +<body bgcolor="#494949"> + + <div class="head404"></div> + + <div class="txtbg404"> + + <div class="txtbox"> + + <p>Sorry, the page you requested does not exist, has been deleted, or is temporarily unavailable</p> + + <p class="paddingbox">Please click the following link to continue browsing</p> + + <p>》<a style="cursor:pointer" onclick="history.back()">Back to previous page</a></p> + + <p>》<a href="https://www.daixiaorui.com">Back to home page</a></p> + + </div> + + </div> + +</body> + +</html> +</html> diff --git a/testdata/ui_file/profiles/response_pages/testc.html b/testdata/ui_file/profiles/response_pages/testc.html new file mode 100644 index 00000000..21d6fcdc --- /dev/null +++ b/testdata/ui_file/profiles/response_pages/testc.html @@ -0,0 +1,56 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + +<head> + +<meta charset="UTF-8" http-equiv="Content-Type" content="text/html; charset=utf-8" /> + +<title> - 404, простите! страница, к которой вы пришли, не существует </title> + +<style type="text/css"> + +.head404{ width:580px; height:234px; margin:50px auto 0 auto; background:url(https://www.daixiaorui.com/Public/images/head404.png) no-repeat; } + +.txtbg404{ width:499px; height:169px; margin:10px auto 0 auto; background:url(https://www.daixiaorui.com/Public/images/txtbg404.png) no-repeat;} + +.txtbg404 .txtbox{ width:390px; position:relative; top:30px; left:60px;color:#eee; font-size:13px;} + +.txtbg404 .txtbox p {margin:5px 0; line-height:18px;} + +.txtbg404 .txtbox .paddingbox { padding-top:15px;} + +.txtbg404 .txtbox p a { color:#eee; text-decoration:none;} + +.txtbg404 .txtbox p a:hover { color:#FC9D1D; text-decoration:underline;} + +</style> + +</head> + + + +<body bgcolor="#494949"> + + <div class="head404"></div> + + <div class="txtbg404"> + + <div class="txtbox"> + + <p> Извините, запрошенная страница не существует или была удалена или временно недоступна </p> + + <p class="paddingbox">Продолжайте просматривать страницы</p> + + <p>》<a style="cursor:pointer" onclick="history.back()">вернуться на предыдущую страницу </a></p> + + <p>》<a href="https://www.daixiaorui.com">вернуться на главную страницу сайта </a></p> + + </div> + + </div> + +</body> + +</html> +</html> diff --git a/testdata/ui_file/profiles/ssl_decryption_keyrings/__init__.py b/testdata/ui_file/profiles/ssl_decryption_keyrings/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/testdata/ui_file/profiles/ssl_decryption_keyrings/__init__.py diff --git a/testdata/ui_file/profiles/ssl_decryption_keyrings/test_end_cert_caentitytest.chain.pem b/testdata/ui_file/profiles/ssl_decryption_keyrings/test_end_cert_caentitytest.chain.pem new file mode 100644 index 00000000..730ea47b --- /dev/null +++ b/testdata/ui_file/profiles/ssl_decryption_keyrings/test_end_cert_caentitytest.chain.pem @@ -0,0 +1,93 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 72:cc:5f:e2:55:f6:e6:f6:c4:bc:7c:6b + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=CN, ST=BJ, L=BJ, O=NT, OU=NT, CN=CA TRUST1 + Validity + Not Before: Jul 7 11:39:21 2023 GMT + Not After : Nov 18 11:39:21 2024 GMT + Subject: C=CN, CN=www.bbc.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:df:ad:1c:bc:ae:44:16:8a:be:bf:eb:69:06:07: + 5e:16:35:3b:e7:41:5d:48:8b:0f:6c:38:ee:7e:97: + 0f:43:de:63:27:84:5e:65:bc:28:7c:57:f1:4c:2a: + 92:98:e2:73:33:be:39:58:f2:7a:cf:55:45:23:16: + f3:c1:e9:fd:3e:f8:a7:a2:02:c6:f1:20:ff:13:dc: + f2:0a:31:29:fc:d8:e7:90:2d:ef:8e:44:6d:65:92: + fa:3a:a2:73:99:26:ee:e8:35:6f:07:dd:2f:49:61: + 11:11:d2:fb:7a:4c:8a:b9:19:ab:e3:99:79:07:ac: + fc:dd:62:7b:7f:de:fe:ff:8b:a7:68:8c:61:f8:49: + 57:67:8d:a8:23:92:a4:3f:e5:69:0a:6a:38:e3:56: + e2:dc:d2:ac:d5:62:6e:16:9e:46:c5:f3:19:c1:85: + 95:f2:5c:99:d0:2a:a6:80:64:2c:d2:7e:06:b6:80: + fc:48:f0:fc:06:57:c0:89:17:6a:4b:06:c9:26:54: + f5:36:59:44:01:89:89:5c:8d:fb:50:d7:10:ca:bc: + 3a:76:2a:f5:fa:4d:dc:0f:bc:bc:49:e0:92:8d:1d: + 7a:33:42:52:83:dc:ce:78:59:86:31:88:c0:4f:25: + f2:4b:7b:6f:18:d8:59:fd:f4:53:1b:fd:b4:95:ad: + 99:d3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:*.bbc.com, DNS:*.bbc.cn + Signature Algorithm: sha256WithRSAEncryption + ba:a0:a4:49:aa:7f:04:9d:eb:df:c1:c6:27:27:2e:52:c1:3a: + 1d:31:73:be:37:d7:17:6e:7f:1d:ca:f6:f8:24:bb:40:e2:08: + aa:13:84:5e:94:c0:e0:7c:80:f2:75:91:2c:cf:b2:31:9c:38: + bf:45:63:81:7c:20:60:d0:23:cf:0c:ca:14:41:b4:95:a0:e2: + 8f:b7:b8:e9:cb:2e:69:19:f0:53:c6:8f:96:1c:94:bd:41:c2: + d6:81:6e:1f:84:45:00:fa:7c:5a:39:3e:fa:14:6d:75:bf:d9: + ad:c9:85:58:10:24:3a:38:2a:85:90:a2:0b:58:06:7d:c8:2f: + 4a:b8:31:92:8e:c8:3d:21:9d:f6:74:2f:29:57:b2:7b:ee:8e: + 90:47:34:69:54:34:af:93:e3:cf:3a:31:56:40:20:03:61:ec: + 38:49:5b:e9:5a:e4:23:41:6e:f1:33:64:7f:d6:44:96:7b:e8: + 14:79:bf:5e:34:03:d0:63:a0:06:bb:c7:b0:24:8b:87:c6:df: + 5e:24:54:2e:35:05:88:f4:36:12:3d:76:8b:92:8f:95:e9:9c: + 14:39:0e:8f:e4:50:70:f6:f7:cf:24:01:7b:30:7d:33:43:b0: + 20:e1:1c:93:64:15:66:f2:4f:b0:2b:ae:48:18:67:fc:86:fa: + b8:f2:5b:ec +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIMcsxf4lX25vbEvHxrMA0GCSqGSIb3DQEBCwUAMFUxCzAJ +BgNVBAYTAkNOMQswCQYDVQQIDAJCSjELMAkGA1UEBwwCQkoxCzAJBgNVBAoMAk5U +MQswCQYDVQQLDAJOVDESMBAGA1UEAwwJQ0EgVFJVU1QxMB4XDTIzMDcwNzExMzky +MVoXDTI0MTExODExMzkyMVowIzELMAkGA1UEBhMCQ04xFDASBgNVBAMMC3d3dy5i +YmMuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA360cvK5EFoq+ +v+tpBgdeFjU750FdSIsPbDjufpcPQ95jJ4ReZbwofFfxTCqSmOJzM745WPJ6z1VF +Ixbzwen9PvinogLG8SD/E9zyCjEp/NjnkC3vjkRtZZL6OqJzmSbu6DVvB90vSWER +EdL7ekyKuRmr45l5B6z83WJ7f97+/4unaIxh+ElXZ42oI5KkP+VpCmo441bi3NKs +1WJuFp5GxfMZwYWV8lyZ0CqmgGQs0n4GtoD8SPD8BlfAiRdqSwbJJlT1NllEAYmJ +XI37UNcQyrw6dir1+k3cD7y8SeCSjR16M0JSg9zOeFmGMYjATyXyS3tvGNhZ/fRT +G/20la2Z0wIDAQABoyIwIDAeBgNVHREEFzAVggkqLmJiYy5jb22CCCouYmJjLmNu +MA0GCSqGSIb3DQEBCwUAA4IBAQC6oKRJqn8EnevfwcYnJy5SwTodMXO+N9cXbn8d +yvb4JLtA4giqE4RelMDgfIDydZEsz7IxnDi/RWOBfCBg0CPPDMoUQbSVoOKPt7jp +yy5pGfBTxo+WHJS9QcLWgW4fhEUA+nxaOT76FG11v9mtyYVYECQ6OCqFkKILWAZ9 +yC9KuDGSjsg9IZ32dC8pV7J77o6QRzRpVDSvk+PPOjFWQCADYew4SVvpWuQjQW7x +M2R/1kSWe+gUeb9eNAPQY6AGu8ewJIuHxt9eJFQuNQWI9DYSPXaLko+V6ZwUOQ6P +5FBw9vfPJAF7MH0zQ7Ag4RyTZBVm8k+wK65IGGf8hvq48lvs +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDfTCCAmWgAwIBAgIJAJnxzpEq+vIfMA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNV +BAYTAkNOMQswCQYDVQQIDAJCSjELMAkGA1UEBwwCQkoxCzAJBgNVBAoMAk5UMQsw +CQYDVQQLDAJOVDESMBAGA1UEAwwJQ0EgVFJVU1QxMB4XDTIzMDcwNzExMjk1NVoX +DTI0MTExODExMjk1NVowVTELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkJKMQswCQYD +VQQHDAJCSjELMAkGA1UECgwCTlQxCzAJBgNVBAsMAk5UMRIwEAYDVQQDDAlDQSBU +UlVTVDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDO+4rZA65F6tlt +HEnbFG56FyYs/V9XAM6sSSnnFj8H8MNvxiRQXlaevdK8/7xwtN3udX+x4VdSnmi4 +wPGLhrPWvrrv2ZrDbRlBwNmIosmE+dQdqf9OyN44Pw4/TQoh14CWqjqxQXYLevrn +45GH1POUR64U6qO5Uq5B83zimTRWTbXertvrYb4plOKNxvav3IKdNEufRJSqxelf +AUMQnsrH1iO4iMpZHBYSNbfwl6gkgnXxsr8YTZrrQwk9Bcd/0bFQ+v3OiWD5oiYc +XfcIBTeoy6IIICNc7krfnXRpsXO2oimNgMS6nHPKvXYF5jTbKr0A40ElDEIjtt5T +Yb4oWNHfAgMBAAGjUDBOMB0GA1UdDgQWBBSD6d3VXldZQOiVGZC0Y3nuANvG2zAf +BgNVHSMEGDAWgBSD6d3VXldZQOiVGZC0Y3nuANvG2zAMBgNVHRMEBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4IBAQCM3XHUZ1RwpLtF5DpEKDmC4osIiguk7ENF7Bg+LCQt +GzIeBkHPZ0sKbqZr0og6a0r0Qn1Xzr5nku9cuFH1Gc9Wwg82i8zXLgD8//VSNy5k +SLKb7MiAAnUHv6ZkluX8X9bdg32vb+sTwhuFhjbI5LVWvY3dq/Ez+WERFUxgNL3s +dgiJABkslbkjobgB39m/Lr223P6HwG5n6YukKSmwfiion5QYsTbTpd9AYbAD5UTs +A5H5pRdk/mxJ7yYsgosu60wAUI/xVAVvsaUDGa+koiVKPhUg4A7Qd/2oDByb/H9J +atqHkSjkwvhAekC0mOjKh6ED/Nr2tnN5l0GIbwRvj9Xz +-----END CERTIFICATE----- diff --git a/testdata/ui_file/profiles/ssl_decryption_keyrings/test_end_keycaentitytest.key b/testdata/ui_file/profiles/ssl_decryption_keyrings/test_end_keycaentitytest.key new file mode 100644 index 00000000..7683dbe3 --- /dev/null +++ b/testdata/ui_file/profiles/ssl_decryption_keyrings/test_end_keycaentitytest.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEA360cvK5EFoq+v+tpBgdeFjU750FdSIsPbDjufpcPQ95jJ4Re +ZbwofFfxTCqSmOJzM745WPJ6z1VFIxbzwen9PvinogLG8SD/E9zyCjEp/NjnkC3v +jkRtZZL6OqJzmSbu6DVvB90vSWEREdL7ekyKuRmr45l5B6z83WJ7f97+/4unaIxh ++ElXZ42oI5KkP+VpCmo441bi3NKs1WJuFp5GxfMZwYWV8lyZ0CqmgGQs0n4GtoD8 +SPD8BlfAiRdqSwbJJlT1NllEAYmJXI37UNcQyrw6dir1+k3cD7y8SeCSjR16M0JS +g9zOeFmGMYjATyXyS3tvGNhZ/fRTG/20la2Z0wIDAQABAoIBAFqQNe1zRaA25wq/ +3xMQ0ph9T1bP0Vw46bKwzme08/pPxafPYYUhjObjmJB1QEvkjC5sG74W14CxDsAp +X+Kowd/IP99J7pDdAkphkCJuS4jTrdZjsvXQYNbajrRE6DcfW2XrlJwDg0zbn1Sv +LyEScqyFZ2JM1oM0GGHuqQBaIrcGa6c8LgtaxmgVKMGA5EbSL86eZ8s0UNwiQs8Y +U1GLrb0ecxJxjI7qHkj3e6bzfJ84P+EA97ZwnSEx2xV9ceMYfzo/nUKFo6BZo9Qy +S1vBbHCs6Pv+1jg5rObI4F+w3Q1xkXDtOo8iGsFjIYvAXVw8k8DeI6hgI1OhF8I1 +Xz/azMkCgYEA8N5JE/u8SVZCfvaHj+e2Orlll+hTvI9GWu7lLYEVd9vdfri31n7v +hHrcV98JqSBVPiKO78H29kSYWfmLRGMWKHInFfdVmuEOi7Xq3b4yIUk+y308A4qo +Wx5JppQQ7Ej/9+lO+AF1ru1x4qsvY+XlmfC9l3zYy9G2+TIKe1kzV1UCgYEA7bpW +tA2ocmeCUWP69dxXwLihsrAMkyIww7DWZHcE2tTH1YxfRdQM4AxrlO2st2aDcP6G +P74cF6ooyeijZS3825rnZpxdpIjic0k/MwJnkyD2Rf16qXhvvu82pA46uyZ2TBfk +Z5kFJw2pC6maNhg2OZCHNlWj2Qprr2EdzcdYXIcCgYBvWNK/gifQXyfuOVkBlUQQ +cZQdXTEYgcMsVjNrjbi259TEt++EILnorEMf++MjY+cECkW5YBkiTyN+tHVE7+lW +WS7oYKYaKt/mhfpE95+E868rsoEDwh2BwcaaUuhf0n9Bw4DV9RbJ/soe1rPZonU5 +bKi4VuaBkjjbid5+lwW84QKBgEB1aBEGKwhqPJGpFGEZz8l3xpBW3/H9MU++YUN4 +ah6T12N13ldmud7+PyVwlIZeC4HV4bzi5WcdQlYM+FD0+TzqcZgHCfUVEKHF2JcS +Lddc9qnfoyTUfSg+YIh3O0GHmkfjqpDUkusV7yI0aJYGVp2hLKh07CprgutY3+Xu +CW19AoGAZzRkQeqrdwLEHOMY4p0GNrwDnubfwBzjEHWt3tBCgRQjPiwpdtXIdXgk +LDc2ZRUMw38JDELQ/BnzhXZa7JKJJJY6mNFTP/mUiGW959C8axE8csiPbIbQopY2 +wseDiyumC8r2wkhUfFST115LoShLeK/ZoiIA2ThWxCdbm/1PHVg= +-----END RSA PRIVATE KEY----- diff --git a/testdata/ui_file/profiles/ssl_decryption_keyrings/test_mid_cert_camiddletest.chain.pem b/testdata/ui_file/profiles/ssl_decryption_keyrings/test_mid_cert_camiddletest.chain.pem new file mode 100644 index 00000000..c13ccf89 --- /dev/null +++ b/testdata/ui_file/profiles/ssl_decryption_keyrings/test_mid_cert_camiddletest.chain.pem @@ -0,0 +1,100 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 71:d9:ff:18:5a:34:cc:9f:ee:60:0b:bd + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=CN, ST=BJ, L=BJ, O=NT, OU=NT, CN=CA TRUST1 + Validity + Not Before: Jul 7 11:30:01 2023 GMT + Not After : Nov 18 11:30:01 2024 GMT + Subject: C=CN, ST=BJ, O=NT, OU=NT, CN=camiddle1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:cb:5a:af:94:d2:6a:98:91:f1:13:6e:95:9e:ed: + 50:96:85:0e:8e:0b:fd:7f:f2:20:b6:88:27:34:91: + 9f:b3:c4:27:43:e4:e9:44:80:fd:e2:51:67:d7:f8: + 9b:17:16:2c:36:7e:f4:75:29:63:40:ec:9b:29:a7: + 4e:a2:d9:e1:ca:1a:51:62:43:5e:af:55:8a:64:b5: + 76:ba:a4:78:d6:87:fa:d6:a1:cb:08:67:69:0c:ec: + 5a:d9:7b:78:6f:28:d3:1b:14:63:ee:bd:47:92:e1: + 57:18:33:bc:99:ba:2f:82:cd:45:15:b2:bd:13:fa: + 51:38:bb:2b:68:11:0a:a4:b9:18:88:70:56:5f:89: + e1:10:21:79:e9:b1:f4:15:8b:74:10:6f:d8:36:9e: + 60:4c:1d:61:63:52:7b:b7:3d:63:8b:65:b3:2f:ed: + e7:d4:b5:39:15:32:52:d3:73:ea:c4:85:53:45:ea: + 5a:77:67:4c:3c:bb:0a:b8:0b:63:69:39:38:d3:61: + 78:16:10:48:e6:40:bf:1a:a9:9b:7a:1c:6f:33:45: + c6:f7:71:43:8c:62:27:7b:78:c3:0e:a7:99:c3:46: + b0:9a:1a:57:aa:8d:aa:75:b3:3d:66:dc:6e:c2:a1: + 04:0c:1e:de:0b:47:22:a9:9e:79:f9:77:b0:4f:02: + a4:f9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 5D:44:58:02:45:8B:00:5A:DC:03:69:84:EE:70:D6:41:3F:17:C6:10 + X509v3 Authority Key Identifier: + keyid:83:E9:DD:D5:5E:57:59:40:E8:95:19:90:B4:63:79:EE:00:DB:C6:DB + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 42:d8:bc:41:ae:5f:f3:3b:49:c0:72:b3:79:d0:68:36:22:82: + 14:d6:71:56:2c:d2:85:39:2c:34:7c:0a:2c:d8:88:2b:0e:04: + 62:b2:5a:0b:ab:03:df:58:a8:ac:a9:16:a4:81:e8:e4:61:45: + 08:2b:82:3c:7c:66:ca:00:04:57:a5:47:7e:15:f4:1b:a8:7d: + c0:02:5d:2e:ad:ee:52:03:38:d4:5b:e2:d8:4e:04:7b:c2:cd: + 7e:0e:ca:9f:b9:e9:43:1c:25:01:60:2b:91:37:de:de:31:cc: + 88:47:88:1f:46:95:49:de:67:35:16:f1:21:77:c3:03:40:56: + 6a:ac:dc:49:4c:ba:b4:5a:13:cb:68:97:59:8d:5c:7e:ca:a2: + fc:5d:21:95:9f:3c:3f:9b:ea:25:b9:8f:30:6d:68:a6:58:6c: + b6:8f:4c:d3:4c:c4:a7:da:04:49:ca:d0:96:81:c3:fb:41:6d: + ba:4d:9a:b2:fd:b2:0b:30:7c:1e:da:90:54:d3:ac:e0:ad:e3: + 48:9f:ef:51:9e:e4:e8:2e:1d:a5:17:cd:8b:40:94:30:44:e0: + 1d:f3:7f:ec:a6:6e:c8:2f:1c:a3:84:17:f9:66:f7:74:f9:8d: + b5:59:86:da:36:31:71:14:0f:af:d9:c3:96:92:e2:54:c6:b4: + 8b:76:f6:08 +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgIMcdn/GFo0zJ/uYAu9MA0GCSqGSIb3DQEBCwUAMFUxCzAJ +BgNVBAYTAkNOMQswCQYDVQQIDAJCSjELMAkGA1UEBwwCQkoxCzAJBgNVBAoMAk5U +MQswCQYDVQQLDAJOVDESMBAGA1UEAwwJQ0EgVFJVU1QxMB4XDTIzMDcwNzExMzAw +MVoXDTI0MTExODExMzAwMVowSDELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkJKMQsw +CQYDVQQKDAJOVDELMAkGA1UECwwCTlQxEjAQBgNVBAMMCWNhbWlkZGxlMTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMtar5TSapiR8RNulZ7tUJaFDo4L +/X/yILaIJzSRn7PEJ0Pk6USA/eJRZ9f4mxcWLDZ+9HUpY0DsmymnTqLZ4coaUWJD +Xq9VimS1drqkeNaH+tahywhnaQzsWtl7eG8o0xsUY+69R5LhVxgzvJm6L4LNRRWy +vRP6UTi7K2gRCqS5GIhwVl+J4RAheemx9BWLdBBv2DaeYEwdYWNSe7c9Y4tlsy/t +59S1ORUyUtNz6sSFU0XqWndnTDy7CrgLY2k5ONNheBYQSOZAvxqpm3ocbzNFxvdx +Q4xiJ3t4ww6nmcNGsJoaV6qNqnWzPWbcbsKhBAwe3gtHIqmeefl3sE8CpPkCAwEA +AaNQME4wHQYDVR0OBBYEFF1EWAJFiwBa3ANphO5w1kE/F8YQMB8GA1UdIwQYMBaA +FIPp3dVeV1lA6JUZkLRjee4A28bbMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBAELYvEGuX/M7ScBys3nQaDYighTWcVYs0oU5LDR8CizYiCsOBGKyWgur +A99YqKypFqSB6ORhRQgrgjx8ZsoABFelR34V9BuofcACXS6t7lIDONRb4thOBHvC +zX4Oyp+56UMcJQFgK5E33t4xzIhHiB9GlUneZzUW8SF3wwNAVmqs3ElMurRaE8to +l1mNXH7KovxdIZWfPD+b6iW5jzBtaKZYbLaPTNNMxKfaBEnK0JaBw/tBbbpNmrL9 +sgswfB7akFTTrOCt40if71Ge5OguHaUXzYtAlDBE4B3zf+ymbsgvHKOEF/lm93T5 +jbVZhto2MXEUD6/Zw5aS4lTGtIt29gg= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDfTCCAmWgAwIBAgIJAJnxzpEq+vIfMA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNV +BAYTAkNOMQswCQYDVQQIDAJCSjELMAkGA1UEBwwCQkoxCzAJBgNVBAoMAk5UMQsw +CQYDVQQLDAJOVDESMBAGA1UEAwwJQ0EgVFJVU1QxMB4XDTIzMDcwNzExMjk1NVoX +DTI0MTExODExMjk1NVowVTELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkJKMQswCQYD +VQQHDAJCSjELMAkGA1UECgwCTlQxCzAJBgNVBAsMAk5UMRIwEAYDVQQDDAlDQSBU +UlVTVDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDO+4rZA65F6tlt +HEnbFG56FyYs/V9XAM6sSSnnFj8H8MNvxiRQXlaevdK8/7xwtN3udX+x4VdSnmi4 +wPGLhrPWvrrv2ZrDbRlBwNmIosmE+dQdqf9OyN44Pw4/TQoh14CWqjqxQXYLevrn +45GH1POUR64U6qO5Uq5B83zimTRWTbXertvrYb4plOKNxvav3IKdNEufRJSqxelf +AUMQnsrH1iO4iMpZHBYSNbfwl6gkgnXxsr8YTZrrQwk9Bcd/0bFQ+v3OiWD5oiYc +XfcIBTeoy6IIICNc7krfnXRpsXO2oimNgMS6nHPKvXYF5jTbKr0A40ElDEIjtt5T +Yb4oWNHfAgMBAAGjUDBOMB0GA1UdDgQWBBSD6d3VXldZQOiVGZC0Y3nuANvG2zAf +BgNVHSMEGDAWgBSD6d3VXldZQOiVGZC0Y3nuANvG2zAMBgNVHRMEBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4IBAQCM3XHUZ1RwpLtF5DpEKDmC4osIiguk7ENF7Bg+LCQt +GzIeBkHPZ0sKbqZr0og6a0r0Qn1Xzr5nku9cuFH1Gc9Wwg82i8zXLgD8//VSNy5k +SLKb7MiAAnUHv6ZkluX8X9bdg32vb+sTwhuFhjbI5LVWvY3dq/Ez+WERFUxgNL3s +dgiJABkslbkjobgB39m/Lr223P6HwG5n6YukKSmwfiion5QYsTbTpd9AYbAD5UTs +A5H5pRdk/mxJ7yYsgosu60wAUI/xVAVvsaUDGa+koiVKPhUg4A7Qd/2oDByb/H9J +atqHkSjkwvhAekC0mOjKh6ED/Nr2tnN5l0GIbwRvj9Xz +-----END CERTIFICATE----- diff --git a/testdata/ui_file/profiles/ssl_decryption_keyrings/test_mid_key_camiddletest.key b/testdata/ui_file/profiles/ssl_decryption_keyrings/test_mid_key_camiddletest.key new file mode 100644 index 00000000..2060cc7d --- /dev/null +++ b/testdata/ui_file/profiles/ssl_decryption_keyrings/test_mid_key_camiddletest.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAy1qvlNJqmJHxE26Vnu1QloUOjgv9f/IgtognNJGfs8QnQ+Tp +RID94lFn1/ibFxYsNn70dSljQOybKadOotnhyhpRYkNer1WKZLV2uqR41of61qHL +CGdpDOxa2Xt4byjTGxRj7r1HkuFXGDO8mbovgs1FFbK9E/pROLsraBEKpLkYiHBW +X4nhECF56bH0FYt0EG/YNp5gTB1hY1J7tz1ji2WzL+3n1LU5FTJS03PqxIVTRepa +d2dMPLsKuAtjaTk402F4FhBI5kC/GqmbehxvM0XG93FDjGIne3jDDqeZw0awmhpX +qo2qdbM9ZtxuwqEEDB7eC0ciqZ55+XewTwKk+QIDAQABAoIBAGHBsaB4WrgHiH3P +7mtdKB2Dz1Bn4TBtpF47K6Wwz7YqeLnBxIWjAOmYOrRvFZdOmGiGNVxRTh5638hx +XnMZDNsMNc1oF49wLrxlI7Nrt49iBSrC0oiytaR5xt6/5VCCrqFY9wVgxpSMcUL4 +NBUulQJrTWe16gE9l2gPSjmX36b5XLG6n3wsMCh8yphwwOBg86DjYWVY+q/AKY+j +emSka2HYNTXOLQw6cBMcx2dKXtz4/XxDEtbhn/Fwd8B4D4n5RsuqDlLe/vLSXoDp +1IDuK+SsprFZg2O6ss6r9hFEpBtTLYlk9RPlCgtvrMhwCULcRhxoIVxfvL9i+75E +WT6KoQECgYEA6J8btSUE/bNVgy3mmcTZ9t/ukagg3DOyAR/cojEZB3G4FocGxfI8 +BRWUYL3X4tTibLh222fWQMiJB2nUGCEstPKC4vBuorq8jdmNS4EvT0v7w0MiELrf +MiBq2vRla74buweIlTO67kXt+2+MsY4H8jkUanj6ajseJYWvPPsEQWECgYEA38qW +qE7Hc32VlgL00uIYjBGkvfEHDRzwROwTiWMtvqea2WpdR/mBfzrWle4rUXiH9c+A +GTSh2aBpfEgIqzR5wDASYk4cbgfyl/PjsG0ibCf/auilMeHJXw9RDSdkWnfPmFd/ +633yzsY6aYNNauaxSuTLI09VxX8rVYXYfp2W0pkCgYEAiXFI67SdyFBnXASI1Z3r +suQIj2MpVzHsIKH0uJgN08orHJRXOimvsMlZS/efUNS7m8U55NTrUIer/wdWW5Nu +WNNY5kFs/RUcRyudQlln3JBmhq5puDzRl0p0GD6CljBTLiR7XLyd3B7RR9hW5qmm +pEV5fJdSTeX0H/Nm4L7nesECgYBbTnnnk7TWzw9gFDa1b+AaDfzMLnH1DLCPPk6+ +SEPavOF2AWqrugX21hfFNlZgODAov4+BOTMr6sH/HhjDWXavTi3CBCKfVgjJrI1i +ZzSbMjqI8QCteHTDnykvl7nfG3EMs+6SM2IEsWYVtKe6jQMbDnw/HNhe6wLQMvrg +tgVaSQKBgQDRLgTP5YxrUMUT3dq1cyXy3DQoMCPjAka07zXBaAAALtnn57SxR1mN +kJ4cl4YjhdhRBvGV7KSB4hDBKks+xRuuuQ+Eq+I68a9uWE/k4Sdh3MZpif57lC+L +edJqQRviqD0xMi+JImb6rUtNCjVJ/OgLc5pGgdeFi/+lRkiX9M8xJA== +-----END RSA PRIVATE KEY----- diff --git a/testdata/ui_file/profiles/ssl_decryption_keyrings/test_root_cert_catest.cer b/testdata/ui_file/profiles/ssl_decryption_keyrings/test_root_cert_catest.cer new file mode 100644 index 00000000..8392b0d6 --- /dev/null +++ b/testdata/ui_file/profiles/ssl_decryption_keyrings/test_root_cert_catest.cer @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDfTCCAmWgAwIBAgIJAJnxzpEq+vIfMA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNV +BAYTAkNOMQswCQYDVQQIDAJCSjELMAkGA1UEBwwCQkoxCzAJBgNVBAoMAk5UMQsw +CQYDVQQLDAJOVDESMBAGA1UEAwwJQ0EgVFJVU1QxMB4XDTIzMDcwNzExMjk1NVoX +DTI0MTExODExMjk1NVowVTELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkJKMQswCQYD +VQQHDAJCSjELMAkGA1UECgwCTlQxCzAJBgNVBAsMAk5UMRIwEAYDVQQDDAlDQSBU +UlVTVDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDO+4rZA65F6tlt +HEnbFG56FyYs/V9XAM6sSSnnFj8H8MNvxiRQXlaevdK8/7xwtN3udX+x4VdSnmi4 +wPGLhrPWvrrv2ZrDbRlBwNmIosmE+dQdqf9OyN44Pw4/TQoh14CWqjqxQXYLevrn +45GH1POUR64U6qO5Uq5B83zimTRWTbXertvrYb4plOKNxvav3IKdNEufRJSqxelf +AUMQnsrH1iO4iMpZHBYSNbfwl6gkgnXxsr8YTZrrQwk9Bcd/0bFQ+v3OiWD5oiYc +XfcIBTeoy6IIICNc7krfnXRpsXO2oimNgMS6nHPKvXYF5jTbKr0A40ElDEIjtt5T +Yb4oWNHfAgMBAAGjUDBOMB0GA1UdDgQWBBSD6d3VXldZQOiVGZC0Y3nuANvG2zAf +BgNVHSMEGDAWgBSD6d3VXldZQOiVGZC0Y3nuANvG2zAMBgNVHRMEBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4IBAQCM3XHUZ1RwpLtF5DpEKDmC4osIiguk7ENF7Bg+LCQt +GzIeBkHPZ0sKbqZr0og6a0r0Qn1Xzr5nku9cuFH1Gc9Wwg82i8zXLgD8//VSNy5k +SLKb7MiAAnUHv6ZkluX8X9bdg32vb+sTwhuFhjbI5LVWvY3dq/Ez+WERFUxgNL3s +dgiJABkslbkjobgB39m/Lr223P6HwG5n6YukKSmwfiion5QYsTbTpd9AYbAD5UTs +A5H5pRdk/mxJ7yYsgosu60wAUI/xVAVvsaUDGa+koiVKPhUg4A7Qd/2oDByb/H9J +atqHkSjkwvhAekC0mOjKh6ED/Nr2tnN5l0GIbwRvj9Xz +-----END CERTIFICATE----- diff --git a/testdata/ui_file/profiles/ssl_decryption_keyrings/test_root_key_catest.key b/testdata/ui_file/profiles/ssl_decryption_keyrings/test_root_key_catest.key new file mode 100644 index 00000000..a347d61e --- /dev/null +++ b/testdata/ui_file/profiles/ssl_decryption_keyrings/test_root_key_catest.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAzvuK2QOuRerZbRxJ2xRuehcmLP1fVwDOrEkp5xY/B/DDb8Yk +UF5Wnr3SvP+8cLTd7nV/seFXUp5ouMDxi4az1r6679maw20ZQcDZiKLJhPnUHan/ +TsjeOD8OP00KIdeAlqo6sUF2C3r65+ORh9TzlEeuFOqjuVKuQfN84pk0Vk213q7b +62G+KZTijcb2r9yCnTRLn0SUqsXpXwFDEJ7Kx9YjuIjKWRwWEjW38JeoJIJ18bK/ +GE2a60MJPQXHf9GxUPr9zolg+aImHF33CAU3qMuiCCAjXO5K3510abFztqIpjYDE +upxzyr12BeY02yq9AONBJQxCI7beU2G+KFjR3wIDAQABAoIBAQClBnEhrYmZPTG1 +iMRp49Rhi2tom2sUVxRw0LSUBmyizBdGWthBK7YsQnRvNAbuZYY8xXnWPS/+M0aT +Z2IuOGvSX6dz7C80eRuWDUhjZEb/uqCgNhXUntpuRff6CFZ3vPZNKdQ511Niu96o +XAyAHA1IwA3Pp3R6Ia3F73g2wqez1jorYZC14OZl8zv2CMLhZ5ES76gilypRV/g0 +6bBbBrpGZ130Cg+kQ81T+HUZWRgNtByFNwzZfBAu1jcdxQdAR1kMtnCjHtUm/kUX +z1h3XclM1nuWoLY6bOUttJKWlHz8J6NKb4pO2PGmsWOhZx7JuQcSJE3rfLbG6LiH +JJSEYB7hAoGBAPCXMUvMwqOsW0uCmsAH1iC1UeNG1lAAgDo49qDeKPoMXLUKmkjw +s/zcllWH1TawU0M4SpdRLolBFJjkgNZL/woiPJ67mUDFSLeYQ/hrgVdxTzWaUnCG +5XUyaiCs9C22Pzs+hMIkAgBhf0rh61J0hCNX0UeyrsMG+tG524lrfAfzAoGBANw9 +TRkqoHRPM9GsM1Kme/5WzT89IpQwSYSFI1v07de5GFNnIFzY7/B8wI61vyne5Bwf +PJmYtdzB4ebU0xJf02QozuKkkYIupju1pDaWctKpgR/0ZYPTh8TAVqjfS0IeOup1 +EVkUSOJffPJuiM6ukuut6e/OTZKI+R4FvDzOolVlAoGAQV3yyNNzNqEHlPaBMRdv ++CcLfqKqa8YXELqVV5PEsltVfOLKlHLBlDwipE5pgZhapvLOYVpvOF90Ry4eSxsO +yiQPMFlsBAsV/LvkC8S5uZZRnRC2wVgFU9hEuWgEV78iYuhTjaPW31+eBCxpkVeS +5z9e3woPLXHiB8Vlfmqzoj0CgYEA2hom8MZC8gvBUGHMzYurfRtu1LJxPPl4xLCo +bJdotlpJ2cZlySzYqHqSooEf15IwqhzRAXa2mvCyCss2X5rgF+9FujKpGpeh7b2a +6qgg+7f69K8tnNftOw4Sg9fliouvYqIeVO3+o5dWgCqwdqVxP84Rvna6YWQd9/pM +CJfFMPUCgYEA5v064YjwtVkE5IIZR7b0HMpZKeJMLRhNkSrYGDpt8y/da/GnRpcw +H8shApl6E+/rTElHPd7o+HTxQ4LdqqgEUDM08sGSFz9R+0DA7YARCPahh5ZIXTqV +4QNdC8CUu20PR05YuLj0V9UXRaO+njtvr2785iv3AF7kBgl9K90sR5E= +-----END RSA PRIVATE KEY----- |
