mangoautomation 1.0.58__py3-none-any.whl → 1.0.60__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/exceptions/error_msg.py +68 -0
- mangoautomation/models/__init__.py +2 -1
- mangoautomation/models/_ui_model.py +14 -7
- mangoautomation/uidrive/_async_element.py +30 -29
- mangoautomation/uidrive/_base_data.py +5 -3
- mangoautomation/uidrive/_sync_element.py +29 -28
- mangoautomation/uidrive/android/__init__.py +2 -2
- mangoautomation/uidrive/android/_application.py +9 -9
- mangoautomation/uidrive/android/_assertion.py +4 -4
- mangoautomation/uidrive/android/_element.py +16 -16
- mangoautomation/uidrive/android/_equipment.py +7 -7
- mangoautomation/uidrive/android/_new_android.py +1 -1
- mangoautomation/uidrive/android/_page.py +12 -12
- mangoautomation/uidrive/web/async_web/__init__.py +3 -4
- mangoautomation/uidrive/web/async_web/_assertion.py +5 -5
- mangoautomation/uidrive/web/async_web/_browser.py +6 -6
- mangoautomation/uidrive/web/async_web/_element.py +29 -21
- mangoautomation/uidrive/web/async_web/_input_device.py +10 -6
- mangoautomation/uidrive/web/async_web/_new_browser.py +4 -2
- mangoautomation/uidrive/web/async_web/_page.py +2 -1
- mangoautomation/uidrive/web/sync_web/__init__.py +3 -4
- mangoautomation/uidrive/web/sync_web/_assertion.py +4 -4
- mangoautomation/uidrive/web/sync_web/_browser.py +7 -6
- mangoautomation/uidrive/web/sync_web/_element.py +29 -18
- mangoautomation/uidrive/web/sync_web/_input_device.py +7 -6
- mangoautomation/uidrive/web/sync_web/_new_browser.py +4 -2
- mangoautomation/uidrive/web/sync_web/_page.py +1 -1
- mangoautomation-1.0.60.dist-info/METADATA +42 -0
- mangoautomation-1.0.60.dist-info/RECORD +59 -0
- {mangoautomation-1.0.58.dist-info → mangoautomation-1.0.60.dist-info}/WHEEL +1 -1
- tests/__init__.py +5 -0
- tests/get_ope.py +12 -0
- tests/test_ui_and.py +0 -24
- mangoautomation-1.0.58.dist-info/METADATA +0 -34
- mangoautomation-1.0.58.dist-info/RECORD +0 -57
- {mangoautomation-1.0.58.dist-info → mangoautomation-1.0.60.dist-info/licenses}/LICENSE +0 -0
- {mangoautomation-1.0.58.dist-info → mangoautomation-1.0.60.dist-info}/top_level.txt +0 -0
|
@@ -11,7 +11,7 @@ from adbutils import AdbTimeout
|
|
|
11
11
|
from uiautomator2 import ConnectError
|
|
12
12
|
|
|
13
13
|
from ...exceptions import MangoAutomationError
|
|
14
|
-
from ...exceptions.
|
|
14
|
+
from ...exceptions.error_msg import ERROR_MSG_0042, ERROR_MSG_0045, ERROR_MSG_0040
|
|
15
15
|
|
|
16
16
|
"""
|
|
17
17
|
python -m uiautomator2 init
|
|
@@ -39,19 +39,19 @@ class AndroidPage(metaclass=Meta):
|
|
|
39
39
|
self.base_data.android.swipe_ext(Direction.BACKWARD)
|
|
40
40
|
|
|
41
41
|
@sync_method_callback('android', '页面操作', 5, [
|
|
42
|
-
MethodModel(f='sx', p='请输入sx坐标', d=True),
|
|
43
|
-
MethodModel(f='sy', p='请输入sy坐标', d=True),
|
|
44
|
-
MethodModel(f='ex', p='请输入ex坐标', d=True),
|
|
45
|
-
MethodModel(f='ey', p='请输入ey坐标', d=True)])
|
|
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
46
|
def a_swipe(self, sx, sy, ex, ey):
|
|
47
47
|
"""坐标滑动"""
|
|
48
48
|
self.base_data.android.swipe(sx, sy, ex, ey, 0.5)
|
|
49
49
|
|
|
50
50
|
@sync_method_callback('android', '页面操作', 6, [
|
|
51
|
-
MethodModel(f='sx', p='请输入sx坐标', d=True),
|
|
52
|
-
MethodModel(f='sy', p='请输入sy坐标', d=True),
|
|
53
|
-
MethodModel(f='ex', p='请输入ex坐标', d=True),
|
|
54
|
-
MethodModel(f='ey', p='请输入ey坐标', d=True)])
|
|
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
55
|
def a_drag(self, sx, sy, ex, ey):
|
|
56
56
|
"""坐标拖动"""
|
|
57
57
|
self.base_data.android.drag(sx, sy, ex, ey, 0.5)
|
|
@@ -62,15 +62,15 @@ class AndroidPage(metaclass=Meta):
|
|
|
62
62
|
self.base_data.android.open_quick_settings()
|
|
63
63
|
|
|
64
64
|
@sync_method_callback('android', '页面操作', 8, [
|
|
65
|
-
MethodModel(f='file_name', p='请输入截图文件名称', d=True)])
|
|
65
|
+
MethodModel(n='文件名称', f='file_name', p='请输入截图文件名称', d=True)])
|
|
66
66
|
def a_screenshot(self, file_name: str):
|
|
67
67
|
"""屏幕截图"""
|
|
68
68
|
self.base_data.android.screenshot(filename=os.path.join(self.base_data.screenshot_path, file_name))
|
|
69
69
|
|
|
70
70
|
@sync_method_callback('android', '页面操作', 9, [
|
|
71
|
-
MethodModel(f='x', p='请输入按下的x坐标', d=True),
|
|
72
|
-
MethodModel(f='y', p='请输入按下的x坐标', d=True),
|
|
73
|
-
MethodModel(f='time_', p='请输入长按时间', d=True)])
|
|
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
74
|
def a_long_click(self, x, y, time_):
|
|
75
75
|
"""长按屏幕N秒"""
|
|
76
76
|
self.base_data.android.long_click(x, y, time_)
|
|
@@ -6,15 +6,14 @@
|
|
|
6
6
|
import re
|
|
7
7
|
import traceback
|
|
8
8
|
|
|
9
|
-
from playwright.
|
|
10
|
-
from playwright.async_api._generated import Locator
|
|
9
|
+
from playwright.async_api import Locator, Error, TimeoutError
|
|
11
10
|
|
|
12
11
|
from mangotools.assertion import MangoAssertion
|
|
13
12
|
from mangotools.enums import StatusEnum
|
|
14
13
|
from mangotools.mangos import Mango
|
|
15
14
|
from ....enums import ElementExpEnum, ElementOperationEnum
|
|
16
15
|
from ....exceptions import MangoAutomationError
|
|
17
|
-
from ....exceptions.
|
|
16
|
+
from ....exceptions.error_msg import *
|
|
18
17
|
from ....uidrive._base_data import BaseData
|
|
19
18
|
from ....uidrive.web.async_web._assertion import AsyncWebAssertion
|
|
20
19
|
from ....uidrive.web.async_web._browser import AsyncWebBrowser
|
|
@@ -76,7 +75,7 @@ class AsyncWebDevice(AsyncWebBrowser,
|
|
|
76
75
|
return await Mango.a_e(AsyncWebAssertion(self.base_data), ope_key, ope_value)
|
|
77
76
|
else:
|
|
78
77
|
self.base_data.log.debug(f'开始断言-2,方法:{ope_key},断言值:{ope_value}')
|
|
79
|
-
return MangoAssertion(self.base_data.mysql_connect) \
|
|
78
|
+
return MangoAssertion(self.base_data.mysql_connect, self.base_data.test_data) \
|
|
80
79
|
.ass(ope_key, ope_value.get('actual'), ope_value.get('expect'))
|
|
81
80
|
except AssertionError as error:
|
|
82
81
|
self.base_data.log.debug(f'WEB自动化断言失败-1,类型:{type(error)},失败详情:{error}')
|
|
@@ -8,7 +8,7 @@ from playwright.async_api import Locator, expect as exp
|
|
|
8
8
|
from mangotools.decorator import async_method_callback
|
|
9
9
|
from mangotools.models import MethodModel
|
|
10
10
|
from ....exceptions import MangoAutomationError
|
|
11
|
-
from ....exceptions.
|
|
11
|
+
from ....exceptions.error_msg import ERROR_MSG_0021
|
|
12
12
|
from ....tools import Meta
|
|
13
13
|
from ....uidrive._base_data import BaseData
|
|
14
14
|
|
|
@@ -21,7 +21,7 @@ class AsyncWebAssertion(metaclass=Meta):
|
|
|
21
21
|
|
|
22
22
|
@async_method_callback('ass_web', '元素断言', 0, [
|
|
23
23
|
MethodModel(f='actual'),
|
|
24
|
-
MethodModel(f='expect', p='请输入元素个数', d=True)])
|
|
24
|
+
MethodModel(n='预期值', f='expect', p='请输入元素个数', d=True)])
|
|
25
25
|
async def w_to_have_count(self, actual: Locator, expect: str):
|
|
26
26
|
"""元素是几个"""
|
|
27
27
|
try:
|
|
@@ -40,7 +40,7 @@ class AsyncWebAssertion(metaclass=Meta):
|
|
|
40
40
|
|
|
41
41
|
@async_method_callback('ass_web', '元素断言', 1, [
|
|
42
42
|
MethodModel(f='actual'),
|
|
43
|
-
MethodModel(f='expect', p='请输入元素存输入1,不存输入0', d=True)])
|
|
43
|
+
MethodModel(n='预期值', f='expect', p='请输入元素存输入1,不存输入0', d=True)])
|
|
44
44
|
async def w_to_element_count(self, actual: Locator, expect: int):
|
|
45
45
|
"""元素是否存在"""
|
|
46
46
|
if int(expect) == 0:
|
|
@@ -59,7 +59,7 @@ class AsyncWebAssertion(metaclass=Meta):
|
|
|
59
59
|
|
|
60
60
|
@async_method_callback('ass_web', '元素断言', 2, [
|
|
61
61
|
MethodModel(f='actual'),
|
|
62
|
-
MethodModel(f='expect', p='请输入不包含的文本', d=True)])
|
|
62
|
+
MethodModel(n='预期值', f='expect', p='请输入不包含的文本', d=True)])
|
|
63
63
|
async def w_not_to_contain_text(self, actual: Locator, expect: str):
|
|
64
64
|
"""元素不包含文本"""
|
|
65
65
|
try:
|
|
@@ -124,7 +124,7 @@ class AsyncWebAssertion(metaclass=Meta):
|
|
|
124
124
|
|
|
125
125
|
@async_method_callback('ass_web', '元素断言', 9, [
|
|
126
126
|
MethodModel(f='actual'),
|
|
127
|
-
MethodModel(f='expect', p='请输入样式', d=True)])
|
|
127
|
+
MethodModel(n='预期值', f='expect', p='请输入样式', d=True)])
|
|
128
128
|
async def w_not_to_have_class(self, actual: Locator, expect: str):
|
|
129
129
|
"""元素没有阶级"""
|
|
130
130
|
try:
|
|
@@ -14,7 +14,7 @@ from mangotools.decorator import async_method_callback
|
|
|
14
14
|
from mangotools.models import MethodModel
|
|
15
15
|
from ..._base_data import BaseData
|
|
16
16
|
from ....exceptions import MangoAutomationError
|
|
17
|
-
from ....exceptions.
|
|
17
|
+
from ....exceptions.error_msg import ERROR_MSG_0049, ERROR_MSG_0013, ERROR_MSG_0058, ERROR_MSG_0059, ERROR_MSG_0010
|
|
18
18
|
from ....tools import Meta
|
|
19
19
|
|
|
20
20
|
|
|
@@ -25,13 +25,13 @@ class AsyncWebBrowser(metaclass=Meta):
|
|
|
25
25
|
self.base_data = base_data
|
|
26
26
|
|
|
27
27
|
@async_method_callback('web', '浏览器操作', 0, [
|
|
28
|
-
MethodModel(f='_time', p='请输入等待时间', d=True)])
|
|
28
|
+
MethodModel(n='等待时间', f='_time', p='请输入等待时间', d=True)])
|
|
29
29
|
async def w_wait_for_timeout(self, _time: int):
|
|
30
30
|
"""强制等待"""
|
|
31
31
|
await asyncio.sleep(int(_time))
|
|
32
32
|
|
|
33
33
|
@async_method_callback('web', '浏览器操作', 1, [
|
|
34
|
-
MethodModel(f='url', p='请输入URL', d=True)])
|
|
34
|
+
MethodModel(n='url地址', f='url', p='请输入URL', d=True)])
|
|
35
35
|
async def w_goto(self, url: str):
|
|
36
36
|
"""打开URL"""
|
|
37
37
|
try:
|
|
@@ -53,11 +53,11 @@ class AsyncWebBrowser(metaclass=Meta):
|
|
|
53
53
|
raise MangoAutomationError(*ERROR_MSG_0058, value=(url,))
|
|
54
54
|
|
|
55
55
|
@async_method_callback('web', '浏览器操作', 2, [
|
|
56
|
-
MethodModel(f='path', p='请输入截图保存路径', d=True)])
|
|
56
|
+
MethodModel(n='存储路径', f='path', p='请输入截图保存路径', d=True)])
|
|
57
57
|
async def w_screenshot(self, path: str):
|
|
58
58
|
"""整个页面截图"""
|
|
59
59
|
try:
|
|
60
|
-
await self.base_data.page.screenshot(path=path, full_page=True)
|
|
60
|
+
await self.base_data.page.screenshot(path=path, full_page=True, timeout=10000)
|
|
61
61
|
except (TargetClosedError, TimeoutError) as error:
|
|
62
62
|
self.base_data.log.debug(
|
|
63
63
|
f'截图出现异常失败-1,类型:{type(error)},失败详情:{error},失败明细:{traceback.format_exc()}')
|
|
@@ -81,7 +81,7 @@ class AsyncWebBrowser(metaclass=Meta):
|
|
|
81
81
|
file.write(json.dumps(await self.base_data.context.storage_state()))
|
|
82
82
|
|
|
83
83
|
@async_method_callback('web', '浏览器操作', 5, [
|
|
84
|
-
MethodModel(f='storage_state', p='请输入获取cookie方法中获取的内容', d=True)])
|
|
84
|
+
MethodModel(n='获取cookie方法的值', f='storage_state', p='请输入获取cookie方法中获取的内容', d=True)])
|
|
85
85
|
async def w_set_cookie(self, storage_state: str):
|
|
86
86
|
"""设置cookie"""
|
|
87
87
|
if isinstance(storage_state, str):
|
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
# @Author : 毛鹏
|
|
5
5
|
import asyncio
|
|
6
6
|
import os
|
|
7
|
-
|
|
8
7
|
import time
|
|
9
|
-
|
|
8
|
+
|
|
9
|
+
from playwright.async_api import Locator, Error, TimeoutError
|
|
10
10
|
|
|
11
11
|
from mangotools.decorator import async_method_callback
|
|
12
12
|
from mangotools.models import MethodModel
|
|
13
13
|
from ..._base_data import BaseData
|
|
14
14
|
from ....exceptions import MangoAutomationError
|
|
15
|
-
from ....exceptions.
|
|
15
|
+
from ....exceptions.error_msg import ERROR_MSG_0024, ERROR_MSG_0056
|
|
16
16
|
from ....tools import Meta
|
|
17
17
|
|
|
18
18
|
|
|
@@ -25,11 +25,15 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
25
25
|
@async_method_callback('web', '元素操作', 0, [MethodModel(f='locating')])
|
|
26
26
|
async def w_click(self, locating: Locator):
|
|
27
27
|
"""元素单击"""
|
|
28
|
+
if await locating.count() < 1:
|
|
29
|
+
raise TimeoutError('元素个数小于1,直接操作超时!')
|
|
28
30
|
await locating.click()
|
|
29
31
|
|
|
30
32
|
@async_method_callback('web', '元素操作', 1, [MethodModel(f='locating')])
|
|
31
33
|
async def w_dblclick(self, locating: Locator):
|
|
32
34
|
"""元素双击"""
|
|
35
|
+
if await locating.count() < 1:
|
|
36
|
+
raise TimeoutError('元素个数小于1,直接操作超时!')
|
|
33
37
|
await locating.dblclick()
|
|
34
38
|
|
|
35
39
|
@async_method_callback('web', '元素操作', 2, [MethodModel(f='locating')])
|
|
@@ -39,9 +43,11 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
39
43
|
|
|
40
44
|
@async_method_callback('web', '元素操作', 3, [
|
|
41
45
|
MethodModel(f='locating'),
|
|
42
|
-
MethodModel(f='input_value', p='请输入输入内容', d=True)])
|
|
46
|
+
MethodModel(n='输入内容', f='input_value', p='请输入输入内容', d=True)])
|
|
43
47
|
async def w_input(self, locating: Locator, input_value: str):
|
|
44
48
|
"""元素输入"""
|
|
49
|
+
if await locating.count() < 1:
|
|
50
|
+
raise TimeoutError('元素个数小于1,直接操作超时!')
|
|
45
51
|
await locating.fill(str(input_value))
|
|
46
52
|
|
|
47
53
|
@async_method_callback('web', '元素操作', 4, [MethodModel(f='locating')])
|
|
@@ -52,9 +58,11 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
52
58
|
|
|
53
59
|
@async_method_callback('web', '元素操作', 5, [
|
|
54
60
|
MethodModel(f='locating'),
|
|
55
|
-
MethodModel(f='set_cache_key', p='请输入获取元素文本后存储的key', d=True)])
|
|
61
|
+
MethodModel(n='缓存的key', f='set_cache_key', p='请输入获取元素文本后存储的key', d=True)])
|
|
56
62
|
async def w_get_text(self, locating: Locator, set_cache_key=None):
|
|
57
63
|
"""获取元素文本"""
|
|
64
|
+
if await locating.count() < 1:
|
|
65
|
+
raise TimeoutError('元素个数小于1,直接操作超时!')
|
|
58
66
|
methods = [
|
|
59
67
|
("inner_text", locating.inner_text),
|
|
60
68
|
("text_content", locating.text_content),
|
|
@@ -62,7 +70,6 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
62
70
|
("get_attribute", lambda: locating.get_attribute("value")),
|
|
63
71
|
("evaluate", lambda: locating.evaluate("el => el.value")),
|
|
64
72
|
]
|
|
65
|
-
|
|
66
73
|
for method_name, method in methods:
|
|
67
74
|
try:
|
|
68
75
|
value = await method()
|
|
@@ -73,14 +80,15 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
73
80
|
return value
|
|
74
81
|
except Exception:
|
|
75
82
|
continue
|
|
76
|
-
|
|
77
83
|
return None
|
|
78
84
|
|
|
79
85
|
@async_method_callback('web', '元素操作', 5, [
|
|
80
86
|
MethodModel(f='locating'),
|
|
81
|
-
MethodModel(f='input_value', p='请输入输入内容', d=True)])
|
|
87
|
+
MethodModel(n='输入文本', f='input_value', p='请输入输入内容', d=True)])
|
|
82
88
|
async def w_clear_input(self, locating: Locator, input_value: str):
|
|
83
89
|
"""元素清空再输入"""
|
|
90
|
+
if await locating.count() < 1:
|
|
91
|
+
raise TimeoutError('元素个数小于1,直接操作超时!')
|
|
84
92
|
await locating.clear()
|
|
85
93
|
await locating.fill(str(input_value))
|
|
86
94
|
|
|
@@ -95,34 +103,34 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
95
103
|
|
|
96
104
|
@async_method_callback('web', '元素操作', 6, [
|
|
97
105
|
MethodModel(f='locating'),
|
|
98
|
-
MethodModel(f='file_path', p='请输入文件路径,参照帮助文档', d=True)])
|
|
106
|
+
MethodModel(n='文件名称', f='file_path', p='请输入文件路径,参照帮助文档', d=True)])
|
|
99
107
|
async def w_upload_files(self, locating: Locator, file_path: str | list):
|
|
100
108
|
"""拖拽文件上传"""
|
|
101
109
|
try:
|
|
102
110
|
if isinstance(file_path, str):
|
|
103
|
-
await locating.set_input_files(file_path)
|
|
111
|
+
await locating.set_input_files(file_path, timeout=30000)
|
|
104
112
|
else:
|
|
105
113
|
for file in file_path:
|
|
106
|
-
await locating.set_input_files(file)
|
|
114
|
+
await locating.set_input_files(file, timeout=30000)
|
|
107
115
|
except Error:
|
|
108
116
|
raise MangoAutomationError(*ERROR_MSG_0024)
|
|
109
117
|
|
|
110
118
|
@async_method_callback('web', '元素操作', 7, [
|
|
111
119
|
MethodModel(f='locating'),
|
|
112
|
-
MethodModel(f='file_path', p='请输入文件路径,参照帮助文档', d=True)])
|
|
120
|
+
MethodModel(n='文件名称', f='file_path', p='请输入文件路径,参照帮助文档', d=True)])
|
|
113
121
|
async def w_click_upload_files(self, locating: Locator, file_path: str | list):
|
|
114
122
|
"""点击并选择文件上传"""
|
|
115
|
-
async with self.base_data.page.expect_file_chooser() as fc_info:
|
|
123
|
+
async with self.base_data.page.expect_file_chooser(timeout=30000) as fc_info:
|
|
116
124
|
await locating.click()
|
|
117
125
|
file_chooser = await fc_info.value
|
|
118
126
|
await file_chooser.set_files(file_path)
|
|
119
127
|
|
|
120
128
|
@async_method_callback('web', '元素操作', 8, [
|
|
121
129
|
MethodModel(f='locating'),
|
|
122
|
-
MethodModel(f='file_key', p='请输入文件存储路径的key,后续通过key获取文件保存的绝对路径', d=True)])
|
|
130
|
+
MethodModel(n='存储key值', f='file_key', p='请输入文件存储路径的key,后续通过key获取文件保存的绝对路径', d=True)])
|
|
123
131
|
async def w_download(self, locating: Locator, file_key: str):
|
|
124
132
|
"""下载文件"""
|
|
125
|
-
async with self.base_data.page.expect_download() as download_info:
|
|
133
|
+
async with self.base_data.page.expect_download(timeout=30000) as download_info:
|
|
126
134
|
await locating.click()
|
|
127
135
|
download = await download_info.value
|
|
128
136
|
file_name = download.suggested_filename
|
|
@@ -143,7 +151,7 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
143
151
|
|
|
144
152
|
@async_method_callback('web', '元素操作', 10, [
|
|
145
153
|
MethodModel(f='locating'),
|
|
146
|
-
MethodModel(f='n', p='请输入循环点击的时间', d=True)])
|
|
154
|
+
MethodModel(n='点击时间', f='n', p='请输入循环点击的时间', d=True)])
|
|
147
155
|
async def w_time_click(self, locating: Locator, n: int):
|
|
148
156
|
"""循环点击N秒"""
|
|
149
157
|
try:
|
|
@@ -158,7 +166,7 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
158
166
|
|
|
159
167
|
@async_method_callback('web', '元素操作', 11, [
|
|
160
168
|
MethodModel(f='locating'),
|
|
161
|
-
MethodModel(f='n', p='请输入向上像素', d=True)])
|
|
169
|
+
MethodModel(n='像素大小', f='n', p='请输入向上像素', d=True)])
|
|
162
170
|
async def w_drag_up_pixel(self, locating: Locator, n: int):
|
|
163
171
|
"""往上拖动N个像素"""
|
|
164
172
|
try:
|
|
@@ -176,7 +184,7 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
176
184
|
|
|
177
185
|
@async_method_callback('web', '元素操作', 12, [
|
|
178
186
|
MethodModel(f='locating'),
|
|
179
|
-
MethodModel(f='n', p='请输入向下像素', d=True)])
|
|
187
|
+
MethodModel(n='像素大小', f='n', p='请输入向下像素', d=True)])
|
|
180
188
|
async def w_drag_down_pixel(self, locating: Locator, n: int):
|
|
181
189
|
"""往下拖动N个像素"""
|
|
182
190
|
try:
|
|
@@ -194,7 +202,7 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
194
202
|
|
|
195
203
|
@async_method_callback('web', '元素操作', 13, [
|
|
196
204
|
MethodModel(f='locating'),
|
|
197
|
-
MethodModel(f='n', p='请输入向左像素', d=True)])
|
|
205
|
+
MethodModel(n='像素大小', f='n', p='请输入向左像素', d=True)])
|
|
198
206
|
async def w_drag_left_pixel(self, locating: Locator, n: int):
|
|
199
207
|
"""往左拖动N个像素"""
|
|
200
208
|
try:
|
|
@@ -212,7 +220,7 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
212
220
|
|
|
213
221
|
@async_method_callback('web', '元素操作', 14, [
|
|
214
222
|
MethodModel(f='locating'),
|
|
215
|
-
MethodModel(f='n', p='请输入向右像素', d=True)])
|
|
223
|
+
MethodModel(n='像素大小', f='n', p='请输入向右像素', d=True)])
|
|
216
224
|
async def w_drag_right_pixel(self, locating: Locator, n: int):
|
|
217
225
|
"""往右拖动N个像素"""
|
|
218
226
|
try:
|
|
@@ -229,7 +237,7 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
229
237
|
|
|
230
238
|
@async_method_callback('web', '元素操作', 15, [
|
|
231
239
|
MethodModel(f='locating'),
|
|
232
|
-
MethodModel(f='path', p='请输入截图保存路径', d=True)])
|
|
240
|
+
MethodModel(n='保存路径', f='path', p='请输入截图保存路径', d=True)])
|
|
233
241
|
async def w_ele_screenshot(self, locating: Locator, path: str):
|
|
234
242
|
"""元素截图"""
|
|
235
243
|
await locating.screenshot(path=path)
|
|
@@ -16,19 +16,20 @@ class AsyncWebDeviceInput(metaclass=Meta):
|
|
|
16
16
|
self.base_data = base_data
|
|
17
17
|
|
|
18
18
|
@async_method_callback('web', '输入设备', 0, [
|
|
19
|
-
MethodModel(f='keyboard', p='请输入键盘名称,首字母大写', d=True)])
|
|
19
|
+
MethodModel(n='按键值', f='keyboard', p='请输入键盘名称,首字母大写', d=True)])
|
|
20
20
|
async def w_keys(self, keyboard: str):
|
|
21
21
|
"""模拟按下指定的键"""
|
|
22
22
|
await self.base_data.page.keyboard.press(str(keyboard))
|
|
23
23
|
|
|
24
24
|
@async_method_callback('web', '输入设备', 1, [
|
|
25
|
-
MethodModel(f='y', p='请输入向上滚动像素', d=True)])
|
|
25
|
+
MethodModel(n='滚动像素', f='y', p='请输入向上滚动像素', d=True)])
|
|
26
26
|
async def w_wheel(self, y):
|
|
27
27
|
"""鼠标上下滚动像素,负数代表向上"""
|
|
28
28
|
await self.base_data.page.mouse.wheel(0, int(y))
|
|
29
29
|
|
|
30
30
|
@async_method_callback('web', '输入设备', 2, [
|
|
31
|
-
MethodModel(
|
|
31
|
+
MethodModel(n='x坐标', f='x', p='请输入点击的x轴', d=True),
|
|
32
|
+
MethodModel(n='y坐标', f='y', p='请输入点击的y轴', d=True)])
|
|
32
33
|
async def w_mouse_click(self, x: float, y: float):
|
|
33
34
|
"""鼠标点击坐标"""
|
|
34
35
|
await self.base_data.page.mouse.click(float(x), float(y))
|
|
@@ -61,17 +62,20 @@ class AsyncWebDeviceInput(metaclass=Meta):
|
|
|
61
62
|
center_y = viewport_size['height'] / 2
|
|
62
63
|
await self.base_data.page.mouse.click(center_x, center_y)
|
|
63
64
|
|
|
64
|
-
@async_method_callback('web', '输入设备', 5, [
|
|
65
|
+
@async_method_callback('web', '输入设备', 5, [
|
|
66
|
+
MethodModel(n='输入文本', f='text', p='请输入键盘输入的内容', d=True)])
|
|
65
67
|
async def w_keyboard_type_text(self, text: str):
|
|
66
68
|
"""模拟人工输入文字"""
|
|
67
69
|
await self.base_data.page.keyboard.type(str(text))
|
|
68
70
|
|
|
69
|
-
@async_method_callback('web', '输入设备', 6, [
|
|
71
|
+
@async_method_callback('web', '输入设备', 6, [
|
|
72
|
+
MethodModel(n='输入文本', f='text', p='请输入键盘输入的内容', d=True)])
|
|
70
73
|
async def w_keyboard_insert_text(self, text: str):
|
|
71
74
|
"""直接输入文字"""
|
|
72
75
|
await self.base_data.page.keyboard.insert_text(str(text))
|
|
73
76
|
|
|
74
|
-
@async_method_callback('web', '输入设备', 7, [
|
|
77
|
+
@async_method_callback('web', '输入设备', 7, [
|
|
78
|
+
MethodModel(n='删除个数', f='count', p='请输入要删除字符串的个数', d=True)])
|
|
75
79
|
async def w_keyboard_delete_text(self, count: int):
|
|
76
80
|
"""删除光标左侧的字符"""
|
|
77
81
|
for _ in range(0, int(count) + 1):
|
|
@@ -15,7 +15,7 @@ from playwright.async_api import async_playwright, Page, BrowserContext, Browser
|
|
|
15
15
|
|
|
16
16
|
from ....enums import BrowserTypeEnum
|
|
17
17
|
from ....exceptions import MangoAutomationError
|
|
18
|
-
from ....exceptions.
|
|
18
|
+
from ....exceptions.error_msg import ERROR_MSG_0057, ERROR_MSG_0008, ERROR_MSG_0062, ERROR_MSG_0009, ERROR_MSG_0055
|
|
19
19
|
|
|
20
20
|
"""
|
|
21
21
|
python -m uiautomator2 init
|
|
@@ -114,7 +114,9 @@ class AsyncWebNewBrowser:
|
|
|
114
114
|
args_dict["no_viewport"] = True
|
|
115
115
|
if self.web_recording and self.videos_path:
|
|
116
116
|
args_dict["record_video_dir"] = self.videos_path
|
|
117
|
-
|
|
117
|
+
context = await self.browser.new_context(**args_dict)
|
|
118
|
+
context.set_default_timeout(3000)
|
|
119
|
+
return context
|
|
118
120
|
|
|
119
121
|
async def new_page(self, context: BrowserContext) -> Page:
|
|
120
122
|
try:
|
|
@@ -18,7 +18,8 @@ class AsyncWebPage(metaclass=Meta):
|
|
|
18
18
|
def __init__(self, base_data: BaseData):
|
|
19
19
|
self.base_data = base_data
|
|
20
20
|
|
|
21
|
-
@async_method_callback('web', '页面操作', 0, [
|
|
21
|
+
@async_method_callback('web', '页面操作', 0, [
|
|
22
|
+
MethodModel(n='页签下标', f='individual', p='请输入页签下标,从1开始数', d=True)])
|
|
22
23
|
async def w_switch_tabs(self, individual: int):
|
|
23
24
|
"""切换页签"""
|
|
24
25
|
pages = self.base_data.context.pages
|
|
@@ -6,15 +6,14 @@
|
|
|
6
6
|
import re
|
|
7
7
|
import traceback
|
|
8
8
|
|
|
9
|
-
from playwright.
|
|
10
|
-
from playwright.sync_api._generated import Locator
|
|
9
|
+
from playwright.sync_api import Locator, TimeoutError, Error
|
|
11
10
|
|
|
12
11
|
from mangotools.assertion import MangoAssertion
|
|
13
12
|
from mangotools.enums import StatusEnum
|
|
14
13
|
from mangotools.mangos import Mango
|
|
15
14
|
from ....enums import ElementExpEnum
|
|
16
15
|
from ....exceptions import MangoAutomationError
|
|
17
|
-
from ....exceptions.
|
|
16
|
+
from ....exceptions.error_msg import *
|
|
18
17
|
from ....uidrive._base_data import BaseData
|
|
19
18
|
from ....uidrive.web.sync_web._assertion import SyncWebAssertion
|
|
20
19
|
from ....uidrive.web.sync_web._browser import SyncWebBrowser
|
|
@@ -75,7 +74,7 @@ class SyncWebDevice(SyncWebBrowser,
|
|
|
75
74
|
return Mango.s_e(SyncWebAssertion(self.base_data), ope_key, ope_value)
|
|
76
75
|
else:
|
|
77
76
|
self.base_data.log.debug(f'开始断言-2,方法:{ope_key},断言值:{ope_value}')
|
|
78
|
-
return MangoAssertion(self.base_data.mysql_connect) \
|
|
77
|
+
return MangoAssertion(self.base_data.mysql_connect, self.base_data.test_data) \
|
|
79
78
|
.ass(ope_key, ope_value.get('actual'), ope_value.get('expect'))
|
|
80
79
|
except AssertionError as error:
|
|
81
80
|
self.base_data.log.debug(f'WEB自动化断言失败-1,类型:{type(error)},失败详情:{error}')
|
|
@@ -21,7 +21,7 @@ class SyncWebAssertion(metaclass=Meta):
|
|
|
21
21
|
|
|
22
22
|
@sync_method_callback('ass_web', '元素断言', 0, [
|
|
23
23
|
MethodModel(f='actual'),
|
|
24
|
-
MethodModel(f='expect', p='请输入元素个数', d=True)])
|
|
24
|
+
MethodModel(n='预期值', f='expect', p='请输入元素个数', d=True)])
|
|
25
25
|
def w_to_have_count(self, actual: Locator, expect: str):
|
|
26
26
|
"""元素是几个"""
|
|
27
27
|
try:
|
|
@@ -40,7 +40,7 @@ class SyncWebAssertion(metaclass=Meta):
|
|
|
40
40
|
|
|
41
41
|
@sync_method_callback('ass_web', '元素断言', 1, [
|
|
42
42
|
MethodModel(f='actual'),
|
|
43
|
-
MethodModel(f='expect', p='请输入元素存输入1,不存输入0', d=True)])
|
|
43
|
+
MethodModel(n='预期值', f='expect', p='请输入元素存输入1,不存输入0', d=True)])
|
|
44
44
|
def w_to_element_count(self, actual: Locator, expect: int):
|
|
45
45
|
"""元素存在个数"""
|
|
46
46
|
if int(expect) == 0:
|
|
@@ -58,7 +58,7 @@ class SyncWebAssertion(metaclass=Meta):
|
|
|
58
58
|
|
|
59
59
|
@sync_method_callback('ass_web', '元素断言', 2, [
|
|
60
60
|
MethodModel(f='actual'),
|
|
61
|
-
MethodModel(f='expect', p='请输入不包含的文本', d=True)])
|
|
61
|
+
MethodModel(n='预期值', f='expect', p='请输入不包含的文本', d=True)])
|
|
62
62
|
def w_not_to_contain_text(self, actual: Locator, expect: str):
|
|
63
63
|
"""元素不包含文本"""
|
|
64
64
|
try:
|
|
@@ -123,7 +123,7 @@ class SyncWebAssertion(metaclass=Meta):
|
|
|
123
123
|
|
|
124
124
|
@sync_method_callback('ass_web', '元素断言', 9, [
|
|
125
125
|
MethodModel(f='actual'),
|
|
126
|
-
MethodModel(f='expect', p='请输入样式', d=True)])
|
|
126
|
+
MethodModel(n='预期值', f='expect', p='请输入样式', d=True)])
|
|
127
127
|
def w_not_to_have_class(self, actual: Locator, expect: str):
|
|
128
128
|
"""元素没有阶级"""
|
|
129
129
|
try:
|
|
@@ -13,7 +13,7 @@ from playwright._impl._errors import TimeoutError, Error, TargetClosedError
|
|
|
13
13
|
from mangotools.decorator import sync_method_callback
|
|
14
14
|
from mangotools.models import MethodModel
|
|
15
15
|
from ....exceptions import MangoAutomationError
|
|
16
|
-
from ....exceptions.
|
|
16
|
+
from ....exceptions.error_msg import ERROR_MSG_0049, ERROR_MSG_0013, ERROR_MSG_0058, ERROR_MSG_0059, ERROR_MSG_0010
|
|
17
17
|
from ....tools import Meta
|
|
18
18
|
from ....uidrive._base_data import BaseData
|
|
19
19
|
|
|
@@ -25,13 +25,13 @@ class SyncWebBrowser(metaclass=Meta):
|
|
|
25
25
|
self.base_data = base_data
|
|
26
26
|
|
|
27
27
|
@sync_method_callback('web', '浏览器操作', 1, [
|
|
28
|
-
MethodModel(f='_time', p='请输入等待时间', d=True)])
|
|
28
|
+
MethodModel(n='等待时间', f='_time', p='请输入等待时间', d=True)])
|
|
29
29
|
def w_wait_for_timeout(self, _time: int):
|
|
30
30
|
"""强制等待"""
|
|
31
31
|
time.sleep(int(_time))
|
|
32
32
|
|
|
33
33
|
@sync_method_callback('web', '浏览器操作', 1, [
|
|
34
|
-
MethodModel(f='url', p='请输入URL', d=True)])
|
|
34
|
+
MethodModel(n='url地址', f='url', p='请输入URL', d=True)])
|
|
35
35
|
def w_goto(self, url: str):
|
|
36
36
|
"""打开URL"""
|
|
37
37
|
try:
|
|
@@ -52,11 +52,12 @@ class SyncWebBrowser(metaclass=Meta):
|
|
|
52
52
|
f'打开URL失败-3,类型:{type(error)},失败详情:{error},失败明细:{traceback.format_exc()}')
|
|
53
53
|
raise MangoAutomationError(*ERROR_MSG_0058, value=(url,))
|
|
54
54
|
|
|
55
|
-
@sync_method_callback('web', '浏览器操作', 2, [
|
|
55
|
+
@sync_method_callback('web', '浏览器操作', 2, [
|
|
56
|
+
MethodModel(n='保存路径', f='path', p='请输入截图保存路径', d=True)])
|
|
56
57
|
def w_screenshot(self, path: str):
|
|
57
58
|
"""整个页面截图"""
|
|
58
59
|
try:
|
|
59
|
-
self.base_data.page.screenshot(path=path, full_page=True)
|
|
60
|
+
self.base_data.page.screenshot(path=path, full_page=True, timeout=10000)
|
|
60
61
|
except (TargetClosedError, TimeoutError) as error:
|
|
61
62
|
self.base_data.log.debug(
|
|
62
63
|
f'截图出现异常失败-1,类型:{type(error)},失败详情:{error},失败明细:{traceback.format_exc()}')
|
|
@@ -80,7 +81,7 @@ class SyncWebBrowser(metaclass=Meta):
|
|
|
80
81
|
file.write(json.dumps(self.base_data.context.storage_state()))
|
|
81
82
|
|
|
82
83
|
@sync_method_callback('web', '浏览器操作', 5, [
|
|
83
|
-
MethodModel(f='storage_state', p='请输入获取cookie方法中获取的内容', d=True)])
|
|
84
|
+
MethodModel(n='获取cookie的值', f='storage_state', p='请输入获取cookie方法中获取的内容', d=True)])
|
|
84
85
|
def w_set_cookie(self, storage_state: str):
|
|
85
86
|
"""设置cookie"""
|
|
86
87
|
if isinstance(storage_state, str):
|