kdtest-pw 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kdtest_pw/__init__.py +50 -0
- kdtest_pw/action/__init__.py +7 -0
- kdtest_pw/action/base_keyword.py +292 -0
- kdtest_pw/action/element_plus/__init__.py +23 -0
- kdtest_pw/action/element_plus/el_cascader.py +263 -0
- kdtest_pw/action/element_plus/el_datepicker.py +324 -0
- kdtest_pw/action/element_plus/el_dialog.py +317 -0
- kdtest_pw/action/element_plus/el_form.py +443 -0
- kdtest_pw/action/element_plus/el_menu.py +456 -0
- kdtest_pw/action/element_plus/el_select.py +268 -0
- kdtest_pw/action/element_plus/el_table.py +442 -0
- kdtest_pw/action/element_plus/el_tree.py +364 -0
- kdtest_pw/action/element_plus/el_upload.py +313 -0
- kdtest_pw/action/key_retrieval.py +311 -0
- kdtest_pw/action/page_action.py +1129 -0
- kdtest_pw/api/__init__.py +6 -0
- kdtest_pw/api/api_keyword.py +251 -0
- kdtest_pw/api/request_handler.py +232 -0
- kdtest_pw/cases/__init__.py +6 -0
- kdtest_pw/cases/case_collector.py +182 -0
- kdtest_pw/cases/case_executor.py +359 -0
- kdtest_pw/cases/read/__init__.py +6 -0
- kdtest_pw/cases/read/cell_handler.py +305 -0
- kdtest_pw/cases/read/excel_reader.py +223 -0
- kdtest_pw/cli/__init__.py +5 -0
- kdtest_pw/cli/run.py +318 -0
- kdtest_pw/common.py +106 -0
- kdtest_pw/core/__init__.py +7 -0
- kdtest_pw/core/browser_manager.py +196 -0
- kdtest_pw/core/config_loader.py +235 -0
- kdtest_pw/core/page_context.py +228 -0
- kdtest_pw/data/__init__.py +5 -0
- kdtest_pw/data/init_data.py +105 -0
- kdtest_pw/data/static/elementData.yaml +59 -0
- kdtest_pw/data/static/parameters.json +24 -0
- kdtest_pw/plugins/__init__.py +6 -0
- kdtest_pw/plugins/element_plus_plugin/__init__.py +5 -0
- kdtest_pw/plugins/element_plus_plugin/elementData/elementData.yaml +144 -0
- kdtest_pw/plugins/element_plus_plugin/element_plus_plugin.py +237 -0
- kdtest_pw/plugins/element_plus_plugin/my.ini +23 -0
- kdtest_pw/plugins/plugin_base.py +180 -0
- kdtest_pw/plugins/plugin_loader.py +260 -0
- kdtest_pw/product.py +5 -0
- kdtest_pw/reference.py +99 -0
- kdtest_pw/utils/__init__.py +13 -0
- kdtest_pw/utils/built_in_function.py +376 -0
- kdtest_pw/utils/decorator.py +211 -0
- kdtest_pw/utils/log/__init__.py +6 -0
- kdtest_pw/utils/log/html_report.py +336 -0
- kdtest_pw/utils/log/logger.py +123 -0
- kdtest_pw/utils/public_script.py +366 -0
- kdtest_pw-2.0.0.dist-info/METADATA +169 -0
- kdtest_pw-2.0.0.dist-info/RECORD +57 -0
- kdtest_pw-2.0.0.dist-info/WHEEL +5 -0
- kdtest_pw-2.0.0.dist-info/entry_points.txt +2 -0
- kdtest_pw-2.0.0.dist-info/licenses/LICENSE +21 -0
- kdtest_pw-2.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""参数初始化模块"""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Any, Optional
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from ..reference import GSDSTORE, MODULEDATA, INFO
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class InitData:
|
|
10
|
+
"""参数初始化类
|
|
11
|
+
|
|
12
|
+
负责初始化测试所需的各类数据。
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(self, work_path: str = None):
|
|
16
|
+
"""初始化
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
work_path: 工作目录路径
|
|
20
|
+
"""
|
|
21
|
+
self._work_path = Path(work_path) if work_path else Path.cwd()
|
|
22
|
+
self._element_data: Dict[str, Any] = {}
|
|
23
|
+
self._custom_params: Dict[str, Any] = {}
|
|
24
|
+
|
|
25
|
+
def load_element_data(self, file_path: str = None) -> Dict[str, Any]:
|
|
26
|
+
"""加载元素数据
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
file_path: elementData.yaml 文件路径
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
Dict: 元素数据
|
|
33
|
+
"""
|
|
34
|
+
if not file_path:
|
|
35
|
+
# 默认路径
|
|
36
|
+
file_path = self._work_path / 'data' / 'elementData' / 'elementData.yaml'
|
|
37
|
+
|
|
38
|
+
path = Path(file_path)
|
|
39
|
+
if not path.exists():
|
|
40
|
+
INFO(f"元素数据文件不存在: {file_path}", "WARNING")
|
|
41
|
+
return {}
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
import yaml
|
|
45
|
+
with open(path, 'r', encoding='utf-8') as f:
|
|
46
|
+
self._element_data = yaml.safe_load(f) or {}
|
|
47
|
+
|
|
48
|
+
MODULEDATA['elementData'] = self._element_data
|
|
49
|
+
INFO(f"加载元素数据: {len(self._element_data)} 个模块")
|
|
50
|
+
|
|
51
|
+
except ImportError:
|
|
52
|
+
INFO("PyYAML 未安装,无法加载元素数据", "WARNING")
|
|
53
|
+
except Exception as e:
|
|
54
|
+
INFO(f"加载元素数据失败: {e}", "ERROR")
|
|
55
|
+
|
|
56
|
+
return self._element_data
|
|
57
|
+
|
|
58
|
+
def load_custom_params(self, params: Dict[str, Any] = None) -> Dict[str, Any]:
|
|
59
|
+
"""加载自定义参数
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
params: 自定义参数字典
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Dict: 自定义参数
|
|
66
|
+
"""
|
|
67
|
+
if params:
|
|
68
|
+
self._custom_params.update(params)
|
|
69
|
+
GSDSTORE['START']['selfDefinedParameter'] = self._custom_params
|
|
70
|
+
INFO(f"加载自定义参数: {list(params.keys())}")
|
|
71
|
+
|
|
72
|
+
return self._custom_params
|
|
73
|
+
|
|
74
|
+
def setup_work_path(self) -> None:
|
|
75
|
+
"""设置工作路径"""
|
|
76
|
+
GSDSTORE['WORKPATH'] = {
|
|
77
|
+
'root': str(self._work_path),
|
|
78
|
+
'data': str(self._work_path / 'data'),
|
|
79
|
+
'result': str(self._work_path / 'result'),
|
|
80
|
+
'plugins': str(self._work_path / 'plugins'),
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# 确保目录存在
|
|
84
|
+
(self._work_path / 'result' / 'report').mkdir(parents=True, exist_ok=True)
|
|
85
|
+
(self._work_path / 'result' / 'log').mkdir(parents=True, exist_ok=True)
|
|
86
|
+
(self._work_path / 'result' / 'screenshot').mkdir(parents=True, exist_ok=True)
|
|
87
|
+
(self._work_path / 'result' / 'trace').mkdir(parents=True, exist_ok=True)
|
|
88
|
+
(self._work_path / 'result' / 'video').mkdir(parents=True, exist_ok=True)
|
|
89
|
+
|
|
90
|
+
INFO(f"工作目录: {self._work_path}")
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def element_data(self) -> Dict[str, Any]:
|
|
94
|
+
"""获取元素数据"""
|
|
95
|
+
return self._element_data
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def custom_params(self) -> Dict[str, Any]:
|
|
99
|
+
"""获取自定义参数"""
|
|
100
|
+
return self._custom_params
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def work_path(self) -> Path:
|
|
104
|
+
"""获取工作路径"""
|
|
105
|
+
return self._work_path
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# KDTest Playwright 元素数据模板
|
|
2
|
+
# 格式: element_name: [定位类型, 定位表达式]
|
|
3
|
+
|
|
4
|
+
# 示例:登录模块
|
|
5
|
+
login:
|
|
6
|
+
# 用户名输入框
|
|
7
|
+
userName:
|
|
8
|
+
- xpath
|
|
9
|
+
- //input[@placeholder='请输入账号']
|
|
10
|
+
# 密码输入框
|
|
11
|
+
password:
|
|
12
|
+
- xpath
|
|
13
|
+
- //input[@placeholder='请输入密码']
|
|
14
|
+
# 登录按钮
|
|
15
|
+
submitBtn:
|
|
16
|
+
- css
|
|
17
|
+
- .el-button--primary
|
|
18
|
+
# 记住我复选框
|
|
19
|
+
rememberMe:
|
|
20
|
+
- css
|
|
21
|
+
- .el-checkbox
|
|
22
|
+
|
|
23
|
+
# 示例:首页模块
|
|
24
|
+
home:
|
|
25
|
+
# 欢迎文字
|
|
26
|
+
welcomeText:
|
|
27
|
+
- css
|
|
28
|
+
- .welcome-text
|
|
29
|
+
# 菜单列表
|
|
30
|
+
menuList:
|
|
31
|
+
- css
|
|
32
|
+
- .el-menu
|
|
33
|
+
# 退出按钮
|
|
34
|
+
logoutBtn:
|
|
35
|
+
- xpath
|
|
36
|
+
- //span[text()='退出']
|
|
37
|
+
|
|
38
|
+
# 示例:用户管理模块
|
|
39
|
+
userManage:
|
|
40
|
+
# 搜索输入框
|
|
41
|
+
searchInput:
|
|
42
|
+
- css
|
|
43
|
+
- .el-input__inner
|
|
44
|
+
# 搜索按钮
|
|
45
|
+
searchBtn:
|
|
46
|
+
- xpath
|
|
47
|
+
- //button[contains(.,'搜索')]
|
|
48
|
+
# 新增按钮
|
|
49
|
+
addBtn:
|
|
50
|
+
- xpath
|
|
51
|
+
- //button[contains(.,'新增')]
|
|
52
|
+
# 用户表格
|
|
53
|
+
userTable:
|
|
54
|
+
- css
|
|
55
|
+
- .el-table
|
|
56
|
+
# 状态下拉框
|
|
57
|
+
statusSelect:
|
|
58
|
+
- xpath
|
|
59
|
+
- //div[contains(@class,'el-select')]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"testCaseFile": [
|
|
3
|
+
{
|
|
4
|
+
"caseFilePath": "data/static/testCases.xlsx",
|
|
5
|
+
"caseItem": ["Sheet1"],
|
|
6
|
+
"interfaceSwitch": false
|
|
7
|
+
}
|
|
8
|
+
],
|
|
9
|
+
"browser": "chromium",
|
|
10
|
+
"url": "http://localhost:8080",
|
|
11
|
+
"headless": false,
|
|
12
|
+
"slowMo": 0,
|
|
13
|
+
"timeout": 30000,
|
|
14
|
+
"trace": false,
|
|
15
|
+
"video": false,
|
|
16
|
+
"retrySwitch": false,
|
|
17
|
+
"retryCount": 1,
|
|
18
|
+
"parallel": false,
|
|
19
|
+
"selfDefinedParameter": {
|
|
20
|
+
"env": "test",
|
|
21
|
+
"username": "admin",
|
|
22
|
+
"password": "123456"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Element Plus 通用元素定义模板
|
|
2
|
+
# 格式: element_name: [定位类型, 定位表达式]
|
|
3
|
+
|
|
4
|
+
# 登录模块示例
|
|
5
|
+
login:
|
|
6
|
+
userName:
|
|
7
|
+
- xpath
|
|
8
|
+
- //input[@placeholder='请输入账号']
|
|
9
|
+
password:
|
|
10
|
+
- xpath
|
|
11
|
+
- //input[@placeholder='请输入密码']
|
|
12
|
+
submitBtn:
|
|
13
|
+
- css
|
|
14
|
+
- .el-button--primary
|
|
15
|
+
rememberMe:
|
|
16
|
+
- css
|
|
17
|
+
- .el-checkbox
|
|
18
|
+
|
|
19
|
+
# 通用组件
|
|
20
|
+
common:
|
|
21
|
+
# Loading 遮罩
|
|
22
|
+
loadingMask:
|
|
23
|
+
- css
|
|
24
|
+
- .el-loading-mask
|
|
25
|
+
# 消息提示
|
|
26
|
+
message:
|
|
27
|
+
- css
|
|
28
|
+
- .el-message
|
|
29
|
+
messageContent:
|
|
30
|
+
- css
|
|
31
|
+
- .el-message__content
|
|
32
|
+
# 确认对话框
|
|
33
|
+
messageBox:
|
|
34
|
+
- css
|
|
35
|
+
- .el-message-box
|
|
36
|
+
messageBoxConfirm:
|
|
37
|
+
- css
|
|
38
|
+
- .el-message-box__btns .el-button--primary
|
|
39
|
+
messageBoxCancel:
|
|
40
|
+
- css
|
|
41
|
+
- .el-message-box__btns .el-button:not(.el-button--primary)
|
|
42
|
+
# 对话框
|
|
43
|
+
dialog:
|
|
44
|
+
- css
|
|
45
|
+
- .el-dialog
|
|
46
|
+
dialogClose:
|
|
47
|
+
- css
|
|
48
|
+
- .el-dialog__headerbtn
|
|
49
|
+
dialogConfirm:
|
|
50
|
+
- css
|
|
51
|
+
- .el-dialog__footer .el-button--primary
|
|
52
|
+
dialogCancel:
|
|
53
|
+
- css
|
|
54
|
+
- .el-dialog__footer .el-button:not(.el-button--primary)
|
|
55
|
+
|
|
56
|
+
# 表单组件
|
|
57
|
+
form:
|
|
58
|
+
input:
|
|
59
|
+
- css
|
|
60
|
+
- .el-input__inner
|
|
61
|
+
textarea:
|
|
62
|
+
- css
|
|
63
|
+
- .el-textarea__inner
|
|
64
|
+
select:
|
|
65
|
+
- css
|
|
66
|
+
- .el-select
|
|
67
|
+
selectDropdown:
|
|
68
|
+
- css
|
|
69
|
+
- .el-select-dropdown:visible
|
|
70
|
+
selectOption:
|
|
71
|
+
- css
|
|
72
|
+
- .el-select-dropdown__item
|
|
73
|
+
datepicker:
|
|
74
|
+
- css
|
|
75
|
+
- .el-date-editor
|
|
76
|
+
checkbox:
|
|
77
|
+
- css
|
|
78
|
+
- .el-checkbox
|
|
79
|
+
radio:
|
|
80
|
+
- css
|
|
81
|
+
- .el-radio
|
|
82
|
+
switch:
|
|
83
|
+
- css
|
|
84
|
+
- .el-switch
|
|
85
|
+
|
|
86
|
+
# 表格组件
|
|
87
|
+
table:
|
|
88
|
+
table:
|
|
89
|
+
- css
|
|
90
|
+
- .el-table
|
|
91
|
+
tableRow:
|
|
92
|
+
- css
|
|
93
|
+
- .el-table__row
|
|
94
|
+
tableCell:
|
|
95
|
+
- css
|
|
96
|
+
- .el-table__cell
|
|
97
|
+
tableHeader:
|
|
98
|
+
- css
|
|
99
|
+
- .el-table__header-wrapper th
|
|
100
|
+
tableCheckbox:
|
|
101
|
+
- css
|
|
102
|
+
- .el-table__row .el-checkbox
|
|
103
|
+
tableHeaderCheckbox:
|
|
104
|
+
- css
|
|
105
|
+
- .el-table__header-wrapper .el-checkbox
|
|
106
|
+
|
|
107
|
+
# 树形控件
|
|
108
|
+
tree:
|
|
109
|
+
tree:
|
|
110
|
+
- css
|
|
111
|
+
- .el-tree
|
|
112
|
+
treeNode:
|
|
113
|
+
- css
|
|
114
|
+
- .el-tree-node
|
|
115
|
+
treeLabel:
|
|
116
|
+
- css
|
|
117
|
+
- .el-tree-node__label
|
|
118
|
+
treeExpand:
|
|
119
|
+
- css
|
|
120
|
+
- .el-tree-node__expand-icon
|
|
121
|
+
treeCheckbox:
|
|
122
|
+
- css
|
|
123
|
+
- .el-tree-node .el-checkbox
|
|
124
|
+
|
|
125
|
+
# 分页组件
|
|
126
|
+
pagination:
|
|
127
|
+
pagination:
|
|
128
|
+
- css
|
|
129
|
+
- .el-pagination
|
|
130
|
+
prevBtn:
|
|
131
|
+
- css
|
|
132
|
+
- .el-pagination .btn-prev
|
|
133
|
+
nextBtn:
|
|
134
|
+
- css
|
|
135
|
+
- .el-pagination .btn-next
|
|
136
|
+
pageNumber:
|
|
137
|
+
- css
|
|
138
|
+
- .el-pagination .number
|
|
139
|
+
pageSizeSelect:
|
|
140
|
+
- css
|
|
141
|
+
- .el-pagination .el-select
|
|
142
|
+
jumper:
|
|
143
|
+
- css
|
|
144
|
+
- .el-pagination__jump .el-input__inner
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"""Element Plus 内置插件"""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from playwright.sync_api import Page
|
|
5
|
+
|
|
6
|
+
from ..plugin_base import PluginBase
|
|
7
|
+
from ...action.element_plus import (
|
|
8
|
+
ElSelectKeyword,
|
|
9
|
+
ElDatePickerKeyword,
|
|
10
|
+
ElDialogKeyword,
|
|
11
|
+
ElTableKeyword,
|
|
12
|
+
ElCascaderKeyword,
|
|
13
|
+
ElTreeKeyword,
|
|
14
|
+
ElUploadKeyword,
|
|
15
|
+
ElFormKeyword,
|
|
16
|
+
ElMenuKeyword,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ElementPlusPlugin(PluginBase):
|
|
21
|
+
"""Element Plus 组件关键字插件
|
|
22
|
+
|
|
23
|
+
提供 Element Plus UI 组件的操作关键字。
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
name = "element_plus"
|
|
27
|
+
version = "2.0.0"
|
|
28
|
+
description = "Element Plus UI 组件关键字"
|
|
29
|
+
author = "KDTest Team"
|
|
30
|
+
|
|
31
|
+
def __init__(self, page: Page = None):
|
|
32
|
+
super().__init__(page)
|
|
33
|
+
self._el_select: ElSelectKeyword = None
|
|
34
|
+
self._el_datepicker: ElDatePickerKeyword = None
|
|
35
|
+
self._el_dialog: ElDialogKeyword = None
|
|
36
|
+
self._el_table: ElTableKeyword = None
|
|
37
|
+
self._el_cascader: ElCascaderKeyword = None
|
|
38
|
+
self._el_tree: ElTreeKeyword = None
|
|
39
|
+
self._el_upload: ElUploadKeyword = None
|
|
40
|
+
self._el_form: ElFormKeyword = None
|
|
41
|
+
self._el_menu: ElMenuKeyword = None
|
|
42
|
+
|
|
43
|
+
def setup(self) -> None:
|
|
44
|
+
"""初始化插件"""
|
|
45
|
+
# 加载配置
|
|
46
|
+
config_path = Path(__file__).parent / "my.ini"
|
|
47
|
+
if config_path.exists():
|
|
48
|
+
self.load_config_from_file(str(config_path))
|
|
49
|
+
|
|
50
|
+
# 加载元素数据
|
|
51
|
+
element_data_path = Path(__file__).parent / "elementData" / "elementData.yaml"
|
|
52
|
+
if element_data_path.exists():
|
|
53
|
+
self.load_element_data_from_file(str(element_data_path))
|
|
54
|
+
|
|
55
|
+
# 初始化关键字类
|
|
56
|
+
if self._page:
|
|
57
|
+
self._init_keyword_classes()
|
|
58
|
+
|
|
59
|
+
# 注册关键字
|
|
60
|
+
self._register_keywords()
|
|
61
|
+
|
|
62
|
+
def _init_keyword_classes(self) -> None:
|
|
63
|
+
"""初始化关键字类实例"""
|
|
64
|
+
self._el_select = ElSelectKeyword(self._page)
|
|
65
|
+
self._el_datepicker = ElDatePickerKeyword(self._page)
|
|
66
|
+
self._el_dialog = ElDialogKeyword(self._page)
|
|
67
|
+
self._el_table = ElTableKeyword(self._page)
|
|
68
|
+
self._el_cascader = ElCascaderKeyword(self._page)
|
|
69
|
+
self._el_tree = ElTreeKeyword(self._page)
|
|
70
|
+
self._el_upload = ElUploadKeyword(self._page)
|
|
71
|
+
self._el_form = ElFormKeyword(self._page)
|
|
72
|
+
self._el_menu = ElMenuKeyword(self._page)
|
|
73
|
+
|
|
74
|
+
def _register_keywords(self) -> None:
|
|
75
|
+
"""注册所有关键字"""
|
|
76
|
+
# Select 关键字
|
|
77
|
+
self.register_keywords({
|
|
78
|
+
'el_select': self._wrap('_el_select', 'el_select'),
|
|
79
|
+
'el_select_multiple': self._wrap('_el_select', 'el_select_multiple'),
|
|
80
|
+
'el_select_clear': self._wrap('_el_select', 'el_select_clear'),
|
|
81
|
+
'el_select_search': self._wrap('_el_select', 'el_select_search'),
|
|
82
|
+
'el_select_get_value': self._wrap('_el_select', 'el_select_get_value'),
|
|
83
|
+
'el_select_assert': self._wrap('_el_select', 'el_select_assert'),
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
# DatePicker 关键字
|
|
87
|
+
self.register_keywords({
|
|
88
|
+
'el_datepicker': self._wrap('_el_datepicker', 'el_datepicker'),
|
|
89
|
+
'el_datepicker_panel': self._wrap('_el_datepicker', 'el_datepicker_panel'),
|
|
90
|
+
'el_datepicker_today': self._wrap('_el_datepicker', 'el_datepicker_today'),
|
|
91
|
+
'el_datetimepicker': self._wrap('_el_datepicker', 'el_datetimepicker'),
|
|
92
|
+
'el_daterange': self._wrap('_el_datepicker', 'el_daterange'),
|
|
93
|
+
'el_datepicker_clear': self._wrap('_el_datepicker', 'el_datepicker_clear'),
|
|
94
|
+
'el_datepicker_get_value': self._wrap('_el_datepicker', 'el_datepicker_get_value'),
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
# Dialog 关键字
|
|
98
|
+
self.register_keywords({
|
|
99
|
+
'el_dialog_wait': self._wrap('_el_dialog', 'el_dialog_wait'),
|
|
100
|
+
'el_dialog_close': self._wrap('_el_dialog', 'el_dialog_close'),
|
|
101
|
+
'el_dialog_confirm': self._wrap('_el_dialog', 'el_dialog_confirm'),
|
|
102
|
+
'el_dialog_cancel': self._wrap('_el_dialog', 'el_dialog_cancel'),
|
|
103
|
+
'el_dialog_input': self._wrap('_el_dialog', 'el_dialog_input'),
|
|
104
|
+
'el_message_box_wait': self._wrap('_el_dialog', 'el_message_box_wait'),
|
|
105
|
+
'el_message_box_confirm': self._wrap('_el_dialog', 'el_message_box_confirm'),
|
|
106
|
+
'el_message_box_input': self._wrap('_el_dialog', 'el_message_box_input'),
|
|
107
|
+
'el_message_wait': self._wrap('_el_dialog', 'el_message_wait'),
|
|
108
|
+
'el_message_get_text': self._wrap('_el_dialog', 'el_message_get_text'),
|
|
109
|
+
'el_message_assert': self._wrap('_el_dialog', 'el_message_assert'),
|
|
110
|
+
'el_notification_wait': self._wrap('_el_dialog', 'el_notification_wait'),
|
|
111
|
+
'el_notification_close': self._wrap('_el_dialog', 'el_notification_close'),
|
|
112
|
+
'el_drawer_wait': self._wrap('_el_dialog', 'el_drawer_wait'),
|
|
113
|
+
'el_drawer_close': self._wrap('_el_dialog', 'el_drawer_close'),
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
# Table 关键字
|
|
117
|
+
self.register_keywords({
|
|
118
|
+
'el_table_click_row': self._wrap('_el_table', 'el_table_click_row'),
|
|
119
|
+
'el_table_click_cell': self._wrap('_el_table', 'el_table_click_cell'),
|
|
120
|
+
'el_table_get_cell_text': self._wrap('_el_table', 'el_table_get_cell_text'),
|
|
121
|
+
'el_table_get_row_count': self._wrap('_el_table', 'el_table_get_row_count'),
|
|
122
|
+
'el_table_select_row': self._wrap('_el_table', 'el_table_select_row'),
|
|
123
|
+
'el_table_select_rows': self._wrap('_el_table', 'el_table_select_rows'),
|
|
124
|
+
'el_table_sort': self._wrap('_el_table', 'el_table_sort'),
|
|
125
|
+
'el_table_expand_row': self._wrap('_el_table', 'el_table_expand_row'),
|
|
126
|
+
'el_table_click_button': self._wrap('_el_table', 'el_table_click_button'),
|
|
127
|
+
'el_table_search_row': self._wrap('_el_table', 'el_table_search_row'),
|
|
128
|
+
'el_table_assert_cell': self._wrap('_el_table', 'el_table_assert_cell'),
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
# Cascader 关键字
|
|
132
|
+
self.register_keywords({
|
|
133
|
+
'el_cascader': self._wrap('_el_cascader', 'el_cascader'),
|
|
134
|
+
'el_cascader_search': self._wrap('_el_cascader', 'el_cascader_search'),
|
|
135
|
+
'el_cascader_clear': self._wrap('_el_cascader', 'el_cascader_clear'),
|
|
136
|
+
'el_cascader_get_value': self._wrap('_el_cascader', 'el_cascader_get_value'),
|
|
137
|
+
'el_cascader_assert': self._wrap('_el_cascader', 'el_cascader_assert'),
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
# Tree 关键字
|
|
141
|
+
self.register_keywords({
|
|
142
|
+
'el_tree_click_node': self._wrap('_el_tree', 'el_tree_click_node'),
|
|
143
|
+
'el_tree_expand_node': self._wrap('_el_tree', 'el_tree_expand_node'),
|
|
144
|
+
'el_tree_collapse_node': self._wrap('_el_tree', 'el_tree_collapse_node'),
|
|
145
|
+
'el_tree_check_node': self._wrap('_el_tree', 'el_tree_check_node'),
|
|
146
|
+
'el_tree_check_nodes': self._wrap('_el_tree', 'el_tree_check_nodes'),
|
|
147
|
+
'el_tree_expand_all': self._wrap('_el_tree', 'el_tree_expand_all'),
|
|
148
|
+
'el_tree_collapse_all': self._wrap('_el_tree', 'el_tree_collapse_all'),
|
|
149
|
+
'el_tree_search': self._wrap('_el_tree', 'el_tree_search'),
|
|
150
|
+
'el_tree_assert_node_exists': self._wrap('_el_tree', 'el_tree_assert_node_exists'),
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
# Upload 关键字
|
|
154
|
+
self.register_keywords({
|
|
155
|
+
'el_upload': self._wrap('_el_upload', 'el_upload'),
|
|
156
|
+
'el_upload_drag': self._wrap('_el_upload', 'el_upload_drag'),
|
|
157
|
+
'el_upload_remove': self._wrap('_el_upload', 'el_upload_remove'),
|
|
158
|
+
'el_upload_clear': self._wrap('_el_upload', 'el_upload_clear'),
|
|
159
|
+
'el_upload_preview': self._wrap('_el_upload', 'el_upload_preview'),
|
|
160
|
+
'el_upload_get_file_count': self._wrap('_el_upload', 'el_upload_get_file_count'),
|
|
161
|
+
'el_upload_assert_count': self._wrap('_el_upload', 'el_upload_assert_count'),
|
|
162
|
+
'el_upload_wait_success': self._wrap('_el_upload', 'el_upload_wait_success'),
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
# Form 关键字
|
|
166
|
+
self.register_keywords({
|
|
167
|
+
'el_form_input': self._wrap('_el_form', 'el_form_input'),
|
|
168
|
+
'el_form_select': self._wrap('_el_form', 'el_form_select'),
|
|
169
|
+
'el_form_date': self._wrap('_el_form', 'el_form_date'),
|
|
170
|
+
'el_form_checkbox': self._wrap('_el_form', 'el_form_checkbox'),
|
|
171
|
+
'el_form_radio': self._wrap('_el_form', 'el_form_radio'),
|
|
172
|
+
'el_form_switch': self._wrap('_el_form', 'el_form_switch'),
|
|
173
|
+
'el_form_submit': self._wrap('_el_form', 'el_form_submit'),
|
|
174
|
+
'el_form_reset': self._wrap('_el_form', 'el_form_reset'),
|
|
175
|
+
'el_form_get_error': self._wrap('_el_form', 'el_form_get_error'),
|
|
176
|
+
'el_form_assert_error': self._wrap('_el_form', 'el_form_assert_error'),
|
|
177
|
+
'el_form_fill': self._wrap('_el_form', 'el_form_fill'),
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
# Menu 菜单导航关键字
|
|
181
|
+
self.register_keywords({
|
|
182
|
+
'menu_load_data': self._wrap('_el_menu', 'load_menu_data'),
|
|
183
|
+
'menu_navigate': self._wrap('_el_menu', 'menu_navigate'),
|
|
184
|
+
'menu_click_first': self._wrap('_el_menu', 'menu_click_first'),
|
|
185
|
+
'menu_click_second': self._wrap('_el_menu', 'menu_click_second'),
|
|
186
|
+
'menu_click_third': self._wrap('_el_menu', 'menu_click_third'),
|
|
187
|
+
'menu_click_tag': self._wrap('_el_menu', 'menu_click_tag'),
|
|
188
|
+
'menu_switch_iframe': self._wrap('_el_menu', 'menu_switch_iframe'),
|
|
189
|
+
'menu_exit_iframe': self._wrap('_el_menu', 'menu_exit_iframe'),
|
|
190
|
+
'menu_get_first_menus': self._wrap('_el_menu', 'menu_get_first_menus'),
|
|
191
|
+
'menu_get_second_menus': self._wrap('_el_menu', 'menu_get_second_menus'),
|
|
192
|
+
'menu_get_tag_count': self._wrap('_el_menu', 'menu_get_tag_count'),
|
|
193
|
+
'menu_has_iframe': self._wrap('_el_menu', 'menu_has_iframe'),
|
|
194
|
+
'menu_get_iframe_name': self._wrap('_el_menu', 'menu_get_iframe_name'),
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
def _wrap(self, instance_name: str, method_name: str):
|
|
198
|
+
"""包装方法调用
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
instance_name: 实例属性名
|
|
202
|
+
method_name: 方法名
|
|
203
|
+
|
|
204
|
+
Returns:
|
|
205
|
+
包装后的函数
|
|
206
|
+
"""
|
|
207
|
+
def wrapper(*args, **kwargs):
|
|
208
|
+
instance = getattr(self, instance_name)
|
|
209
|
+
if instance is None:
|
|
210
|
+
if self._page:
|
|
211
|
+
self._init_keyword_classes()
|
|
212
|
+
instance = getattr(self, instance_name)
|
|
213
|
+
else:
|
|
214
|
+
raise RuntimeError("Page 实例未设置")
|
|
215
|
+
|
|
216
|
+
method = getattr(instance, method_name)
|
|
217
|
+
return method(*args, **kwargs)
|
|
218
|
+
|
|
219
|
+
return wrapper
|
|
220
|
+
|
|
221
|
+
def set_page(self, page: Page) -> None:
|
|
222
|
+
"""设置 Page 实例"""
|
|
223
|
+
super().set_page(page)
|
|
224
|
+
if page:
|
|
225
|
+
self._init_keyword_classes()
|
|
226
|
+
|
|
227
|
+
def load_menu_data(self, file_path: str) -> None:
|
|
228
|
+
"""加载菜单配置文件
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
file_path: modularInformation.json 文件路径
|
|
232
|
+
"""
|
|
233
|
+
if self._el_menu:
|
|
234
|
+
self._el_menu.load_menu_data(file_path)
|
|
235
|
+
elif self._page:
|
|
236
|
+
self._init_keyword_classes()
|
|
237
|
+
self._el_menu.load_menu_data(file_path)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
[element_plus]
|
|
2
|
+
# Element Plus 插件配置
|
|
3
|
+
|
|
4
|
+
# 默认等待超时 (毫秒)
|
|
5
|
+
default_timeout = 5000
|
|
6
|
+
|
|
7
|
+
# 下拉面板选择器
|
|
8
|
+
dropdown_selector = .el-select-dropdown:visible, .el-popper:visible
|
|
9
|
+
|
|
10
|
+
# 日期面板选择器
|
|
11
|
+
datepicker_panel_selector = .el-date-picker:visible, .el-picker-panel:visible
|
|
12
|
+
|
|
13
|
+
# 对话框选择器
|
|
14
|
+
dialog_selector = .el-dialog:visible
|
|
15
|
+
|
|
16
|
+
# Message 选择器
|
|
17
|
+
message_selector = .el-message:visible
|
|
18
|
+
|
|
19
|
+
# 是否等待 loading 消失
|
|
20
|
+
wait_loading = true
|
|
21
|
+
|
|
22
|
+
# loading 选择器
|
|
23
|
+
loading_selector = .el-loading-mask
|