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.
Files changed (57) hide show
  1. kdtest_pw/__init__.py +50 -0
  2. kdtest_pw/action/__init__.py +7 -0
  3. kdtest_pw/action/base_keyword.py +292 -0
  4. kdtest_pw/action/element_plus/__init__.py +23 -0
  5. kdtest_pw/action/element_plus/el_cascader.py +263 -0
  6. kdtest_pw/action/element_plus/el_datepicker.py +324 -0
  7. kdtest_pw/action/element_plus/el_dialog.py +317 -0
  8. kdtest_pw/action/element_plus/el_form.py +443 -0
  9. kdtest_pw/action/element_plus/el_menu.py +456 -0
  10. kdtest_pw/action/element_plus/el_select.py +268 -0
  11. kdtest_pw/action/element_plus/el_table.py +442 -0
  12. kdtest_pw/action/element_plus/el_tree.py +364 -0
  13. kdtest_pw/action/element_plus/el_upload.py +313 -0
  14. kdtest_pw/action/key_retrieval.py +311 -0
  15. kdtest_pw/action/page_action.py +1129 -0
  16. kdtest_pw/api/__init__.py +6 -0
  17. kdtest_pw/api/api_keyword.py +251 -0
  18. kdtest_pw/api/request_handler.py +232 -0
  19. kdtest_pw/cases/__init__.py +6 -0
  20. kdtest_pw/cases/case_collector.py +182 -0
  21. kdtest_pw/cases/case_executor.py +359 -0
  22. kdtest_pw/cases/read/__init__.py +6 -0
  23. kdtest_pw/cases/read/cell_handler.py +305 -0
  24. kdtest_pw/cases/read/excel_reader.py +223 -0
  25. kdtest_pw/cli/__init__.py +5 -0
  26. kdtest_pw/cli/run.py +318 -0
  27. kdtest_pw/common.py +106 -0
  28. kdtest_pw/core/__init__.py +7 -0
  29. kdtest_pw/core/browser_manager.py +196 -0
  30. kdtest_pw/core/config_loader.py +235 -0
  31. kdtest_pw/core/page_context.py +228 -0
  32. kdtest_pw/data/__init__.py +5 -0
  33. kdtest_pw/data/init_data.py +105 -0
  34. kdtest_pw/data/static/elementData.yaml +59 -0
  35. kdtest_pw/data/static/parameters.json +24 -0
  36. kdtest_pw/plugins/__init__.py +6 -0
  37. kdtest_pw/plugins/element_plus_plugin/__init__.py +5 -0
  38. kdtest_pw/plugins/element_plus_plugin/elementData/elementData.yaml +144 -0
  39. kdtest_pw/plugins/element_plus_plugin/element_plus_plugin.py +237 -0
  40. kdtest_pw/plugins/element_plus_plugin/my.ini +23 -0
  41. kdtest_pw/plugins/plugin_base.py +180 -0
  42. kdtest_pw/plugins/plugin_loader.py +260 -0
  43. kdtest_pw/product.py +5 -0
  44. kdtest_pw/reference.py +99 -0
  45. kdtest_pw/utils/__init__.py +13 -0
  46. kdtest_pw/utils/built_in_function.py +376 -0
  47. kdtest_pw/utils/decorator.py +211 -0
  48. kdtest_pw/utils/log/__init__.py +6 -0
  49. kdtest_pw/utils/log/html_report.py +336 -0
  50. kdtest_pw/utils/log/logger.py +123 -0
  51. kdtest_pw/utils/public_script.py +366 -0
  52. kdtest_pw-2.0.0.dist-info/METADATA +169 -0
  53. kdtest_pw-2.0.0.dist-info/RECORD +57 -0
  54. kdtest_pw-2.0.0.dist-info/WHEEL +5 -0
  55. kdtest_pw-2.0.0.dist-info/entry_points.txt +2 -0
  56. kdtest_pw-2.0.0.dist-info/licenses/LICENSE +21 -0
  57. kdtest_pw-2.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,366 @@
1
+ """公共逻辑方法"""
2
+
3
+ import os
4
+ import json
5
+ import hashlib
6
+ from typing import Any, Dict, List, Optional
7
+ from pathlib import Path
8
+
9
+ from ..reference import INFO
10
+
11
+
12
+ class PublicScript:
13
+ """公共脚本工具类
14
+
15
+ 提供文件操作、数据处理等公共方法。
16
+ """
17
+
18
+ # ==================== 文件操作 ====================
19
+
20
+ @staticmethod
21
+ def read_file(file_path: str, encoding: str = 'utf-8') -> str:
22
+ """读取文件内容
23
+
24
+ Args:
25
+ file_path: 文件路径
26
+ encoding: 编码
27
+
28
+ Returns:
29
+ str: 文件内容
30
+ """
31
+ with open(file_path, 'r', encoding=encoding) as f:
32
+ return f.read()
33
+
34
+ @staticmethod
35
+ def write_file(file_path: str, content: str, encoding: str = 'utf-8') -> None:
36
+ """写入文件
37
+
38
+ Args:
39
+ file_path: 文件路径
40
+ content: 内容
41
+ encoding: 编码
42
+ """
43
+ Path(file_path).parent.mkdir(parents=True, exist_ok=True)
44
+ with open(file_path, 'w', encoding=encoding) as f:
45
+ f.write(content)
46
+
47
+ @staticmethod
48
+ def append_file(file_path: str, content: str, encoding: str = 'utf-8') -> None:
49
+ """追加写入文件
50
+
51
+ Args:
52
+ file_path: 文件路径
53
+ content: 内容
54
+ encoding: 编码
55
+ """
56
+ Path(file_path).parent.mkdir(parents=True, exist_ok=True)
57
+ with open(file_path, 'a', encoding=encoding) as f:
58
+ f.write(content)
59
+
60
+ @staticmethod
61
+ def read_json(file_path: str) -> Any:
62
+ """读取 JSON 文件
63
+
64
+ Args:
65
+ file_path: 文件路径
66
+
67
+ Returns:
68
+ 解析后的 JSON 数据
69
+ """
70
+ with open(file_path, 'r', encoding='utf-8') as f:
71
+ return json.load(f)
72
+
73
+ @staticmethod
74
+ def write_json(file_path: str, data: Any, indent: int = 2) -> None:
75
+ """写入 JSON 文件
76
+
77
+ Args:
78
+ file_path: 文件路径
79
+ data: 数据
80
+ indent: 缩进
81
+ """
82
+ Path(file_path).parent.mkdir(parents=True, exist_ok=True)
83
+ with open(file_path, 'w', encoding='utf-8') as f:
84
+ json.dump(data, f, indent=indent, ensure_ascii=False)
85
+
86
+ @staticmethod
87
+ def read_yaml(file_path: str) -> Any:
88
+ """读取 YAML 文件
89
+
90
+ Args:
91
+ file_path: 文件路径
92
+
93
+ Returns:
94
+ 解析后的 YAML 数据
95
+ """
96
+ import yaml
97
+ with open(file_path, 'r', encoding='utf-8') as f:
98
+ return yaml.safe_load(f)
99
+
100
+ @staticmethod
101
+ def write_yaml(file_path: str, data: Any) -> None:
102
+ """写入 YAML 文件
103
+
104
+ Args:
105
+ file_path: 文件路径
106
+ data: 数据
107
+ """
108
+ import yaml
109
+ Path(file_path).parent.mkdir(parents=True, exist_ok=True)
110
+ with open(file_path, 'w', encoding='utf-8') as f:
111
+ yaml.dump(data, f, default_flow_style=False, allow_unicode=True)
112
+
113
+ @staticmethod
114
+ def file_exists(file_path: str) -> bool:
115
+ """检查文件是否存在
116
+
117
+ Args:
118
+ file_path: 文件路径
119
+
120
+ Returns:
121
+ bool: 是否存在
122
+ """
123
+ return Path(file_path).exists()
124
+
125
+ @staticmethod
126
+ def delete_file(file_path: str) -> bool:
127
+ """删除文件
128
+
129
+ Args:
130
+ file_path: 文件路径
131
+
132
+ Returns:
133
+ bool: 是否成功
134
+ """
135
+ try:
136
+ Path(file_path).unlink(missing_ok=True)
137
+ return True
138
+ except Exception:
139
+ return False
140
+
141
+ @staticmethod
142
+ def list_files(directory: str, pattern: str = '*') -> List[str]:
143
+ """列出目录下的文件
144
+
145
+ Args:
146
+ directory: 目录路径
147
+ pattern: 匹配模式
148
+
149
+ Returns:
150
+ List[str]: 文件路径列表
151
+ """
152
+ return [str(p) for p in Path(directory).glob(pattern)]
153
+
154
+ # ==================== 数据处理 ====================
155
+
156
+ @staticmethod
157
+ def dict_get(data: Dict, key_path: str, default: Any = None) -> Any:
158
+ """从嵌套字典获取值
159
+
160
+ Args:
161
+ data: 字典
162
+ key_path: 键路径 (用点分隔)
163
+ default: 默认值
164
+
165
+ Returns:
166
+
167
+ """
168
+ keys = key_path.split('.')
169
+ value = data
170
+
171
+ for key in keys:
172
+ if isinstance(value, dict):
173
+ value = value.get(key)
174
+ elif isinstance(value, list) and key.isdigit():
175
+ index = int(key)
176
+ value = value[index] if 0 <= index < len(value) else None
177
+ else:
178
+ return default
179
+
180
+ if value is None:
181
+ return default
182
+
183
+ return value
184
+
185
+ @staticmethod
186
+ def dict_set(data: Dict, key_path: str, value: Any) -> None:
187
+ """设置嵌套字典的值
188
+
189
+ Args:
190
+ data: 字典
191
+ key_path: 键路径
192
+ value: 值
193
+ """
194
+ keys = key_path.split('.')
195
+
196
+ for key in keys[:-1]:
197
+ if key not in data:
198
+ data[key] = {}
199
+ data = data[key]
200
+
201
+ data[keys[-1]] = value
202
+
203
+ @staticmethod
204
+ def merge_dicts(*dicts: Dict) -> Dict:
205
+ """合并多个字典
206
+
207
+ Args:
208
+ *dicts: 要合并的字典
209
+
210
+ Returns:
211
+ Dict: 合并后的字典
212
+ """
213
+ result = {}
214
+ for d in dicts:
215
+ result.update(d)
216
+ return result
217
+
218
+ @staticmethod
219
+ def list_to_dict(data: List[Dict], key: str) -> Dict:
220
+ """将列表转换为字典
221
+
222
+ Args:
223
+ data: 字典列表
224
+ key: 作为键的字段名
225
+
226
+ Returns:
227
+ Dict: 转换后的字典
228
+ """
229
+ return {item[key]: item for item in data if key in item}
230
+
231
+ # ==================== 加密工具 ====================
232
+
233
+ @staticmethod
234
+ def md5(text: str) -> str:
235
+ """MD5 加密
236
+
237
+ Args:
238
+ text: 原文
239
+
240
+ Returns:
241
+ str: MD5 值
242
+ """
243
+ return hashlib.md5(text.encode()).hexdigest()
244
+
245
+ @staticmethod
246
+ def sha256(text: str) -> str:
247
+ """SHA256 加密
248
+
249
+ Args:
250
+ text: 原文
251
+
252
+ Returns:
253
+ str: SHA256 值
254
+ """
255
+ return hashlib.sha256(text.encode()).hexdigest()
256
+
257
+ @staticmethod
258
+ def base64_encode(text: str) -> str:
259
+ """Base64 编码
260
+
261
+ Args:
262
+ text: 原文
263
+
264
+ Returns:
265
+ str: 编码后的字符串
266
+ """
267
+ import base64
268
+ return base64.b64encode(text.encode()).decode()
269
+
270
+ @staticmethod
271
+ def base64_decode(text: str) -> str:
272
+ """Base64 解码
273
+
274
+ Args:
275
+ text: 编码字符串
276
+
277
+ Returns:
278
+ str: 解码后的字符串
279
+ """
280
+ import base64
281
+ return base64.b64decode(text.encode()).decode()
282
+
283
+ # ==================== 环境变量 ====================
284
+
285
+ @staticmethod
286
+ def get_env(name: str, default: str = '') -> str:
287
+ """获取环境变量
288
+
289
+ Args:
290
+ name: 变量名
291
+ default: 默认值
292
+
293
+ Returns:
294
+ str: 环境变量值
295
+ """
296
+ return os.environ.get(name, default)
297
+
298
+ @staticmethod
299
+ def set_env(name: str, value: str) -> None:
300
+ """设置环境变量
301
+
302
+ Args:
303
+ name: 变量名
304
+ value: 值
305
+ """
306
+ os.environ[name] = value
307
+
308
+ # ==================== 验证工具 ====================
309
+
310
+ @staticmethod
311
+ def is_email(text: str) -> bool:
312
+ """验证邮箱格式
313
+
314
+ Args:
315
+ text: 文本
316
+
317
+ Returns:
318
+ bool: 是否有效
319
+ """
320
+ import re
321
+ pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
322
+ return bool(re.match(pattern, text))
323
+
324
+ @staticmethod
325
+ def is_phone(text: str) -> bool:
326
+ """验证手机号格式
327
+
328
+ Args:
329
+ text: 文本
330
+
331
+ Returns:
332
+ bool: 是否有效
333
+ """
334
+ import re
335
+ pattern = r'^1[3-9]\d{9}$'
336
+ return bool(re.match(pattern, text))
337
+
338
+ @staticmethod
339
+ def is_url(text: str) -> bool:
340
+ """验证 URL 格式
341
+
342
+ Args:
343
+ text: 文本
344
+
345
+ Returns:
346
+ bool: 是否有效
347
+ """
348
+ import re
349
+ pattern = r'^https?://[^\s/$.?#].[^\s]*$'
350
+ return bool(re.match(pattern, text, re.IGNORECASE))
351
+
352
+ @staticmethod
353
+ def is_json(text: str) -> bool:
354
+ """验证 JSON 格式
355
+
356
+ Args:
357
+ text: 文本
358
+
359
+ Returns:
360
+ bool: 是否有效
361
+ """
362
+ try:
363
+ json.loads(text)
364
+ return True
365
+ except (json.JSONDecodeError, TypeError):
366
+ return False
@@ -0,0 +1,169 @@
1
+ Metadata-Version: 2.4
2
+ Name: kdtest-pw
3
+ Version: 2.0.0
4
+ Summary: KDTest Playwright Edition - 关键字驱动测试框架,专为 Element Plus/Vue3 优化
5
+ Home-page: https://github.com/kdtest/kdtest-pw
6
+ Author: KDTest Team
7
+ Author-email: KDTest Team <kdtest@example.com>
8
+ License: MIT
9
+ Project-URL: Homepage, https://github.com/kdtest/kdtest-pw
10
+ Project-URL: Documentation, https://github.com/kdtest/kdtest-pw#readme
11
+ Project-URL: Repository, https://github.com/kdtest/kdtest-pw
12
+ Keywords: testing,automation,playwright,keyword-driven,element-plus,vue3
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Software Development :: Testing
24
+ Requires-Python: >=3.8
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: playwright>=1.40.0
28
+ Requires-Dist: openpyxl>=3.1.0
29
+ Requires-Dist: PyYAML>=6.0
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
32
+ Requires-Dist: pytest-playwright>=0.4.0; extra == "dev"
33
+ Requires-Dist: build; extra == "dev"
34
+ Requires-Dist: twine; extra == "dev"
35
+ Dynamic: author
36
+ Dynamic: home-page
37
+ Dynamic: license-file
38
+ Dynamic: requires-python
39
+
40
+ # KDTest-Playwright
41
+
42
+ 基于 Playwright 的关键字驱动测试框架,专为 Element Plus/Vue3 优化。
43
+
44
+ ## 安装
45
+
46
+ ```bash
47
+ # 从 PyPI 安装
48
+ pip install kdtest-pw
49
+
50
+ # 安装 Playwright 浏览器
51
+ playwright install chromium
52
+ ```
53
+
54
+ ## 快速开始
55
+
56
+ ### 1. 创建配置文件 `parameters.json`
57
+
58
+ ```json
59
+ {
60
+ "testCaseFile": [
61
+ {
62
+ "caseFilePath": "testCases.xlsx",
63
+ "caseItem": ["Sheet1"]
64
+ }
65
+ ],
66
+ "browser": "chromium",
67
+ "url": "http://localhost:8080",
68
+ "headless": false,
69
+ "timeout": 30000
70
+ }
71
+ ```
72
+
73
+ ### 2. 创建 Excel 测试用例
74
+
75
+ | 用例ID | 用例名称 | 描述 | 关键字 | 定位信息 | 操作值 |
76
+ |--------|----------|------|--------|----------|--------|
77
+ | TC001 | 登录测试 | | | | |
78
+ | | | 打开网站 | driver_get | | http://localhost |
79
+ | | | 输入用户名 | input_text | xpath | //input[@placeholder='账号'] | admin |
80
+ | | | 点击登录 | click_btn | css | .el-button--primary | |
81
+
82
+ ### 3. 运行测试
83
+
84
+ ```bash
85
+ # 命令行运行
86
+ kdtest-pw -c parameters.json
87
+
88
+ # 或在 Python 中使用
89
+ from kdtest_pw.cli import KDTestRunner
90
+
91
+ runner = KDTestRunner("parameters.json")
92
+ runner.setup()
93
+ runner.run()
94
+ runner.teardown()
95
+ ```
96
+
97
+ ## 核心关键字
98
+
99
+ ### 浏览器操作
100
+ - `driver_get` - 导航到 URL
101
+ - `driver_back` - 后退
102
+ - `driver_refresh` - 刷新
103
+ - `driver_close` - 关闭页面
104
+
105
+ ### 输入操作
106
+ - `input_text` - 输入文本(清除后输入)
107
+ - `input_append` - 追加输入
108
+ - `input_clear` - 清除输入
109
+
110
+ ### 点击操作
111
+ - `click_btn` - 点击元素
112
+ - `double_click` - 双击
113
+ - `right_click` - 右键点击
114
+ - `hover` - 鼠标悬停
115
+
116
+ ### 断言
117
+ - `text_assert` - 文本断言
118
+ - `title_assert` - 标题断言
119
+ - `element_visible_assert` - 可见性断言
120
+ - `element_count_assert` - 数量断言
121
+
122
+ ### Element Plus 组件
123
+ - `el_select` - 下拉选择
124
+ - `el_datepicker` - 日期选择
125
+ - `el_dialog_confirm` - 对话框确认
126
+ - `el_table_click_row` - 表格行点击
127
+ - `el_tree_click_node` - 树节点点击
128
+ - `el_cascader` - 级联选择
129
+ - `el_upload` - 文件上传
130
+ - `el_form_input` - 表单输入
131
+
132
+ ### 菜单导航
133
+ - `menu_load_data` - 加载菜单配置
134
+ - `menu_navigate` - 导航到菜单
135
+ - `menu_switch_iframe` - 切换 iframe
136
+ - `menu_exit_iframe` - 退出 iframe
137
+
138
+ ## 变量和内置函数
139
+
140
+ ### 变量引用
141
+ ```
142
+ ${varName} # 从缓存获取
143
+ ${self.param} # 自定义参数
144
+ ${env.NAME} # 环境变量
145
+ ```
146
+
147
+ ### 内置函数
148
+ ```
149
+ @today() # 今天日期
150
+ @now() # 当前时间
151
+ @random(1,100) # 随机数
152
+ @random_phone() # 随机手机号
153
+ @uuid() # UUID
154
+ ```
155
+
156
+ ## 与 kdtest (Selenium) 的区别
157
+
158
+ | 特性 | kdtest (Selenium) | kdtest-pw (Playwright) |
159
+ |------|-------------------|------------------------|
160
+ | 浏览器驱动 | 需要下载 WebDriver | 内置浏览器 |
161
+ | 等待机制 | 显式/隐式等待 | 自动等待 |
162
+ | Element Plus | 需要额外处理 | 原生支持 |
163
+ | 多标签页 | 需要切换句柄 | 原生支持 |
164
+ | 录制回放 | 无 | 支持 Trace |
165
+ | 视频录制 | 无 | 原生支持 |
166
+
167
+ ## License
168
+
169
+ MIT
@@ -0,0 +1,57 @@
1
+ kdtest_pw/__init__.py,sha256=kbWVNaPicqC4yvMR51NBCZhklpaHxoRatkVrRAqQHBw,947
2
+ kdtest_pw/common.py,sha256=8ilBred-Vza2EgzRDmjapXmKry5cYTznZyZqUzqrEAQ,2732
3
+ kdtest_pw/product.py,sha256=0xyrdLjqK-Pphmgn-d8YXb0WxVlfNY97ovCcuJ4DmN4,163
4
+ kdtest_pw/reference.py,sha256=7kmQg6sB2pxO6RVEdRuRZ1RayoNx3KZ-mVdN1M_zTZY,2082
5
+ kdtest_pw/action/__init__.py,sha256=9zJa6vGbBq788b-FLOEg5gWhf1MNXUQHNICqRemY1po,211
6
+ kdtest_pw/action/base_keyword.py,sha256=hM2cPvHUcYrkb6tdlRy5NMTbSPbN3epK5wev4tRMJWM,9082
7
+ kdtest_pw/action/key_retrieval.py,sha256=L2lrkgiHB0YHh-oNvsy0AP0gQ04YP4O460EDiHN0K-E,10433
8
+ kdtest_pw/action/page_action.py,sha256=lkCg5nkMv-XyoKc3PQv4AukT0_tLlfWxR1s9ingFpOs,31268
9
+ kdtest_pw/action/element_plus/__init__.py,sha256=e9QwNNoYY2EYgo1N5Pt8NfxcqR0qXuoSNYBLdfslieQ,612
10
+ kdtest_pw/action/element_plus/el_cascader.py,sha256=RyEeVhGsd_JKcFbQQre6o38LOBBQsFvbYcyCoN4YTzU,8006
11
+ kdtest_pw/action/element_plus/el_datepicker.py,sha256=cUqU-Xy0bYxUTttQTf_qeM3V3z8P4vZM40ihrAQpafk,9730
12
+ kdtest_pw/action/element_plus/el_dialog.py,sha256=FhATmQnc0IMtoHk987uvGtdqdOYoTqhHBGXzgjqFxSc,10077
13
+ kdtest_pw/action/element_plus/el_form.py,sha256=aOMmmaZqAON79idvf2htfdqeR7iZhdPw-HYCSE655po,13132
14
+ kdtest_pw/action/element_plus/el_menu.py,sha256=0TorgHPz4SaDybFv0F7D2jM8OlY6nNgUhEd7TEQEp3s,14562
15
+ kdtest_pw/action/element_plus/el_select.py,sha256=oVF0_l3Q8PzUhKdpH9rgo957iQcNZUJRPO3WgQKBMe8,7830
16
+ kdtest_pw/action/element_plus/el_table.py,sha256=E8MF03iuj7niuxZofa2ePao3KiqK0BCcavbPt9QNCH0,12484
17
+ kdtest_pw/action/element_plus/el_tree.py,sha256=klWCTOOryKO1YZawOX9t0o5rtZLTlTg93mxlOgh1jH4,10916
18
+ kdtest_pw/action/element_plus/el_upload.py,sha256=hRUHDWHJI2FP-XI4G3emDTkfGOxwEc8vG8dOrmV0Ods,9252
19
+ kdtest_pw/api/__init__.py,sha256=lItPmMeRbsIX2LpUDx1PgMJscjfvKzmflQp_VPZHLxM,148
20
+ kdtest_pw/api/api_keyword.py,sha256=GTvPBhpy7BJMs7Pc3JXKB3X63pPQI2vrJA1fAkE6Nh0,6909
21
+ kdtest_pw/api/request_handler.py,sha256=XC2V_MjQ4QK82ccn7sqgM8ZwBRB_fVeqeWOTsgvklLw,6150
22
+ kdtest_pw/cases/__init__.py,sha256=Imn4Kb7qzLr3oTxVE2MV2IdxA-PA2oAgfD5mSRB5oEQ,153
23
+ kdtest_pw/cases/case_collector.py,sha256=rd5y8eZrslwQu2yiYFypP0UbKJDHFvjcm2VSfM6Cj4E,5332
24
+ kdtest_pw/cases/case_executor.py,sha256=SH71wJpcc1mV4Z_bSVCOMUb8_ZQ1jq_CuGhVTSRhPJU,10884
25
+ kdtest_pw/cases/read/__init__.py,sha256=J2b6AhGd-DLbvAf0BtUeufmjpZE10x4HUeudIZuJdLE,144
26
+ kdtest_pw/cases/read/cell_handler.py,sha256=qrXhG3w6o5rI0_LHrMYbdEC4_v8WFxRMbExhE_VmYMQ,8383
27
+ kdtest_pw/cases/read/excel_reader.py,sha256=23jC-eckCJ1gt99rv851ICwL5Ohexa483bWcJyER-Mw,6711
28
+ kdtest_pw/cli/__init__.py,sha256=-HKjQDPfpt2wnCIo3s5xtSkpUQI95XrdmQ9Kp84EO6A,90
29
+ kdtest_pw/cli/run.py,sha256=PpI84objdftklPshjv3EV71UudoVxQJfIBecCL-yKm0,8839
30
+ kdtest_pw/core/__init__.py,sha256=EDzLQl-77BuP_WQE4VkoWOLm79qZk-F3z-YSMWqrTqc,203
31
+ kdtest_pw/core/browser_manager.py,sha256=gqqgzH4heAtXraVmLlyYpBcR2S4opolcPgddkN_af6E,5867
32
+ kdtest_pw/core/config_loader.py,sha256=nOYR0R4sCAd5iT2sXNTtAbS1f7KHdLwzBJtbXr2og1A,6658
33
+ kdtest_pw/core/page_context.py,sha256=yVslWCupj2TeC_VFl6ZYxnsD5ZdONdxfBnYJjfPi2H4,6726
34
+ kdtest_pw/data/__init__.py,sha256=wWdyTFTj2fSrH1vQERYXPH6crLDfj-JpsfdNhTtgu7M,76
35
+ kdtest_pw/data/init_data.py,sha256=ta_Yf0MZzgKPIKz7PidBM9Z6nsYWy4RCKQVaqvFoi3o,3277
36
+ kdtest_pw/data/static/elementData.yaml,sha256=FP9T8iOJDdj5rxjS5-H84-B7_P5SxKfSKaCPlNOkB68,1073
37
+ kdtest_pw/data/static/parameters.json,sha256=m_VYzPbDcFpLJNiNMQxnxYW_XGpL0fZw-4z1aDoApdY,536
38
+ kdtest_pw/plugins/__init__.py,sha256=omqR6rlbxObDVFf5Dz8X4i8jmNGcY_o2Hp1hqBbKVs0,138
39
+ kdtest_pw/plugins/plugin_base.py,sha256=klFSvA1v4iLgonGvWFXTe3l3eWSJYxDRdbthUCZh310,4933
40
+ kdtest_pw/plugins/plugin_loader.py,sha256=R0pRN0qaJ8SG6-_1ZObEZKDzVRmfROwnTafqKWu7sag,7595
41
+ kdtest_pw/plugins/element_plus_plugin/__init__.py,sha256=JAyqZRzv1IuW4P6UvzhdmB6VMgxwtAoexuGEGsVy178,117
42
+ kdtest_pw/plugins/element_plus_plugin/element_plus_plugin.py,sha256=vGO44XXzfWJcgQ_Kr_x2AfLRVrhNjfRV7a2VG0iwsJ0,11100
43
+ kdtest_pw/plugins/element_plus_plugin/my.ini,sha256=Aow394SfyB5nZ2lBCVIj8o-w98PCK4H6jlEKtm7knjw,520
44
+ kdtest_pw/plugins/element_plus_plugin/elementData/elementData.yaml,sha256=nFDzGqOSwXs39oqSVO7NaTrzCBlrjYJbqlzdVwi-t5Y,2451
45
+ kdtest_pw/utils/__init__.py,sha256=ga9qFiHNz-WeX9qMw9F8uHdfeuZS-bq_55I9nnDSqYc,271
46
+ kdtest_pw/utils/built_in_function.py,sha256=3xDEGOhJl0GnYr_lYQYuIbuhFdv2czAL4aGj6ci5JOE,9405
47
+ kdtest_pw/utils/decorator.py,sha256=f2jEy0fYPUiAAVTFZ6O9p2UwauwEwOZPXT0FT4jC2CM,5790
48
+ kdtest_pw/utils/public_script.py,sha256=t-p4AwZa9L7LE9abJqE594Vcaeh6N5MVb_kGqTfTpEU,8692
49
+ kdtest_pw/utils/log/__init__.py,sha256=P3LllVQCC6u1-YDuuj1KGoXwxK3pdVV4ZzJPy3cmCtk,123
50
+ kdtest_pw/utils/log/html_report.py,sha256=gfsgv8ovO175_sOa532JjXPukIYyZblT-kmgVKhHnLI,10104
51
+ kdtest_pw/utils/log/logger.py,sha256=JWeMkWQrCucmz4RygA6nZ9AbHwcp6EDGsm95jEeuv_g,3264
52
+ kdtest_pw-2.0.0.dist-info/licenses/LICENSE,sha256=CfrnDDvu_s5bfkBBJ45r6GAnsCAXHE1XespOc4Fr0Gc,1068
53
+ kdtest_pw-2.0.0.dist-info/METADATA,sha256=UgyFIBFxJoFEs5VudXOfIOFnUr9zlVjXSDLfDUaVjrc,4770
54
+ kdtest_pw-2.0.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
55
+ kdtest_pw-2.0.0.dist-info/entry_points.txt,sha256=tZyewwaBHxV6S5wb9gtHeW93hKvWoUzMH-hPae_JhZ8,53
56
+ kdtest_pw-2.0.0.dist-info/top_level.txt,sha256=ctqaSUioNrEU1ijYI5ux0Szl3txlof2UdbyEq1Pf-Yc,10
57
+ kdtest_pw-2.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ kdtest-pw = kdtest_pw.cli.run:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 KDTest Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ kdtest_pw