mangoautomation 1.1.21__py3-none-any.whl → 1.1.23__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/__init__.py +1 -1
- mangoautomation/enums/__init__.py +0 -2
- mangoautomation/exceptions/__init__.py +0 -3
- mangoautomation/exceptions/error_msg.py +4 -4
- 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 -2
- mangoautomation/models/_ui_model.py +2 -1
- mangoautomation/tools/__init__.py +0 -2
- mangoautomation/tools/_uiautodev.py +1 -3
- mangoautomation/uidrive/__init__.py +5 -7
- mangoautomation/uidrives/__init__.py +21 -0
- mangoautomation/{uidrive → uidrives}/_async_element.py +80 -52
- mangoautomation/{uidrive → uidrives}/_base_data.py +16 -4
- mangoautomation/{uidrive → uidrives}/_driver_object.py +2 -4
- mangoautomation/{uidrive → uidrives}/_sync_element.py +78 -50
- mangoautomation/{uidrive → uidrives}/android/__init__.py +2 -16
- mangoautomation/{uidrive → uidrives}/android/_application.py +1 -1
- mangoautomation/{uidrive → uidrives}/android/_assertion.py +1 -1
- mangoautomation/{uidrive → uidrives}/android/_customization.py +1 -1
- mangoautomation/{uidrive → uidrives}/android/_element.py +3 -3
- mangoautomation/{uidrive → uidrives}/android/_equipment.py +1 -1
- mangoautomation/{uidrive → uidrives}/android/_page.py +1 -1
- mangoautomation/{uidrive → uidrives}/pc/__init__.py +3 -4
- mangoautomation/{uidrive → uidrives}/pc/customization.py +1 -1
- mangoautomation/{uidrive → uidrives}/pc/element.py +1 -2
- mangoautomation/{uidrive → uidrives}/pc/input_device.py +1 -2
- mangoautomation/uidrives/web/__init__.py +10 -0
- mangoautomation/uidrives/web/_async_web.py +166 -0
- mangoautomation/uidrives/web/_sync_web.py +166 -0
- mangoautomation/{uidrive → uidrives}/web/async_web/__init__.py +8 -8
- mangoautomation/{uidrive → uidrives}/web/async_web/_assertion.py +1 -1
- mangoautomation/{uidrive → uidrives}/web/async_web/_browser.py +2 -2
- mangoautomation/{uidrive → uidrives}/web/async_web/_customization.py +1 -1
- mangoautomation/{uidrive → uidrives}/web/async_web/_element.py +3 -13
- mangoautomation/{uidrive → uidrives}/web/async_web/_input_device.py +1 -1
- mangoautomation/{uidrive → uidrives}/web/async_web/_page.py +1 -1
- mangoautomation/{uidrive → uidrives}/web/sync_web/__init__.py +8 -8
- mangoautomation/{uidrive → uidrives}/web/sync_web/_assertion.py +1 -1
- mangoautomation/{uidrive → uidrives}/web/sync_web/_browser.py +3 -3
- mangoautomation/{uidrive → uidrives}/web/sync_web/_customization.py +1 -1
- mangoautomation/{uidrive → uidrives}/web/sync_web/_element.py +3 -13
- mangoautomation/{uidrive → uidrives}/web/sync_web/_input_device.py +1 -1
- mangoautomation/{uidrive → uidrives}/web/sync_web/_page.py +2 -2
- {mangoautomation-1.1.21.dist-info → mangoautomation-1.1.23.dist-info}/METADATA +4 -4
- mangoautomation-1.1.23.dist-info/RECORD +71 -0
- tests/__init__.py +0 -10
- tests/demo1.py +21 -0
- tests/test_ai_element.py +36 -0
- tests/test_ui_web.py +31 -31
- mangoautomation/uidrive/web/__init__.py +0 -5
- mangoautomation-1.1.21.dist-info/RECORD +0 -58
- /mangoautomation/{uidrive → uidrives}/android/_new_android.py +0 -0
- /mangoautomation/{uidrive → uidrives}/ios/__init__.py +0 -0
- /mangoautomation/{uidrive → uidrives}/pc/assertion.py +0 -0
- /mangoautomation/{uidrive → uidrives}/pc/new_windows.py +0 -0
- /mangoautomation/{uidrive → uidrives}/web/async_web/_new_browser.py +0 -0
- /mangoautomation/{uidrive → uidrives}/web/sync_web/_new_browser.py +0 -0
- {mangoautomation-1.1.21.dist-info → mangoautomation-1.1.23.dist-info}/LICENSE +0 -0
- {mangoautomation-1.1.21.dist-info → mangoautomation-1.1.23.dist-info}/WHEEL +0 -0
- {mangoautomation-1.1.21.dist-info → mangoautomation-1.1.23.dist-info}/top_level.txt +0 -0
|
@@ -8,26 +8,13 @@ from uiautomator2 import UiObject, UiObjectNotFoundError
|
|
|
8
8
|
from uiautomator2.exceptions import XPathElementNotFoundError
|
|
9
9
|
from uiautomator2.xpath import XPathSelector
|
|
10
10
|
|
|
11
|
+
from mangoautomation.mangos import AndroidApplication, AndroidAssertion, AndroidElement, AndroidCustomization, \
|
|
12
|
+
AndroidEquipment, AndroidPage
|
|
11
13
|
from mangotools.assertion import MangoAssertion
|
|
12
|
-
from ..android._application import AndroidApplication
|
|
13
|
-
from ..android._assertion import AndroidAssertion
|
|
14
|
-
from ..android._customization import AndroidCustomization
|
|
15
|
-
from ..android._element import AndroidElement
|
|
16
|
-
from ..android._equipment import AndroidEquipment
|
|
17
|
-
from ..android._page import AndroidPage
|
|
18
14
|
from ...enums import ElementExpEnum
|
|
19
15
|
from ...exceptions import MangoAutomationError
|
|
20
16
|
from ...exceptions.error_msg import *
|
|
21
17
|
|
|
22
|
-
__all__ = [
|
|
23
|
-
'AndroidApplication',
|
|
24
|
-
'AndroidAssertion',
|
|
25
|
-
'AndroidElement',
|
|
26
|
-
'AndroidCustomization',
|
|
27
|
-
'AndroidEquipment',
|
|
28
|
-
'AndroidPage',
|
|
29
|
-
'AndroidDriver',
|
|
30
|
-
]
|
|
31
18
|
|
|
32
19
|
from mangotools.mangos import Mango
|
|
33
20
|
|
|
@@ -68,7 +55,6 @@ class AndroidDriver(AndroidPage,
|
|
|
68
55
|
is_method = callable(getattr(AndroidAssertion(self.base_data), ope_key, None))
|
|
69
56
|
if is_method and ope_value.get('actual') is None:
|
|
70
57
|
raise MangoAutomationError(*ERROR_MSG_0031, value=(name,))
|
|
71
|
-
|
|
72
58
|
try:
|
|
73
59
|
if is_method:
|
|
74
60
|
self.base_data.log.debug(f'开始断言-1,方法:{ope_key},断言值:{ope_value}')
|
|
@@ -10,7 +10,7 @@ from mangotools.models import MethodModel
|
|
|
10
10
|
from ...exceptions import MangoAutomationError
|
|
11
11
|
from ...exceptions.error_msg import ERROR_MSG_0046
|
|
12
12
|
from ...tools import Meta
|
|
13
|
-
from ...
|
|
13
|
+
from ...uidrives._base_data import BaseData
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class AndroidApplication(metaclass=Meta):
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
from uiautomator2 import UiObject
|
|
7
7
|
|
|
8
8
|
from mangoautomation.tools import Meta
|
|
9
|
-
from mangoautomation.
|
|
9
|
+
from mangoautomation.uidrives._base_data import BaseData
|
|
10
10
|
from mangotools.decorator import sync_method_callback
|
|
11
11
|
from mangotools.models import MethodModel
|
|
12
12
|
|
|
@@ -9,12 +9,12 @@ import time
|
|
|
9
9
|
from uiautomator2 import UiObject
|
|
10
10
|
from uiautomator2.xpath import XPathSelector
|
|
11
11
|
|
|
12
|
+
from mangotools.decorator import sync_method_callback
|
|
13
|
+
from mangotools.models import MethodModel
|
|
12
14
|
from ...exceptions import MangoAutomationError
|
|
13
15
|
from ...exceptions.error_msg import ERROR_MSG_0043, ERROR_MSG_0044
|
|
14
16
|
from ...tools import Meta
|
|
15
|
-
from ...
|
|
16
|
-
from mangotools.decorator import sync_method_callback
|
|
17
|
-
from mangotools.models import MethodModel
|
|
17
|
+
from ...uidrives._base_data import BaseData
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class AndroidElement(metaclass=Meta):
|
|
@@ -8,7 +8,7 @@ from time import sleep
|
|
|
8
8
|
from mangotools.decorator import sync_method_callback
|
|
9
9
|
from mangotools.models import MethodModel
|
|
10
10
|
from ...tools import Meta
|
|
11
|
-
from ...
|
|
11
|
+
from ...uidrives._base_data import BaseData
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class AndroidEquipment(metaclass=Meta):
|
|
@@ -9,7 +9,7 @@ from uiautomator2 import Direction
|
|
|
9
9
|
from mangotools.decorator import sync_method_callback
|
|
10
10
|
from mangotools.models import MethodModel
|
|
11
11
|
from ...tools import Meta
|
|
12
|
-
from ...
|
|
12
|
+
from ...uidrives._base_data import BaseData
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class AndroidPage(metaclass=Meta):
|
|
@@ -24,13 +24,12 @@ else:
|
|
|
24
24
|
from uiautomation import Control
|
|
25
25
|
import uiautomation
|
|
26
26
|
|
|
27
|
-
from mangoautomation.
|
|
28
|
-
from mangoautomation.
|
|
29
|
-
from mangoautomation.uidrive.pc.input_device import WinDeviceInput
|
|
27
|
+
from mangoautomation.uidrives.pc.element import WinElement
|
|
28
|
+
from mangoautomation.uidrives.pc.input_device import WinDeviceInput
|
|
30
29
|
|
|
31
30
|
|
|
32
31
|
class WinDriver(WinElement, WinDeviceInput):
|
|
33
|
-
def __init__(self, base_data
|
|
32
|
+
def __init__(self, base_data):
|
|
34
33
|
super().__init__(base_data)
|
|
35
34
|
|
|
36
35
|
def find_element(
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
from ...tools import Meta
|
|
2
|
-
from ...uidrive._base_data import BaseData
|
|
3
2
|
|
|
4
3
|
|
|
5
4
|
class WinElement(metaclass=Meta):
|
|
6
5
|
"""元素操作"""
|
|
7
6
|
|
|
8
|
-
def __init__(self, base_data
|
|
7
|
+
def __init__(self, base_data):
|
|
9
8
|
self.base_data = base_data
|
|
10
9
|
|
|
11
10
|
def click(self, control):
|
|
@@ -4,11 +4,10 @@
|
|
|
4
4
|
# @Time : 2024-11-30 23:44
|
|
5
5
|
# @Author : 毛鹏
|
|
6
6
|
from ...tools import Meta
|
|
7
|
-
from ...uidrive._base_data import BaseData
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
class WinDeviceInput(metaclass=Meta):
|
|
11
10
|
"""输入设备操作"""
|
|
12
11
|
|
|
13
|
-
def __init__(self, base_data
|
|
12
|
+
def __init__(self, base_data):
|
|
14
13
|
self.base_data = base_data
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# @Project: 芒果测试平台
|
|
3
|
+
# @Description:
|
|
4
|
+
# @Time : 2023/5/16 14:50
|
|
5
|
+
# @Author : 毛鹏
|
|
6
|
+
from ._async_web import AsyncWebDevice, AsyncWebCustomization, AsyncWebAssertion
|
|
7
|
+
from ._sync_web import SyncWebDevice, SyncWebCustomization, SyncWebAssertion
|
|
8
|
+
|
|
9
|
+
__all__ = ['AsyncWebDevice', 'AsyncWebCustomization', 'AsyncWebAssertion', 'SyncWebDevice', 'SyncWebCustomization',
|
|
10
|
+
'SyncWebAssertion']
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# @Project: 芒果测试平台
|
|
3
|
+
# @Description:
|
|
4
|
+
# @Time : 2025-04-04 21:42
|
|
5
|
+
# @Author : 毛鹏
|
|
6
|
+
import re
|
|
7
|
+
import traceback
|
|
8
|
+
|
|
9
|
+
from playwright.async_api import Locator, Error, TimeoutError
|
|
10
|
+
|
|
11
|
+
from mangoautomation.mangos import AsyncWebAssertion, AsyncWebBrowser, AsyncWebCustomization, AsyncWebElement, \
|
|
12
|
+
AsyncWebDeviceInput, AsyncWebPage, ElementMain
|
|
13
|
+
from mangotools.assertion import MangoAssertion
|
|
14
|
+
from mangotools.enums import StatusEnum
|
|
15
|
+
from mangotools.mangos import Mango
|
|
16
|
+
from ...enums import ElementExpEnum
|
|
17
|
+
from ...exceptions import MangoAutomationError
|
|
18
|
+
from ...exceptions.error_msg import *
|
|
19
|
+
|
|
20
|
+
re = re
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class AsyncWebDevice(AsyncWebBrowser,
|
|
24
|
+
AsyncWebPage,
|
|
25
|
+
AsyncWebElement,
|
|
26
|
+
AsyncWebDeviceInput,
|
|
27
|
+
AsyncWebCustomization):
|
|
28
|
+
|
|
29
|
+
def __init__(self, base_data):
|
|
30
|
+
super().__init__(base_data)
|
|
31
|
+
|
|
32
|
+
async def open_url(self, is_open: bool = False):
|
|
33
|
+
if not self.base_data.is_open_url or is_open:
|
|
34
|
+
self.base_data.log.debug(f'打开url,is_open_url:{self.base_data.is_open_url},url:{self.base_data.url}')
|
|
35
|
+
await self.w_goto(self.base_data.url)
|
|
36
|
+
self.base_data.is_open_url = True
|
|
37
|
+
|
|
38
|
+
async def web_action_element(self, name, ope_key, ope_value, ):
|
|
39
|
+
self.base_data.log.debug(f'操作元素{name}:,key:{ope_key},value:{ope_value}')
|
|
40
|
+
try:
|
|
41
|
+
await ElementMain.a_element(self, ope_key, ope_value)
|
|
42
|
+
except TimeoutError as error:
|
|
43
|
+
self.base_data.log.debug(f'WEB自动化操作失败-1,类型:{type(error)},失败详情:{error}')
|
|
44
|
+
raise MangoAutomationError(*ERROR_MSG_0011, value=(name,))
|
|
45
|
+
except Error as error:
|
|
46
|
+
self.base_data.log.error(f'WEB自动化操作失败-2,类型:{type(error)},失败详情:{error}')
|
|
47
|
+
raise MangoAutomationError(*ERROR_MSG_0032, value=(name,))
|
|
48
|
+
except ValueError as error:
|
|
49
|
+
self.base_data.log.error(f'WEB自动化操作失败-3,类型:{type(error)},失败详情:{error}')
|
|
50
|
+
raise MangoAutomationError(*ERROR_MSG_0012)
|
|
51
|
+
|
|
52
|
+
async def web_assertion_element(self, name, ope_key, ope_value) -> str:
|
|
53
|
+
self.base_data.log.debug(f'断言元素,名称:{name},key:{ope_key},value:{ope_value}')
|
|
54
|
+
is_method = callable(getattr(AsyncWebAssertion, ope_key, None))
|
|
55
|
+
try:
|
|
56
|
+
if is_method:
|
|
57
|
+
if ope_value.get('actual', None) is None:
|
|
58
|
+
raise MangoAutomationError(*ERROR_MSG_0031, value=(name,))
|
|
59
|
+
self.base_data.log.debug(f'开始断言-1,方法:{ope_key},断言值:{ope_value}')
|
|
60
|
+
return await Mango.a_e(AsyncWebAssertion(self.base_data), ope_key, ope_value)
|
|
61
|
+
else:
|
|
62
|
+
self.base_data.log.debug(f'开始断言-2,方法:{ope_key},断言值:{ope_value}')
|
|
63
|
+
return MangoAssertion(self.base_data.mysql_connect, self.base_data.test_data) \
|
|
64
|
+
.ass(ope_key, ope_value.get('actual'), ope_value.get('expect'))
|
|
65
|
+
except AssertionError as error:
|
|
66
|
+
self.base_data.log.debug(f'WEB自动化断言失败-1,类型:{type(error)},失败详情:{error}')
|
|
67
|
+
raise MangoAutomationError(*ERROR_MSG_0017, value=error.args)
|
|
68
|
+
except AttributeError as error:
|
|
69
|
+
self.base_data.log.error(f'WEB自动化断言失败-2,类型:{type(error)},失败详情:{error}')
|
|
70
|
+
raise MangoAutomationError(*ERROR_MSG_0048)
|
|
71
|
+
except ValueError as error:
|
|
72
|
+
self.base_data.log.error(f'WEB自动化断言失败-3,类型:{type(error)},失败详情:{error}')
|
|
73
|
+
raise MangoAutomationError(*ERROR_MSG_0005)
|
|
74
|
+
except Error as error:
|
|
75
|
+
self.base_data.log.error(f'WEB自动化断言失败-4,类型:{type(error)},失败详情:{error}')
|
|
76
|
+
raise MangoAutomationError(*ERROR_MSG_0052, value=(name,), )
|
|
77
|
+
|
|
78
|
+
async def web_find_element(self, name, _type, exp, loc, sub, is_iframe) \
|
|
79
|
+
-> tuple[Locator, int, str] | tuple[list[Locator], int, str]:
|
|
80
|
+
self.base_data.log.debug(
|
|
81
|
+
f'查找元素-1,名称:{name},_type:{_type},exp:{exp},loc:{loc},sub:{sub},is_iframe:{is_iframe}')
|
|
82
|
+
if is_iframe != StatusEnum.SUCCESS.value:
|
|
83
|
+
locator: Locator = await self.__find_ele(self.base_data.page, exp, loc)
|
|
84
|
+
try:
|
|
85
|
+
return await self.__element_info(locator, sub)
|
|
86
|
+
except Error as error:
|
|
87
|
+
self.base_data.log.debug(
|
|
88
|
+
f'WEB自动化查找元素失败-1,类型:{type(error)},失败详情:{error},失败明细:{traceback.format_exc()}')
|
|
89
|
+
raise MangoAutomationError(*ERROR_MSG_0041, value=(name, loc))
|
|
90
|
+
else:
|
|
91
|
+
return await self.__is_iframe(_type, exp, loc, sub)
|
|
92
|
+
|
|
93
|
+
async def __element_info(self, locator: Locator, sub) -> tuple[Locator, int, str]:
|
|
94
|
+
count = await locator.count()
|
|
95
|
+
if count < 1:
|
|
96
|
+
raise MangoAutomationError(*ERROR_MSG_0053)
|
|
97
|
+
if sub is not None:
|
|
98
|
+
loc_result = locator.nth(sub - 1) if sub else locator
|
|
99
|
+
else:
|
|
100
|
+
loc_result = locator.nth(0)
|
|
101
|
+
|
|
102
|
+
try:
|
|
103
|
+
text = await self.w_get_text(loc_result)
|
|
104
|
+
except Exception:
|
|
105
|
+
text = None
|
|
106
|
+
return loc_result, count, text
|
|
107
|
+
|
|
108
|
+
async def ai_element_info(self, locator: Locator) -> tuple[Locator, int, str]:
|
|
109
|
+
count = await locator.count()
|
|
110
|
+
if count < 1:
|
|
111
|
+
raise MangoAutomationError(*ERROR_MSG_0053)
|
|
112
|
+
try:
|
|
113
|
+
text = await self.w_get_text(locator.nth(0))
|
|
114
|
+
except Exception:
|
|
115
|
+
text = None
|
|
116
|
+
return locator.nth(0), count, text
|
|
117
|
+
|
|
118
|
+
async def __is_iframe(self, _type, exp, loc, sub):
|
|
119
|
+
ele_list: list[Locator] = []
|
|
120
|
+
for i in self.base_data.page.frames:
|
|
121
|
+
locator: Locator = await self.__find_ele(i, exp, loc)
|
|
122
|
+
try:
|
|
123
|
+
count = await locator.count()
|
|
124
|
+
except Error as error:
|
|
125
|
+
self.base_data.log.debug(
|
|
126
|
+
f'WEB自动化查找元素失败-2,类型:{type(error)},失败详情:{error},失败明细:{traceback.format_exc()}')
|
|
127
|
+
raise MangoAutomationError(*ERROR_MSG_0041, )
|
|
128
|
+
if count > 0:
|
|
129
|
+
for nth in range(0, count):
|
|
130
|
+
ele_list.append(locator.nth(nth))
|
|
131
|
+
else:
|
|
132
|
+
raise MangoAutomationError(*ERROR_MSG_0023)
|
|
133
|
+
try:
|
|
134
|
+
count = len(ele_list)
|
|
135
|
+
loc = ele_list[sub - 1] if sub else ele_list[0]
|
|
136
|
+
try:
|
|
137
|
+
text = await self.w_get_text(loc)
|
|
138
|
+
except Exception:
|
|
139
|
+
text = None
|
|
140
|
+
return loc, count, text
|
|
141
|
+
except IndexError:
|
|
142
|
+
raise MangoAutomationError(*ERROR_MSG_0025, value=(len(ele_list),))
|
|
143
|
+
|
|
144
|
+
async def __find_ele(self, page, exp, loc) -> Locator:
|
|
145
|
+
if exp == ElementExpEnum.LOCATOR.value:
|
|
146
|
+
try:
|
|
147
|
+
return eval(f"await page.{loc}")
|
|
148
|
+
except SyntaxError:
|
|
149
|
+
try:
|
|
150
|
+
return eval(f"page.{loc}")
|
|
151
|
+
except SyntaxError as error:
|
|
152
|
+
self.base_data.log.error(f'WEB自动化查找元素失败-3,类型:{type(error)},失败详情:{error}')
|
|
153
|
+
raise MangoAutomationError(*ERROR_MSG_0022)
|
|
154
|
+
except NameError as error:
|
|
155
|
+
self.base_data.log.error(f'WEB自动化查找元素失败-4,类型:{type(error)},失败详情:{error}')
|
|
156
|
+
raise MangoAutomationError(*ERROR_MSG_0060)
|
|
157
|
+
elif exp == ElementExpEnum.XPATH.value:
|
|
158
|
+
return page.locator(f'xpath={loc}')
|
|
159
|
+
elif exp == ElementExpEnum.CSS.value:
|
|
160
|
+
return page.locator(loc)
|
|
161
|
+
elif exp == ElementExpEnum.TEXT.value:
|
|
162
|
+
return page.get_by_text(loc, exact=True)
|
|
163
|
+
elif exp == ElementExpEnum.PLACEHOLDER.value:
|
|
164
|
+
return page.get_by_placeholder(loc)
|
|
165
|
+
else:
|
|
166
|
+
raise MangoAutomationError(*ERROR_MSG_0020)
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# @Project: 芒果测试平台
|
|
3
|
+
# @Description:
|
|
4
|
+
# @Time : 2025-04-04 21:42
|
|
5
|
+
# @Author : 毛鹏
|
|
6
|
+
import re
|
|
7
|
+
import traceback
|
|
8
|
+
|
|
9
|
+
from playwright.sync_api import Locator, TimeoutError, Error
|
|
10
|
+
|
|
11
|
+
from mangoautomation.mangos import SyncWebAssertion, SyncWebBrowser, SyncWebCustomization, SyncWebElement, \
|
|
12
|
+
SyncWebDeviceInput, SyncWebPage, ElementMain
|
|
13
|
+
from mangotools.assertion import MangoAssertion
|
|
14
|
+
from mangotools.enums import StatusEnum
|
|
15
|
+
from mangotools.mangos import Mango
|
|
16
|
+
from ...enums import ElementExpEnum
|
|
17
|
+
from ...exceptions import MangoAutomationError
|
|
18
|
+
from ...exceptions.error_msg import *
|
|
19
|
+
|
|
20
|
+
re = re
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class SyncWebDevice(SyncWebBrowser,
|
|
24
|
+
SyncWebPage,
|
|
25
|
+
SyncWebElement,
|
|
26
|
+
SyncWebDeviceInput,
|
|
27
|
+
SyncWebCustomization):
|
|
28
|
+
|
|
29
|
+
def __init__(self, base_data):
|
|
30
|
+
super().__init__(base_data)
|
|
31
|
+
|
|
32
|
+
def open_url(self, is_open: bool = False):
|
|
33
|
+
if not self.base_data.is_open_url or is_open:
|
|
34
|
+
self.base_data.log.debug(f'打开url,is_open_url:{self.base_data.is_open_url},url:{self.base_data.url}')
|
|
35
|
+
self.w_goto(self.base_data.url)
|
|
36
|
+
self.base_data.is_open_url = True
|
|
37
|
+
|
|
38
|
+
def web_action_element(self, name, ope_key, ope_value, ):
|
|
39
|
+
self.base_data.log.debug(f'操作元素,名称:{name},key:{ope_key},value:{ope_value}')
|
|
40
|
+
try:
|
|
41
|
+
ElementMain.s_element(self, ope_key, ope_value)
|
|
42
|
+
except TimeoutError as error:
|
|
43
|
+
self.base_data.log.debug(f'WEB自动化操作失败-1,类型:{type(error)},失败详情:{error}')
|
|
44
|
+
raise MangoAutomationError(*ERROR_MSG_0011, value=(name,))
|
|
45
|
+
except Error as error:
|
|
46
|
+
self.base_data.log.error(f'WEB自动化操作失败-2,类型:{type(error)},失败详情:{error}')
|
|
47
|
+
raise MangoAutomationError(*ERROR_MSG_0032, value=(name,))
|
|
48
|
+
except ValueError as error:
|
|
49
|
+
self.base_data.log.error(f'WEB自动化操作失败-3,类型:{type(error)},失败详情:{error}')
|
|
50
|
+
raise MangoAutomationError(*ERROR_MSG_0012)
|
|
51
|
+
|
|
52
|
+
def web_assertion_element(self, name, ope_key, ope_value) -> str:
|
|
53
|
+
self.base_data.log.debug(f'断言元素,名称:{name},key:{ope_key},value:{ope_value}')
|
|
54
|
+
is_method = callable(getattr(SyncWebAssertion, ope_key, None))
|
|
55
|
+
try:
|
|
56
|
+
if is_method:
|
|
57
|
+
if ope_value.get('actual', None) is None:
|
|
58
|
+
raise MangoAutomationError(*ERROR_MSG_0031, value=(name,))
|
|
59
|
+
self.base_data.log.debug(f'开始断言-1,方法:{ope_key},断言值:{ope_value}')
|
|
60
|
+
return Mango.s_e(SyncWebAssertion(self.base_data), ope_key, ope_value)
|
|
61
|
+
else:
|
|
62
|
+
self.base_data.log.debug(f'开始断言-2,方法:{ope_key},断言值:{ope_value}')
|
|
63
|
+
return MangoAssertion(self.base_data.mysql_connect, self.base_data.test_data) \
|
|
64
|
+
.ass(ope_key, ope_value.get('actual'), ope_value.get('expect'))
|
|
65
|
+
except AssertionError as error:
|
|
66
|
+
self.base_data.log.debug(f'WEB自动化断言失败-1,类型:{type(error)},失败详情:{error}')
|
|
67
|
+
raise MangoAutomationError(*ERROR_MSG_0017, value=error.args)
|
|
68
|
+
except AttributeError as error:
|
|
69
|
+
self.base_data.log.error(f'WEB自动化断言失败-2,类型:{type(error)},失败详情:{error}')
|
|
70
|
+
raise MangoAutomationError(*ERROR_MSG_0048)
|
|
71
|
+
except ValueError as error:
|
|
72
|
+
self.base_data.log.error(f'WEB自动化断言失败-3,类型:{type(error)},失败详情:{error}')
|
|
73
|
+
raise MangoAutomationError(*ERROR_MSG_0005)
|
|
74
|
+
except Error as error:
|
|
75
|
+
self.base_data.log.error(f'WEB自动化断言失败-4,类型:{type(error)},失败详情:{error}')
|
|
76
|
+
raise MangoAutomationError(*ERROR_MSG_0052, value=(name,), )
|
|
77
|
+
|
|
78
|
+
def web_find_element(self, name, _type, exp, loc, sub, is_iframe) \
|
|
79
|
+
-> tuple[Locator, int, str] | tuple[list[Locator], int, str]:
|
|
80
|
+
self.base_data.log.debug(
|
|
81
|
+
f'查找元素,名称:{name},_type:{_type},exp:{exp},loc:{loc},sub:{sub},is_iframe:{is_iframe}')
|
|
82
|
+
if is_iframe != StatusEnum.SUCCESS.value:
|
|
83
|
+
locator: Locator = self.__find_ele(self.base_data.page, exp, loc)
|
|
84
|
+
try:
|
|
85
|
+
return self.__element_info(locator, sub)
|
|
86
|
+
except Error as error:
|
|
87
|
+
self.base_data.log.debug(
|
|
88
|
+
f'WEB自动化查找元素失败-1,类型:{type(error)},失败详情:{error},失败明细:{traceback.format_exc()}')
|
|
89
|
+
raise MangoAutomationError(*ERROR_MSG_0041, )
|
|
90
|
+
else:
|
|
91
|
+
return self.__is_iframe(_type, exp, loc, sub)
|
|
92
|
+
|
|
93
|
+
def __element_info(self, locator: Locator, sub) -> tuple[Locator, int, str]:
|
|
94
|
+
count = locator.count()
|
|
95
|
+
if count < 1:
|
|
96
|
+
raise MangoAutomationError(*ERROR_MSG_0053)
|
|
97
|
+
if sub is not None:
|
|
98
|
+
loc_result = locator.nth(sub - 1) if sub else locator
|
|
99
|
+
else:
|
|
100
|
+
loc_result = locator.nth(0)
|
|
101
|
+
|
|
102
|
+
try:
|
|
103
|
+
text = self.w_get_text(loc_result)
|
|
104
|
+
except Exception:
|
|
105
|
+
text = None
|
|
106
|
+
return loc_result, count, text
|
|
107
|
+
|
|
108
|
+
def ai_element_info(self, locator: Locator) -> tuple[Locator, int, str]:
|
|
109
|
+
count = locator.count()
|
|
110
|
+
if count < 1:
|
|
111
|
+
raise MangoAutomationError(*ERROR_MSG_0053)
|
|
112
|
+
try:
|
|
113
|
+
text = self.w_get_text(locator.nth(0))
|
|
114
|
+
except Exception:
|
|
115
|
+
text = None
|
|
116
|
+
return locator.nth(0), count, text
|
|
117
|
+
|
|
118
|
+
def __is_iframe(self, _type, exp, loc, sub):
|
|
119
|
+
ele_list: list[Locator] = []
|
|
120
|
+
for i in self.base_data.page.frames:
|
|
121
|
+
locator: Locator = self.__find_ele(i, exp, loc)
|
|
122
|
+
try:
|
|
123
|
+
count = locator.count()
|
|
124
|
+
except Error as error:
|
|
125
|
+
self.base_data.log.debug(
|
|
126
|
+
f'WEB自动化查找元素失败-2,类型:{type(error)},失败详情:{error},失败明细:{traceback.format_exc()}')
|
|
127
|
+
raise MangoAutomationError(*ERROR_MSG_0041, )
|
|
128
|
+
if count > 0:
|
|
129
|
+
for nth in range(0, count):
|
|
130
|
+
ele_list.append(locator.nth(nth))
|
|
131
|
+
else:
|
|
132
|
+
raise MangoAutomationError(*ERROR_MSG_0023)
|
|
133
|
+
try:
|
|
134
|
+
count = len(ele_list)
|
|
135
|
+
loc = ele_list[sub - 1] if sub else ele_list[0]
|
|
136
|
+
try:
|
|
137
|
+
text = self.w_get_text(loc)
|
|
138
|
+
except Exception:
|
|
139
|
+
text = None
|
|
140
|
+
return loc, count, text
|
|
141
|
+
except IndexError:
|
|
142
|
+
raise MangoAutomationError(*ERROR_MSG_0025, value=(len(ele_list),))
|
|
143
|
+
|
|
144
|
+
def __find_ele(self, page, exp, loc) -> Locator:
|
|
145
|
+
if exp == ElementExpEnum.LOCATOR.value:
|
|
146
|
+
try:
|
|
147
|
+
return eval(f"page.{loc}")
|
|
148
|
+
except SyntaxError:
|
|
149
|
+
try:
|
|
150
|
+
return eval(f"await page.{loc}")
|
|
151
|
+
except SyntaxError as error:
|
|
152
|
+
self.base_data.log.error(f'WEB自动化查找元素失败-3,类型:{type(error)},失败详情:{error}')
|
|
153
|
+
raise MangoAutomationError(*ERROR_MSG_0022)
|
|
154
|
+
except NameError as error:
|
|
155
|
+
self.base_data.log.error(f'WEB自动化查找元素失败-4,类型:{type(error)},失败详情:{error}')
|
|
156
|
+
raise MangoAutomationError(*ERROR_MSG_0060)
|
|
157
|
+
elif exp == ElementExpEnum.XPATH.value:
|
|
158
|
+
return page.locator(f'xpath={loc}')
|
|
159
|
+
elif exp == ElementExpEnum.CSS.value:
|
|
160
|
+
return page.locator(loc)
|
|
161
|
+
elif exp == ElementExpEnum.TEXT.value:
|
|
162
|
+
return page.get_by_text(loc, exact=True)
|
|
163
|
+
elif exp == ElementExpEnum.PLACEHOLDER.value:
|
|
164
|
+
return page.get_by_placeholder(loc)
|
|
165
|
+
else:
|
|
166
|
+
raise MangoAutomationError(*ERROR_MSG_0020)
|
|
@@ -14,13 +14,13 @@ from mangotools.mangos import Mango
|
|
|
14
14
|
from ....enums import ElementExpEnum, ElementOperationEnum
|
|
15
15
|
from ....exceptions import MangoAutomationError
|
|
16
16
|
from ....exceptions.error_msg import *
|
|
17
|
-
from ....
|
|
18
|
-
from ....
|
|
19
|
-
from ....
|
|
20
|
-
from ....
|
|
21
|
-
from ....
|
|
22
|
-
from ....
|
|
23
|
-
from ....
|
|
17
|
+
from ....uidrives._base_data import BaseData
|
|
18
|
+
from ....uidrives.web.async_web._assertion import AsyncWebAssertion
|
|
19
|
+
from ....uidrives.web.async_web._browser import AsyncWebBrowser
|
|
20
|
+
from ....uidrives.web.async_web._customization import AsyncWebCustomization
|
|
21
|
+
from ....uidrives.web.async_web._element import AsyncWebElement
|
|
22
|
+
from ....uidrives.web.async_web._input_device import AsyncWebDeviceInput
|
|
23
|
+
from ....uidrives.web.async_web._page import AsyncWebPage
|
|
24
24
|
|
|
25
25
|
re = re
|
|
26
26
|
__all__ = [
|
|
@@ -54,7 +54,7 @@ class AsyncWebDevice(AsyncWebBrowser,
|
|
|
54
54
|
try:
|
|
55
55
|
await Mango.a_e(self, ope_key, ope_value)
|
|
56
56
|
except TimeoutError as error:
|
|
57
|
-
self.base_data.log.
|
|
57
|
+
self.base_data.log.debug(f'WEB自动化操作失败-1,类型:{type(error)},失败详情:{error}')
|
|
58
58
|
raise MangoAutomationError(*ERROR_MSG_0011, value=(name,))
|
|
59
59
|
except Error as error:
|
|
60
60
|
self.base_data.log.error(f'WEB自动化操作失败-2,类型:{type(error)},失败详情:{error}')
|
|
@@ -10,7 +10,7 @@ from mangotools.models import MethodModel
|
|
|
10
10
|
from ....exceptions import MangoAutomationError
|
|
11
11
|
from ....exceptions.error_msg import ERROR_MSG_0021
|
|
12
12
|
from ....tools import Meta
|
|
13
|
-
from ....
|
|
13
|
+
from ....uidrives._base_data import BaseData
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class AsyncWebAssertion(metaclass=Meta):
|
|
@@ -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(n='存储路径', f='path', p='
|
|
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, timeout=10000)
|
|
60
|
+
await self.base_data.page.screenshot(path=os.path.join(self.base_data.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()}')
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
# @Author : 毛鹏
|
|
5
5
|
import asyncio
|
|
6
6
|
import os
|
|
7
|
-
import time
|
|
8
7
|
|
|
8
|
+
import time
|
|
9
9
|
from playwright.async_api import Locator, Error, TimeoutError
|
|
10
10
|
|
|
11
11
|
from mangotools.decorator import async_method_callback
|
|
@@ -25,15 +25,11 @@ 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,直接操作超时!')
|
|
30
28
|
await locating.click()
|
|
31
29
|
|
|
32
30
|
@async_method_callback('web', '元素操作', 1, [MethodModel(f='locating')])
|
|
33
31
|
async def w_dblclick(self, locating: Locator):
|
|
34
32
|
"""元素双击"""
|
|
35
|
-
if await locating.count() < 1:
|
|
36
|
-
raise TimeoutError('元素个数小于1,直接操作超时!')
|
|
37
33
|
await locating.dblclick()
|
|
38
34
|
|
|
39
35
|
@async_method_callback('web', '元素操作', 2, [MethodModel(f='locating')])
|
|
@@ -46,8 +42,6 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
46
42
|
MethodModel(n='输入内容', f='input_value', p='请输入输入内容', d=True)])
|
|
47
43
|
async def w_input(self, locating: Locator, input_value: str):
|
|
48
44
|
"""元素输入"""
|
|
49
|
-
if await locating.count() < 1:
|
|
50
|
-
raise TimeoutError('元素个数小于1,直接操作超时!')
|
|
51
45
|
await locating.fill(str(input_value))
|
|
52
46
|
|
|
53
47
|
@async_method_callback('web', '元素操作', 4, [MethodModel(f='locating')])
|
|
@@ -61,8 +55,6 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
61
55
|
MethodModel(n='缓存的key', f='set_cache_key', p='请输入获取元素文本后存储的key', d=True)])
|
|
62
56
|
async def w_get_text(self, locating: Locator, set_cache_key=None):
|
|
63
57
|
"""获取元素文本"""
|
|
64
|
-
if await locating.count() < 1:
|
|
65
|
-
raise TimeoutError('元素个数小于1,直接操作超时!')
|
|
66
58
|
methods = [
|
|
67
59
|
("inner_text", locating.inner_text),
|
|
68
60
|
("text_content", locating.text_content),
|
|
@@ -87,8 +79,6 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
87
79
|
MethodModel(n='输入文本', f='input_value', p='请输入输入内容', d=True)])
|
|
88
80
|
async def w_clear_input(self, locating: Locator, input_value: str):
|
|
89
81
|
"""元素清空再输入"""
|
|
90
|
-
if await locating.count() < 1:
|
|
91
|
-
raise TimeoutError('元素个数小于1,直接操作超时!')
|
|
92
82
|
await locating.clear()
|
|
93
83
|
await locating.fill(str(input_value))
|
|
94
84
|
|
|
@@ -237,10 +227,10 @@ class AsyncWebElement(metaclass=Meta):
|
|
|
237
227
|
|
|
238
228
|
@async_method_callback('web', '元素操作', 15, [
|
|
239
229
|
MethodModel(f='locating'),
|
|
240
|
-
MethodModel(n='保存路径', f='path', p='
|
|
230
|
+
MethodModel(n='保存路径', f='path', p='请输入截图名称', d=True)])
|
|
241
231
|
async def w_ele_screenshot(self, locating: Locator, path: str):
|
|
242
232
|
"""元素截图"""
|
|
243
|
-
await locating.screenshot(path=path)
|
|
233
|
+
await locating.screenshot(path=os.path.join(self.base_data.download_path, path))
|
|
244
234
|
|
|
245
235
|
@async_method_callback('web', '元素操作', 20, [
|
|
246
236
|
MethodModel(f='locating1'),
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
from mangotools.decorator import async_method_callback
|
|
7
7
|
from mangotools.models import MethodModel
|
|
8
8
|
from ....tools import Meta
|
|
9
|
-
from ....
|
|
9
|
+
from ....uidrives._base_data import BaseData
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class AsyncWebDeviceInput(metaclass=Meta):
|
|
@@ -9,7 +9,7 @@ from playwright.async_api import Locator
|
|
|
9
9
|
from mangotools.decorator import async_method_callback
|
|
10
10
|
from mangotools.models import MethodModel
|
|
11
11
|
from ....tools import Meta
|
|
12
|
-
from ....
|
|
12
|
+
from ....uidrives._base_data import BaseData
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class AsyncWebPage(metaclass=Meta):
|