mangoautomation 1.1.22__py3-none-any.whl → 1.1.24__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.
Potentially problematic release.
This version of mangoautomation might be problematic. Click here for more details.
- mangoautomation/enums/__init__.py +0 -1
- mangoautomation/exceptions/__init__.py +0 -2
- mangoautomation/exceptions/error_msg.py +3 -3
- mangoautomation/mangos/__init__.py +14 -0
- mangoautomation/mangos/__pycache__/__init__.cpython-310.pyc +0 -0
- mangoautomation/mangos/mangos.cp310-win_amd64.pyd +0 -0
- mangoautomation/mangos/mangos.cp312-win_amd64.pyd +0 -0
- mangoautomation/mangos/mangos.cpython-310-darwin.so +0 -0
- mangoautomation/mangos/mangos.cpython-310-x86_64-linux-gnu.so +0 -0
- mangoautomation/mangos/mangos.cpython-312-darwin.so +0 -0
- mangoautomation/mangos/mangos.cpython-312-x86_64-linux-gnu.so +0 -0
- mangoautomation/models/__init__.py +0 -1
- mangoautomation/models/_ui_model.py +1 -0
- mangoautomation/tools/__init__.py +0 -1
- mangoautomation/tools/_uiautodev.py +1 -1
- mangoautomation/uidrives/__init__.py +2 -3
- mangoautomation/uidrives/_async_element.py +74 -48
- mangoautomation/uidrives/_base_data.py +16 -4
- mangoautomation/uidrives/_driver_object.py +7 -40
- mangoautomation/uidrives/_sync_element.py +75 -46
- mangoautomation/uidrives/android/__init__.py +2 -16
- mangoautomation/uidrives/pc/__init__.py +1 -2
- mangoautomation/uidrives/pc/element.py +1 -2
- mangoautomation/uidrives/pc/input_device.py +1 -2
- mangoautomation/uidrives/web/__init__.py +5 -0
- mangoautomation/uidrives/web/{async_web/__init__.py → _async_web.py} +82 -81
- mangoautomation/uidrives/web/{sync_web/__init__.py → _sync_web.py} +80 -74
- mangoautomation-1.1.24.dist-info/METADATA +42 -0
- mangoautomation-1.1.24.dist-info/RECORD +48 -0
- {mangoautomation-1.1.22.dist-info → mangoautomation-1.1.24.dist-info}/WHEEL +1 -1
- tests/__init__.py +0 -10
- tests/demo1.py +94 -0
- tests/get_ope.py +12 -3
- tests/test_ai_element.py +36 -0
- tests/test_ui_web.py +7 -3
- mangoautomation/uidrives/android/_application.py +0 -70
- mangoautomation/uidrives/android/_assertion.py +0 -90
- mangoautomation/uidrives/android/_customization.py +0 -15
- mangoautomation/uidrives/android/_element.py +0 -169
- mangoautomation/uidrives/android/_equipment.py +0 -151
- mangoautomation/uidrives/android/_new_android.py +0 -54
- mangoautomation/uidrives/android/_page.py +0 -116
- mangoautomation/uidrives/web/async_web/_assertion.py +0 -303
- mangoautomation/uidrives/web/async_web/_browser.py +0 -112
- mangoautomation/uidrives/web/async_web/_customization.py +0 -14
- mangoautomation/uidrives/web/async_web/_element.py +0 -250
- mangoautomation/uidrives/web/async_web/_input_device.py +0 -82
- mangoautomation/uidrives/web/async_web/_new_browser.py +0 -153
- mangoautomation/uidrives/web/async_web/_page.py +0 -63
- mangoautomation/uidrives/web/sync_web/_assertion.py +0 -304
- mangoautomation/uidrives/web/sync_web/_browser.py +0 -112
- mangoautomation/uidrives/web/sync_web/_customization.py +0 -14
- mangoautomation/uidrives/web/sync_web/_element.py +0 -250
- mangoautomation/uidrives/web/sync_web/_input_device.py +0 -80
- mangoautomation/uidrives/web/sync_web/_new_browser.py +0 -153
- mangoautomation/uidrives/web/sync_web/_page.py +0 -61
- mangoautomation-1.1.22.dist-info/METADATA +0 -34
- mangoautomation-1.1.22.dist-info/RECORD +0 -59
- {mangoautomation-1.1.22.dist-info → mangoautomation-1.1.24.dist-info/licenses}/LICENSE +0 -0
- {mangoautomation-1.1.22.dist-info → mangoautomation-1.1.24.dist-info}/top_level.txt +0 -0
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
# @Project: 芒果测试平台
|
|
3
|
-
# @Description:
|
|
4
|
-
# @Time : 03-09-09 3:17
|
|
5
|
-
# @Author : 毛鹏
|
|
6
|
-
from time import sleep
|
|
7
|
-
|
|
8
|
-
from mangotools.decorator import sync_method_callback
|
|
9
|
-
from mangotools.models import MethodModel
|
|
10
|
-
from ...tools import Meta
|
|
11
|
-
from ...uidrives._base_data import BaseData
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class AndroidEquipment(metaclass=Meta):
|
|
15
|
-
"""设备操作"""
|
|
16
|
-
|
|
17
|
-
def __init__(self, base_data: BaseData):
|
|
18
|
-
self.base_data = base_data
|
|
19
|
-
|
|
20
|
-
@sync_method_callback('android', '设备操作', 1, [
|
|
21
|
-
MethodModel(n='等待时间', f='_time', p='请输入等待时间', d=True)])
|
|
22
|
-
def a_sleep(self, time_: int):
|
|
23
|
-
"""强制等待"""
|
|
24
|
-
sleep(time_)
|
|
25
|
-
|
|
26
|
-
@sync_method_callback('android', '设备操作', 2)
|
|
27
|
-
def a_screen_on(self):
|
|
28
|
-
"""打开屏幕"""
|
|
29
|
-
self.base_data.android.screen_on()
|
|
30
|
-
self.a_sleep(1)
|
|
31
|
-
|
|
32
|
-
@sync_method_callback('android', '设备操作', 3)
|
|
33
|
-
def a_screen_off(self):
|
|
34
|
-
"""关闭屏幕"""
|
|
35
|
-
self.base_data.android.screen_off()
|
|
36
|
-
self.a_sleep(1)
|
|
37
|
-
|
|
38
|
-
@sync_method_callback('android', '设备操作', 4)
|
|
39
|
-
def a_swipe_left(self):
|
|
40
|
-
"""获取屏幕开关状态"""
|
|
41
|
-
self.base_data.android.info.get('screenOn')
|
|
42
|
-
|
|
43
|
-
@sync_method_callback('android', '设备操作', 5)
|
|
44
|
-
def a_get_window_size(self):
|
|
45
|
-
"""提取屏幕尺寸"""
|
|
46
|
-
w, h = self.base_data.android.window_size()
|
|
47
|
-
return w, h
|
|
48
|
-
|
|
49
|
-
@sync_method_callback('android', '设备操作', 6, [
|
|
50
|
-
MethodModel(n='文件路径', f='file_path', p='请输入计算机文件路径', d=True),
|
|
51
|
-
MethodModel(n='手机目录', f='catalogue', p='请输入设备目录', d=True)])
|
|
52
|
-
def a_push(self, file_path, catalogue):
|
|
53
|
-
"""推送一个文件到设备"""
|
|
54
|
-
self.base_data.android.push(file_path, catalogue)
|
|
55
|
-
|
|
56
|
-
@sync_method_callback('android', '设备操作', 7, [
|
|
57
|
-
MethodModel(n='文件路径', f='feli_path', p='请输入设备文件路径', d=True),
|
|
58
|
-
MethodModel(n='手机目录', f='catalogue', p='请输入计算机目录', d=True)])
|
|
59
|
-
def a_pull(self, feli_path, catalogue):
|
|
60
|
-
"""提取文件"""
|
|
61
|
-
self.base_data.android.pull(feli_path, catalogue)
|
|
62
|
-
|
|
63
|
-
@sync_method_callback('android', '设备操作', 8)
|
|
64
|
-
def a_unlock(self):
|
|
65
|
-
"""解锁屏幕"""
|
|
66
|
-
self.base_data.android.unlock()
|
|
67
|
-
|
|
68
|
-
@sync_method_callback('android', '设备操作', 9)
|
|
69
|
-
def a_press_home(self):
|
|
70
|
-
"""按home键"""
|
|
71
|
-
self.base_data.android.press('home')
|
|
72
|
-
|
|
73
|
-
@sync_method_callback('android', '设备操作', 10)
|
|
74
|
-
def a_press_back(self):
|
|
75
|
-
"""按back键"""
|
|
76
|
-
self.base_data.android.press('back')
|
|
77
|
-
|
|
78
|
-
@sync_method_callback('android', '设备操作', 11)
|
|
79
|
-
def a_press_left(self):
|
|
80
|
-
"""按left键"""
|
|
81
|
-
self.base_data.android.press('left')
|
|
82
|
-
|
|
83
|
-
@sync_method_callback('android', '设备操作', 12)
|
|
84
|
-
def a_press_right(self):
|
|
85
|
-
"""按right键"""
|
|
86
|
-
self.base_data.android.press('right')
|
|
87
|
-
|
|
88
|
-
@sync_method_callback('android', '设备操作', 13)
|
|
89
|
-
def a_press_up(self):
|
|
90
|
-
"""按up键"""
|
|
91
|
-
self.base_data.android.press('up')
|
|
92
|
-
|
|
93
|
-
@sync_method_callback('android', '设备操作', 14)
|
|
94
|
-
def a_press_down(self):
|
|
95
|
-
"""按down键"""
|
|
96
|
-
self.base_data.android.press('down')
|
|
97
|
-
|
|
98
|
-
@sync_method_callback('android', '设备操作', 15)
|
|
99
|
-
def a_press_center(self):
|
|
100
|
-
"""按center键"""
|
|
101
|
-
self.base_data.android.press('center')
|
|
102
|
-
|
|
103
|
-
@sync_method_callback('android', '设备操作', 16)
|
|
104
|
-
def a_press_menu(self):
|
|
105
|
-
"""按menu键"""
|
|
106
|
-
self.base_data.android.press('menu')
|
|
107
|
-
|
|
108
|
-
@sync_method_callback('android', '设备操作', 17)
|
|
109
|
-
def a_press_search(self):
|
|
110
|
-
"""按search键"""
|
|
111
|
-
self.base_data.android.press('search')
|
|
112
|
-
|
|
113
|
-
@sync_method_callback('android', '设备操作', 18)
|
|
114
|
-
def a_press_enter(self):
|
|
115
|
-
"""按enter键"""
|
|
116
|
-
self.base_data.android.press('enter')
|
|
117
|
-
|
|
118
|
-
@sync_method_callback('android', '设备操作', 19)
|
|
119
|
-
def a_press_delete(self):
|
|
120
|
-
"""按delete键"""
|
|
121
|
-
self.base_data.android.press('delete')
|
|
122
|
-
|
|
123
|
-
@sync_method_callback('android', '设备操作', 20)
|
|
124
|
-
def a_press_recent(self):
|
|
125
|
-
"""按recent键"""
|
|
126
|
-
self.base_data.android.press('recent')
|
|
127
|
-
|
|
128
|
-
@sync_method_callback('android', '设备操作', 21)
|
|
129
|
-
def a_press_volume_up(self):
|
|
130
|
-
"""按volume_up键"""
|
|
131
|
-
self.base_data.android.press('volume_up')
|
|
132
|
-
|
|
133
|
-
@sync_method_callback('android', '设备操作', 22)
|
|
134
|
-
def a_press_volume_down(self):
|
|
135
|
-
"""按volume_down键"""
|
|
136
|
-
self.base_data.android.press('volume_down')
|
|
137
|
-
|
|
138
|
-
@sync_method_callback('android', '设备操作', 23)
|
|
139
|
-
def a_press_volume_mute(self):
|
|
140
|
-
"""按volume_mute键"""
|
|
141
|
-
self.base_data.android.press('volume_mute')
|
|
142
|
-
|
|
143
|
-
@sync_method_callback('android', '设备操作', 24)
|
|
144
|
-
def a_press_camera(self):
|
|
145
|
-
"""按camera键"""
|
|
146
|
-
self.base_data.android.press('camera')
|
|
147
|
-
|
|
148
|
-
@sync_method_callback('android', '设备操作', 25)
|
|
149
|
-
def a_press_power(self):
|
|
150
|
-
"""按power键"""
|
|
151
|
-
self.base_data.android.press('power')
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
# @Project: 芒果测试平台
|
|
3
|
-
# @Description:
|
|
4
|
-
# @Time : 2024-05-23 15:05
|
|
5
|
-
# @Author : 毛鹏
|
|
6
|
-
|
|
7
|
-
from typing import Optional
|
|
8
|
-
|
|
9
|
-
import uiautomator2 as u2
|
|
10
|
-
from adbutils import AdbTimeout
|
|
11
|
-
from uiautomator2 import ConnectError
|
|
12
|
-
|
|
13
|
-
from ...exceptions import MangoAutomationError
|
|
14
|
-
from ...exceptions.error_msg import ERROR_MSG_0042, ERROR_MSG_0045, ERROR_MSG_0040
|
|
15
|
-
|
|
16
|
-
"""
|
|
17
|
-
python -m uiautomator2 init
|
|
18
|
-
python -m weditor
|
|
19
|
-
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class NewAndroid:
|
|
24
|
-
|
|
25
|
-
def __init__(self, and_equipment):
|
|
26
|
-
self.and_equipment = and_equipment
|
|
27
|
-
self.info: Optional[dict | None] = None
|
|
28
|
-
self.example_dict = []
|
|
29
|
-
|
|
30
|
-
def new_android(self):
|
|
31
|
-
if self.and_equipment is None:
|
|
32
|
-
raise MangoAutomationError(*ERROR_MSG_0042)
|
|
33
|
-
try:
|
|
34
|
-
|
|
35
|
-
android = u2.connect(self.and_equipment)
|
|
36
|
-
self.info = android.info
|
|
37
|
-
# msg = f"设备启动成功!产品名称:{self.info.get('productName')}"
|
|
38
|
-
self.example_dict.append({
|
|
39
|
-
'config': self.and_equipment,
|
|
40
|
-
'info': self.info,
|
|
41
|
-
'android': android
|
|
42
|
-
})
|
|
43
|
-
except ConnectError:
|
|
44
|
-
raise MangoAutomationError(*ERROR_MSG_0040, value=(self.and_equipment,))
|
|
45
|
-
except RuntimeError:
|
|
46
|
-
raise MangoAutomationError(*ERROR_MSG_0045, value=(self.and_equipment,))
|
|
47
|
-
except (AdbTimeout, TimeoutError):
|
|
48
|
-
raise MangoAutomationError(*ERROR_MSG_0040, value=(self.and_equipment,))
|
|
49
|
-
else:
|
|
50
|
-
android.implicitly_wait(10)
|
|
51
|
-
return android
|
|
52
|
-
|
|
53
|
-
def close_android(self):
|
|
54
|
-
pass
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
# @Project: 芒果测试平台
|
|
3
|
-
# @Description: # @Time : 2023/4/6 13:31
|
|
4
|
-
# @Author : 毛鹏
|
|
5
|
-
import os.path
|
|
6
|
-
|
|
7
|
-
from uiautomator2 import Direction
|
|
8
|
-
|
|
9
|
-
from mangotools.decorator import sync_method_callback
|
|
10
|
-
from mangotools.models import MethodModel
|
|
11
|
-
from ...tools import Meta
|
|
12
|
-
from ...uidrives._base_data import BaseData
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class AndroidPage(metaclass=Meta):
|
|
16
|
-
"""页面操作"""
|
|
17
|
-
|
|
18
|
-
def __init__(self, base_data: BaseData):
|
|
19
|
-
self.base_data = base_data
|
|
20
|
-
|
|
21
|
-
@sync_method_callback('android', '页面操作', 1)
|
|
22
|
-
def a_swipe_right(self):
|
|
23
|
-
"""右滑"""
|
|
24
|
-
self.base_data.android.swipe_ext(Direction.HORIZ_FORWARD)
|
|
25
|
-
|
|
26
|
-
@sync_method_callback('android', '页面操作', 2)
|
|
27
|
-
def a_swipe_left(self):
|
|
28
|
-
"""左滑"""
|
|
29
|
-
self.base_data.android.swipe_ext(Direction.HORIZ_BACKWARD)
|
|
30
|
-
|
|
31
|
-
@sync_method_callback('android', '页面操作', 3)
|
|
32
|
-
def a_swipe_up(self):
|
|
33
|
-
"""上滑"""
|
|
34
|
-
self.base_data.android.swipe_ext(Direction.FORWARD)
|
|
35
|
-
|
|
36
|
-
@sync_method_callback('android', '页面操作', 4)
|
|
37
|
-
def a_swipe_down(self):
|
|
38
|
-
"""下滑"""
|
|
39
|
-
self.base_data.android.swipe_ext(Direction.BACKWARD)
|
|
40
|
-
|
|
41
|
-
@sync_method_callback('android', '页面操作', 5, [
|
|
42
|
-
MethodModel(n='当前x', f='sx', p='请输入sx坐标', d=True),
|
|
43
|
-
MethodModel(n='当前y', f='sy', p='请输入sy坐标', d=True),
|
|
44
|
-
MethodModel(n='目标x', f='ex', p='请输入ex坐标', d=True),
|
|
45
|
-
MethodModel(n='目标y', f='ey', p='请输入ey坐标', d=True)])
|
|
46
|
-
def a_swipe(self, sx, sy, ex, ey):
|
|
47
|
-
"""坐标滑动"""
|
|
48
|
-
self.base_data.android.swipe(sx, sy, ex, ey, 0.5)
|
|
49
|
-
|
|
50
|
-
@sync_method_callback('android', '页面操作', 6, [
|
|
51
|
-
MethodModel(n='当前x', f='sx', p='请输入sx坐标', d=True),
|
|
52
|
-
MethodModel(n='当前y', f='sy', p='请输入sy坐标', d=True),
|
|
53
|
-
MethodModel(n='目标x', f='ex', p='请输入ex坐标', d=True),
|
|
54
|
-
MethodModel(n='目标y', f='ey', p='请输入ey坐标', d=True)])
|
|
55
|
-
def a_drag(self, sx, sy, ex, ey):
|
|
56
|
-
"""坐标拖动"""
|
|
57
|
-
self.base_data.android.drag(sx, sy, ex, ey, 0.5)
|
|
58
|
-
|
|
59
|
-
@sync_method_callback('android', '页面操作', 7)
|
|
60
|
-
def a_open_quick_settings(self):
|
|
61
|
-
"""打开快速通知"""
|
|
62
|
-
self.base_data.android.open_quick_settings()
|
|
63
|
-
|
|
64
|
-
@sync_method_callback('android', '页面操作', 8, [
|
|
65
|
-
MethodModel(n='文件名称', f='file_name', p='请输入截图文件名称', d=True)])
|
|
66
|
-
def a_screenshot(self, file_name: str):
|
|
67
|
-
"""屏幕截图"""
|
|
68
|
-
self.base_data.android.screenshot(filename=os.path.join(self.base_data.screenshot_path, file_name))
|
|
69
|
-
|
|
70
|
-
@sync_method_callback('android', '页面操作', 9, [
|
|
71
|
-
MethodModel(n='x坐标', f='x', p='请输入按下的x坐标', d=True),
|
|
72
|
-
MethodModel(n='y坐标', f='y', p='请输入按下的x坐标', d=True),
|
|
73
|
-
MethodModel(n='长按时间', f='time_', p='请输入长按时间', d=True)])
|
|
74
|
-
def a_long_click(self, x, y, time_):
|
|
75
|
-
"""长按屏幕N秒"""
|
|
76
|
-
self.base_data.android.long_click(x, y, time_)
|
|
77
|
-
|
|
78
|
-
@sync_method_callback('android', '页面操作', 10)
|
|
79
|
-
def a_set_orientation_natural(self):
|
|
80
|
-
"""设置为natural"""
|
|
81
|
-
self.base_data.android.set_orientation("natural")
|
|
82
|
-
|
|
83
|
-
@sync_method_callback('android', '页面操作', 11)
|
|
84
|
-
def a_set_orientation_left(self):
|
|
85
|
-
"""设置为natural"""
|
|
86
|
-
self.base_data.android.set_orientation("left")
|
|
87
|
-
|
|
88
|
-
@sync_method_callback('android', '页面操作', 12)
|
|
89
|
-
def a_set_orientation_right(self):
|
|
90
|
-
"""设置为right"""
|
|
91
|
-
self.base_data.android.set_orientation("right")
|
|
92
|
-
|
|
93
|
-
@sync_method_callback('android', '页面操作', 13)
|
|
94
|
-
def a_set_orientation_upsidedown(self):
|
|
95
|
-
"""设置为upsidedown"""
|
|
96
|
-
self.base_data.android.set_orientation("upsidedown")
|
|
97
|
-
|
|
98
|
-
@sync_method_callback('android', '页面操作', 14)
|
|
99
|
-
def a_freeze_rotation(self):
|
|
100
|
-
"""冻结旋转"""
|
|
101
|
-
self.base_data.android.freeze_rotation()
|
|
102
|
-
|
|
103
|
-
@sync_method_callback('android', '页面操作', 15)
|
|
104
|
-
def a_freeze_rotation_false(self):
|
|
105
|
-
"""取消冻结旋转"""
|
|
106
|
-
self.base_data.android.freeze_rotation(False)
|
|
107
|
-
|
|
108
|
-
@sync_method_callback('android', '页面操作', 16)
|
|
109
|
-
def a_dump_hierarchy(self):
|
|
110
|
-
"""获取转储的内容"""
|
|
111
|
-
return self.base_data.android.dump_hierarchy()
|
|
112
|
-
|
|
113
|
-
@sync_method_callback('android', '页面操作', 17)
|
|
114
|
-
def a_open_notification(self):
|
|
115
|
-
"""打开通知"""
|
|
116
|
-
return self.base_data.android.dump_hierarchy()
|
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
# @Project: 芒果测试平台
|
|
3
|
-
# @Description: # @Time : 2023-04-26 22:25
|
|
4
|
-
# @Author : 毛鹏
|
|
5
|
-
|
|
6
|
-
from playwright.async_api import Locator, expect as exp
|
|
7
|
-
|
|
8
|
-
from mangotools.decorator import async_method_callback
|
|
9
|
-
from mangotools.models import MethodModel
|
|
10
|
-
from ....exceptions import MangoAutomationError
|
|
11
|
-
from ....exceptions.error_msg import ERROR_MSG_0021
|
|
12
|
-
from ....tools import Meta
|
|
13
|
-
from ....uidrives._base_data import BaseData
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class AsyncWebAssertion(metaclass=Meta):
|
|
17
|
-
"""元素断言"""
|
|
18
|
-
|
|
19
|
-
def __init__(self, base_data: BaseData):
|
|
20
|
-
self.base_data = base_data
|
|
21
|
-
|
|
22
|
-
@async_method_callback('ass_web', '元素断言', 0, [
|
|
23
|
-
MethodModel(f='actual'),
|
|
24
|
-
MethodModel(n='预期值', f='expect', p='请输入元素个数', d=True)])
|
|
25
|
-
async def w_to_have_count(self, actual: Locator, expect: str):
|
|
26
|
-
"""元素是几个"""
|
|
27
|
-
try:
|
|
28
|
-
await exp(actual).to_have_count(int(expect))
|
|
29
|
-
except AssertionError as e:
|
|
30
|
-
raise AssertionError(f'实际={await actual.count()}, 预期={expect}') from e
|
|
31
|
-
return f'实际={await actual.count()}, 预期={expect}'
|
|
32
|
-
|
|
33
|
-
@async_method_callback('ass_web', '元素断言', 1, [MethodModel(f='actual')])
|
|
34
|
-
async def w_all_not_to_be_empty(self, actual: Locator):
|
|
35
|
-
"""元素存在"""
|
|
36
|
-
count = await actual.count()
|
|
37
|
-
if count == 0:
|
|
38
|
-
assert False, f'实际={count}, 预期>0'
|
|
39
|
-
return f'实际={count}, 预期>0'
|
|
40
|
-
|
|
41
|
-
@async_method_callback('ass_web', '元素断言', 1, [
|
|
42
|
-
MethodModel(f='actual'),
|
|
43
|
-
MethodModel(n='预期值', f='expect', p='请输入元素存输入1,不存输入0', d=True)])
|
|
44
|
-
async def w_to_element_count(self, actual: Locator, expect: int):
|
|
45
|
-
"""元素是否存在"""
|
|
46
|
-
if int(expect) == 0:
|
|
47
|
-
assert actual is None, f'实际={actual}, 预期={expect}'
|
|
48
|
-
return f'实际={actual}, 预期={expect}'
|
|
49
|
-
|
|
50
|
-
else:
|
|
51
|
-
if actual:
|
|
52
|
-
try:
|
|
53
|
-
await exp(actual).to_have_count(int(expect))
|
|
54
|
-
return f'实际={actual.count()}, 预期={expect}'
|
|
55
|
-
except AssertionError as e:
|
|
56
|
-
raise AssertionError(f'实际={actual.count()}, 预期={expect}') from e
|
|
57
|
-
else:
|
|
58
|
-
raise MangoAutomationError(*ERROR_MSG_0021)
|
|
59
|
-
|
|
60
|
-
@async_method_callback('ass_web', '元素断言', 2, [
|
|
61
|
-
MethodModel(f='actual'),
|
|
62
|
-
MethodModel(n='预期值', f='expect', p='请输入不包含的文本', d=True)])
|
|
63
|
-
async def w_not_to_contain_text(self, actual: Locator, expect: str):
|
|
64
|
-
"""元素不包含文本"""
|
|
65
|
-
try:
|
|
66
|
-
await exp(actual).not_to_contain_text(expect)
|
|
67
|
-
except AssertionError as e:
|
|
68
|
-
raise AssertionError(f'实际={actual}, 预期={expect}') from e
|
|
69
|
-
return f'实际={actual}, 预期={expect}'
|
|
70
|
-
|
|
71
|
-
@async_method_callback('ass_web', '元素断言', 3, [MethodModel(f='actual')])
|
|
72
|
-
async def w_not_to_be_empty(self, actual: Locator):
|
|
73
|
-
"""元素不为空"""
|
|
74
|
-
try:
|
|
75
|
-
await exp(actual).not_to_be_empty()
|
|
76
|
-
except AssertionError as e:
|
|
77
|
-
raise AssertionError(f'实际={actual}, 预期=不为空') from e
|
|
78
|
-
return f'实际={actual}, 预期=不为空'
|
|
79
|
-
|
|
80
|
-
@async_method_callback('ass_web', '元素断言', 4, [MethodModel(f='actual')])
|
|
81
|
-
async def w_not_to_be_enabled(self, actual: Locator):
|
|
82
|
-
"""元素不启用"""
|
|
83
|
-
try:
|
|
84
|
-
await exp(actual).not_to_be_enabled()
|
|
85
|
-
except AssertionError as e:
|
|
86
|
-
raise AssertionError(f'实际={actual}, 预期=不启用') from e
|
|
87
|
-
return f'实际={actual}, 预期=不启用'
|
|
88
|
-
|
|
89
|
-
@async_method_callback('ass_web', '元素断言', 5, [MethodModel(f='actual')])
|
|
90
|
-
async def w_not_to_be_focused(self, actual: Locator):
|
|
91
|
-
"""元素不聚焦"""
|
|
92
|
-
try:
|
|
93
|
-
await exp(actual).not_to_be_focused()
|
|
94
|
-
except AssertionError as e:
|
|
95
|
-
raise AssertionError(f'实际={actual}, 预期=不聚焦') from e
|
|
96
|
-
return f'实际={actual}, 预期=不聚焦'
|
|
97
|
-
|
|
98
|
-
@async_method_callback('ass_web', '元素断言', 6, [MethodModel(f='actual')])
|
|
99
|
-
async def w_not_to_be_hidden(self, actual: Locator):
|
|
100
|
-
"""元素不可隐藏"""
|
|
101
|
-
try:
|
|
102
|
-
await exp(actual).not_to_be_hidden()
|
|
103
|
-
except AssertionError as e:
|
|
104
|
-
raise AssertionError(f'实际={actual}, 预期=不可隐藏') from e
|
|
105
|
-
return f'实际={actual}, 预期=不可隐藏'
|
|
106
|
-
|
|
107
|
-
@async_method_callback('ass_web', '元素断言', 7, [MethodModel(f='actual')])
|
|
108
|
-
async def w_not_to_be_in_viewport(self, actual: Locator):
|
|
109
|
-
"""元素不在视窗中"""
|
|
110
|
-
try:
|
|
111
|
-
await exp(actual).not_to_be_in_viewport()
|
|
112
|
-
except AssertionError as e:
|
|
113
|
-
raise AssertionError(f'实际={actual}, 预期=不在视窗中') from e
|
|
114
|
-
return f'实际={actual}, 预期=不在视窗中'
|
|
115
|
-
|
|
116
|
-
@async_method_callback('ass_web', '元素断言', 8, [MethodModel(f='actual')])
|
|
117
|
-
async def w_not_to_be_visible(self, actual: Locator):
|
|
118
|
-
"""元素不可见"""
|
|
119
|
-
try:
|
|
120
|
-
await exp(actual).not_to_be_visible()
|
|
121
|
-
except AssertionError as e:
|
|
122
|
-
raise AssertionError(f'实际={actual}, 预期=不可见') from e
|
|
123
|
-
return f'实际={actual}, 预期=不可见'
|
|
124
|
-
|
|
125
|
-
@async_method_callback('ass_web', '元素断言', 9, [
|
|
126
|
-
MethodModel(f='actual'),
|
|
127
|
-
MethodModel(n='预期值', f='expect', p='请输入样式', d=True)])
|
|
128
|
-
async def w_not_to_have_class(self, actual: Locator, expect: str):
|
|
129
|
-
"""元素没有阶级"""
|
|
130
|
-
try:
|
|
131
|
-
await exp(actual).not_to_have_class(expect)
|
|
132
|
-
except AssertionError as e:
|
|
133
|
-
raise AssertionError(f'实际={actual}, 预期=没有阶级') from e
|
|
134
|
-
return f'实际={actual}, 预期=没有阶级'
|
|
135
|
-
|
|
136
|
-
@async_method_callback('ass_web', '元素断言', 10, [MethodModel(f='actual')])
|
|
137
|
-
async def w_to_be_checked(self, actual: Locator):
|
|
138
|
-
"""复选框已选中"""
|
|
139
|
-
try:
|
|
140
|
-
await exp(actual).to_be_checked()
|
|
141
|
-
except AssertionError as e:
|
|
142
|
-
raise AssertionError(f'实际={actual}, 预期=复选框已选中') from e
|
|
143
|
-
return f'实际={actual}, 预期=复选框已选中'
|
|
144
|
-
|
|
145
|
-
@async_method_callback('ass_web', '元素断言', 11, [MethodModel(f='actual')])
|
|
146
|
-
async def w_to_be_disabled(self, actual: Locator):
|
|
147
|
-
"""元素已禁用"""
|
|
148
|
-
try:
|
|
149
|
-
await exp(actual).to_be_disabled()
|
|
150
|
-
except AssertionError as e:
|
|
151
|
-
raise AssertionError(f'实际={actual}, 预期=已禁用') from e
|
|
152
|
-
return f'实际={actual}, 预期=已禁用'
|
|
153
|
-
|
|
154
|
-
@async_method_callback('ass_web', '元素断言', 12, [MethodModel(f='actual')])
|
|
155
|
-
async def w_not_to_be_editable(self, actual: Locator):
|
|
156
|
-
"""元素已启用"""
|
|
157
|
-
try:
|
|
158
|
-
await exp(actual).to_be_editable()
|
|
159
|
-
except AssertionError as e:
|
|
160
|
-
raise AssertionError(f'实际={actual}, 预期=已启用') from e
|
|
161
|
-
return f'实际={actual}, 预期=已启用'
|
|
162
|
-
|
|
163
|
-
@async_method_callback('ass_web', '元素断言', 13, [MethodModel(f='actual')])
|
|
164
|
-
async def w_to_be_empty(self, actual: Locator | list | None):
|
|
165
|
-
"""元素为空"""
|
|
166
|
-
if actual is None:
|
|
167
|
-
assert True, f'实际={actual}, 预期=为空'
|
|
168
|
-
return f'实际={actual}, 预期=为空'
|
|
169
|
-
else:
|
|
170
|
-
try:
|
|
171
|
-
await exp(actual).to_be_empty()
|
|
172
|
-
return f'实际={actual}, 预期=为空'
|
|
173
|
-
except AssertionError as e:
|
|
174
|
-
raise AssertionError(f'实际={actual}, 预期=为空') from e
|
|
175
|
-
|
|
176
|
-
@async_method_callback('ass_web', '元素断言', 14, [MethodModel(f='actual')])
|
|
177
|
-
async def w_to_be_visible(self, actual: Locator):
|
|
178
|
-
"""元素可见"""
|
|
179
|
-
try:
|
|
180
|
-
await exp(actual).to_be_visible()
|
|
181
|
-
except AssertionError as e:
|
|
182
|
-
raise AssertionError(f'实际={actual}, 预期=可见') from e
|
|
183
|
-
return f'实际={actual}, 预期=可见'
|
|
184
|
-
# @staticmethod
|
|
185
|
-
# async def w_not_to_have_actuals(actual: Locator, actuals: list):
|
|
186
|
-
# """选择已选择选项"""
|
|
187
|
-
# await exp(actual).to_have_actuals(actuals)
|
|
188
|
-
|
|
189
|
-
# @staticmethod
|
|
190
|
-
# def w_not_to_have_attribute(locating: Locator, name: str, actual: str):
|
|
191
|
-
# """元素不具有属性"""
|
|
192
|
-
# exp(locating).not_to_have_attribute(name, actual)
|
|
193
|
-
# @staticmethod
|
|
194
|
-
|
|
195
|
-
# @staticmethod
|
|
196
|
-
# def w_not_to_have_css(locating: Locator, name: str, actual: str):
|
|
197
|
-
# """元素不使用CSS"""
|
|
198
|
-
# exp(locating).not_to_have_css(name, actual)
|
|
199
|
-
|
|
200
|
-
# @staticmethod
|
|
201
|
-
# def w_not_to_have_id(locating: Locator, _id: str):
|
|
202
|
-
# """元素没有ID"""
|
|
203
|
-
# exp(locating).not_to_have_id(_id)
|
|
204
|
-
#
|
|
205
|
-
# @staticmethod
|
|
206
|
-
# def w_not_to_have_js_property(locating: Locator, name: str, actual):
|
|
207
|
-
# """元素不具有js属性"""
|
|
208
|
-
# exp(locating).not_to_have_js_property(name, actual)
|
|
209
|
-
#
|
|
210
|
-
# @staticmethod
|
|
211
|
-
# def w_not_to_have_text(locating: Locator, expected: str):
|
|
212
|
-
# """元素没有文本"""
|
|
213
|
-
# exp(locating).not_to_have_text(expected)
|
|
214
|
-
|
|
215
|
-
# @staticmethod
|
|
216
|
-
# def w_not_to_have_actual(locating: Locator, actual: str):
|
|
217
|
-
# """元素无价值"""
|
|
218
|
-
# exp(locating).not_to_have_actual(actual)
|
|
219
|
-
|
|
220
|
-
#
|
|
221
|
-
# def w_to_be_attached(self, hidden_text: str):
|
|
222
|
-
# """待连接"""
|
|
223
|
-
# exp(self.page.get_by_text(hidden_text)).to_be_attached()
|
|
224
|
-
|
|
225
|
-
#
|
|
226
|
-
# def w_to_be_editable(self, hidden_text: str):
|
|
227
|
-
# """可编辑"""
|
|
228
|
-
# locator = self.page.get_by_role("textbox")
|
|
229
|
-
# exp(locator).to_be_editable()
|
|
230
|
-
|
|
231
|
-
# def w_to_be_enabled(self, hidden_text: str):
|
|
232
|
-
# """为空"""
|
|
233
|
-
# locator = self.page.locator("button.submit")
|
|
234
|
-
# exp(locator).to_be_enabled()
|
|
235
|
-
|
|
236
|
-
# def w_to_be_focused(self, hidden_text: str):
|
|
237
|
-
# """聚焦"""
|
|
238
|
-
# locator = self.page.get_by_role("textbox")
|
|
239
|
-
# exp(locator).to_be_focused()
|
|
240
|
-
#
|
|
241
|
-
# def w_to_be_hidden(self, hidden_text: str):
|
|
242
|
-
# """隐藏"""
|
|
243
|
-
# locator = self.page.locator('.my-element')
|
|
244
|
-
# exp(locator).to_be_hidden()
|
|
245
|
-
#
|
|
246
|
-
# def w_to_be_in_viewport(self, hidden_text: str):
|
|
247
|
-
# """待在视口中"""
|
|
248
|
-
# locator = self.page.get_by_role("button")
|
|
249
|
-
# # Make sure at least some part of element intersects viewport.
|
|
250
|
-
# exp(locator).to_be_in_viewport()
|
|
251
|
-
# # Make sure element is fully outside of viewport.
|
|
252
|
-
# exp(locator).not_to_be_in_viewport()
|
|
253
|
-
# # Make sure that at least half of the element intersects viewport.
|
|
254
|
-
# exp(locator).to_be_in_viewport(ratio=0.5)
|
|
255
|
-
#
|
|
256
|
-
|
|
257
|
-
# def w_to_contain_text(self, hidden_text: str):
|
|
258
|
-
# """包含文本"""
|
|
259
|
-
# locator = self.page.locator('.title')
|
|
260
|
-
# exp(locator).to_contain_text("substring")
|
|
261
|
-
# exp(locator).to_contain_text(re.compile(r"\d messages"))
|
|
262
|
-
#
|
|
263
|
-
# def w_to_have_attribute(self, hidden_text: str):
|
|
264
|
-
# """具有属性"""
|
|
265
|
-
# locator = self.page.locator("input")
|
|
266
|
-
# exp(locator).to_have_attribute("type", "text")
|
|
267
|
-
#
|
|
268
|
-
# def w_to_have_class(self, hidden_text: str):
|
|
269
|
-
# """到保存类别"""
|
|
270
|
-
# locator = self.page.locator("#component")
|
|
271
|
-
# exp(locator).to_have_class(re.compile(r"selected"))
|
|
272
|
-
# exp(locator).to_have_class("selected row")
|
|
273
|
-
#
|
|
274
|
-
# def w_to_have_count(self, hidden_text: str):
|
|
275
|
-
# """有计数"""
|
|
276
|
-
# locator = self.page.locator("list > .component")
|
|
277
|
-
# exp(locator).to_have_count(3)
|
|
278
|
-
#
|
|
279
|
-
# def w_to_have_css(self, hidden_text: str):
|
|
280
|
-
# """使用CSS"""
|
|
281
|
-
# locator = self.page.get_by_role("button")
|
|
282
|
-
# exp(locator).to_have_css("display", "flex")
|
|
283
|
-
#
|
|
284
|
-
# def w_to_have_id(self, hidden_text: str):
|
|
285
|
-
# """到id"""
|
|
286
|
-
# locator = self.page.get_by_role("textbox")
|
|
287
|
-
# exp(locator).to_have_id("lastname")
|
|
288
|
-
#
|
|
289
|
-
# def w_to_have_js_property(self, hidden_text: str):
|
|
290
|
-
# """拥有js属性"""
|
|
291
|
-
# locator = self.page.locator(".component")
|
|
292
|
-
# exp(locator).to_have_js_property("loaded", True)
|
|
293
|
-
#
|
|
294
|
-
# def w_to_have_text(self, hidden_text: str):
|
|
295
|
-
# """有文本"""
|
|
296
|
-
# locator = self.page.locator(".title")
|
|
297
|
-
# exp(locator).to_have_text(re.compile(r"Welcome, Test User"))
|
|
298
|
-
# exp(locator).to_have_text(re.compile(r"Welcome, .*"))
|
|
299
|
-
#
|
|
300
|
-
# def w_to_have_actual(self, hidden_text: str):
|
|
301
|
-
# """有价值"""
|
|
302
|
-
# locator = self.page.locator("input[type=number]")
|
|
303
|
-
# exp(locator).to_have_actual(re.compile(r"[0-9]"))
|