mangoautomation 1.1.22__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.

Files changed (39) hide show
  1. mangoautomation/enums/__init__.py +0 -1
  2. mangoautomation/exceptions/__init__.py +0 -2
  3. mangoautomation/exceptions/error_msg.py +3 -3
  4. mangoautomation/mangos/__init__.py +14 -0
  5. mangoautomation/mangos/__pycache__/__init__.cpython-310.pyc +0 -0
  6. mangoautomation/mangos/mangos.cp310-win_amd64.pyd +0 -0
  7. mangoautomation/mangos/mangos.cp312-win_amd64.pyd +0 -0
  8. mangoautomation/mangos/mangos.cpython-310-darwin.so +0 -0
  9. mangoautomation/mangos/mangos.cpython-310-x86_64-linux-gnu.so +0 -0
  10. mangoautomation/mangos/mangos.cpython-312-darwin.so +0 -0
  11. mangoautomation/mangos/mangos.cpython-312-x86_64-linux-gnu.so +0 -0
  12. mangoautomation/models/__init__.py +0 -1
  13. mangoautomation/models/_ui_model.py +1 -0
  14. mangoautomation/tools/__init__.py +0 -1
  15. mangoautomation/tools/_uiautodev.py +1 -1
  16. mangoautomation/uidrives/__init__.py +2 -3
  17. mangoautomation/uidrives/_async_element.py +74 -48
  18. mangoautomation/uidrives/_base_data.py +16 -4
  19. mangoautomation/uidrives/_driver_object.py +2 -4
  20. mangoautomation/uidrives/_sync_element.py +75 -46
  21. mangoautomation/uidrives/android/__init__.py +2 -16
  22. mangoautomation/uidrives/pc/__init__.py +1 -2
  23. mangoautomation/uidrives/pc/element.py +1 -2
  24. mangoautomation/uidrives/pc/input_device.py +1 -2
  25. mangoautomation/uidrives/web/__init__.py +5 -0
  26. mangoautomation/uidrives/web/_async_web.py +166 -0
  27. mangoautomation/uidrives/web/_sync_web.py +166 -0
  28. mangoautomation/uidrives/web/async_web/_element.py +0 -10
  29. mangoautomation/uidrives/web/sync_web/_element.py +0 -10
  30. {mangoautomation-1.1.22.dist-info → mangoautomation-1.1.23.dist-info}/METADATA +3 -3
  31. mangoautomation-1.1.23.dist-info/RECORD +71 -0
  32. tests/__init__.py +0 -10
  33. tests/demo1.py +21 -0
  34. tests/test_ai_element.py +36 -0
  35. tests/test_ui_web.py +7 -3
  36. mangoautomation-1.1.22.dist-info/RECORD +0 -59
  37. {mangoautomation-1.1.22.dist-info → mangoautomation-1.1.23.dist-info}/LICENSE +0 -0
  38. {mangoautomation-1.1.22.dist-info → mangoautomation-1.1.23.dist-info}/WHEEL +0 -0
  39. {mangoautomation-1.1.22.dist-info → mangoautomation-1.1.23.dist-info}/top_level.txt +0 -0
@@ -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)
@@ -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
 
@@ -24,15 +24,11 @@ class SyncWebElement(metaclass=Meta):
24
24
  @sync_method_callback('web', '元素操作', 0, [MethodModel(f='locating')])
25
25
  def w_click(self, locating: Locator):
26
26
  """元素单击"""
27
- if locating.count() < 1:
28
- raise TimeoutError('元素个数小于1,直接操作超时!')
29
27
  locating.click()
30
28
 
31
29
  @sync_method_callback('web', '元素操作', 1, [MethodModel(f='locating')])
32
30
  def w_dblclick(self, locating: Locator):
33
31
  """元素双击"""
34
- if locating.count() < 1:
35
- raise TimeoutError('元素个数小于1,直接操作超时!')
36
32
  locating.dblclick()
37
33
 
38
34
  @sync_method_callback('web', '元素操作', 2, [MethodModel(f='locating')])
@@ -45,8 +41,6 @@ class SyncWebElement(metaclass=Meta):
45
41
  MethodModel(n='输入文本', f='input_value', p='请输入输入内容', d=True)])
46
42
  def w_input(self, locating: Locator, input_value: str):
47
43
  """元素输入"""
48
- if locating.count() < 1:
49
- raise TimeoutError('元素个数小于1,直接操作超时!')
50
44
  locating.fill(str(input_value))
51
45
 
52
46
  @sync_method_callback('web', '元素操作', 4, [MethodModel(f='locating')])
@@ -60,8 +54,6 @@ class SyncWebElement(metaclass=Meta):
60
54
  MethodModel(n='缓存的key', f='set_cache_key', p='请输入获取元素文本后存储的key', d=True)])
61
55
  def w_get_text(self, locating: Locator, set_cache_key=None):
62
56
  """获取元素文本"""
63
- if locating.count() < 1:
64
- raise TimeoutError('元素个数小于1,直接操作超时!')
65
57
  methods = [
66
58
  ("inner_text", lambda: locating.inner_text()),
67
59
  ("text_content", lambda: locating.text_content()),
@@ -86,8 +78,6 @@ class SyncWebElement(metaclass=Meta):
86
78
  MethodModel(n='输入文本', f='input_value', p='请输入输入内容', d=True)])
87
79
  def w_clear_input(self, locating: Locator, input_value: str):
88
80
  """元素清空再输入"""
89
- if locating.count() < 1:
90
- raise TimeoutError('元素个数小于1,直接操作超时!')
91
81
  locating.clear()
92
82
  locating.fill(str(input_value))
93
83
 
@@ -1,14 +1,12 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mangoautomation
3
- Version: 1.1.22
3
+ Version: 1.1.23
4
4
  Summary: 测试工具
5
5
  Home-page: https://gitee.com/mao-peng/testkit
6
6
  Author: 毛鹏
7
7
  Author-email: 729164035@qq.com
8
8
  Classifier: Programming Language :: Python :: 3.10
9
- Classifier: Programming Language :: Python :: 3.11
10
9
  Classifier: Programming Language :: Python :: 3.12
11
- Classifier: Programming Language :: Python :: 3.13
12
10
  License-File: LICENSE
13
11
  Requires-Dist: setuptools ==78.1.1
14
12
  Requires-Dist: pydantic >=2.9.2
@@ -18,6 +16,8 @@ Requires-Dist: uiautomator2 >=3.2.5
18
16
  Requires-Dist: mangotools >=1.1.42
19
17
  Requires-Dist: adbutils ~=2.8.9
20
18
  Requires-Dist: uiautodev >=0.9.0
19
+ Requires-Dist: beautifulsoup4 ==4.14.2
20
+ Requires-Dist: openai ==2.6.1
21
21
 
22
22
  # testkit
23
23
 
@@ -0,0 +1,71 @@
1
+ mangoautomation/__init__.py,sha256=JxPNVexFQvkBfh0awPNeHxQGU_gtVgYPwD5rYeuHWEk,125
2
+ mangoautomation/enums/__init__.py,sha256=PnOgNttAXT64elr_Fd1ZthuAddCkm7sh4xwm9Eutm_I,373
3
+ mangoautomation/enums/_base_enum.py,sha256=dpaXsdhWY08BhIzi1B1ksh_p18ZTmhWvTYhbd3n_ONQ,1176
4
+ mangoautomation/enums/_ui_enum.py,sha256=mT_MfQ7TEw-BgHIqH0wXTA_yVWsaWnd3iHSHi9E0pgA,4599
5
+ mangoautomation/exceptions/__init__.py,sha256=2j3ravPuzljR2Mbq8J2JLdXUzII7hzrjdVjmEc_NHJU,211
6
+ mangoautomation/exceptions/_exceptions.py,sha256=BiyST1QPivpfIOuKn1gKhpXOyBv6gfip_KvlQuu8ctw,385
7
+ mangoautomation/exceptions/error_msg.py,sha256=0unQ_tgrRJtVMAOXTzhQJkwO4_7lhMKAMMCfwmzQD58,5517
8
+ mangoautomation/mangos/__init__.py,sha256=gEu8lVHGXm8PDTBZ1XXWNUOAbCtHb37uKQLBRYQR4rs,644
9
+ mangoautomation/mangos/mangos.cp310-win_amd64.pyd,sha256=XkKi2OyGgDxX7lJQnNuJMGiL4b-vntDLwo4wAmOUdrg,1751552
10
+ mangoautomation/mangos/mangos.cp312-win_amd64.pyd,sha256=5ajaOne3Kb1yNEb3Eci1bvjzKIuiJaTPfwBY3f_MK0o,1879040
11
+ mangoautomation/mangos/mangos.cpython-310-darwin.so,sha256=HwZCN0lpGKdAzvygPA4O4Q_xyAd7aDcrZFUzWSqZcWI,3555568
12
+ mangoautomation/mangos/mangos.cpython-310-x86_64-linux-gnu.so,sha256=EaTWB-R4yHJYfkwF0P_YMjlBKY35KTTKrDsAaKCqAZo,10465816
13
+ mangoautomation/mangos/mangos.cpython-312-darwin.so,sha256=iG43WcChIPozrKK98MqBTqDlZFNxKjQSyB0CKu0mIaE,3456880
14
+ mangoautomation/mangos/mangos.cpython-312-x86_64-linux-gnu.so,sha256=P1Hax5huyMm-7eeuWby9mWmTI2HW3JEA8mSvIl65aAk,10670984
15
+ mangoautomation/mangos/__pycache__/__init__.cpython-310.pyc,sha256=kQcwQCOca8l62vfKIC6YKi0lEIUV3Vjnel0ox2bDbOc,608
16
+ mangoautomation/models/__init__.py,sha256=wHACwBCrd9HCvmrAkTFUV3qmK9GnOa-FJFiL0kOQjME,309
17
+ mangoautomation/models/_ui_model.py,sha256=nfxh_4TpOLzKKWC7c-IgMLVZY5wkTPfyS_Oh-SvsYsk,1825
18
+ mangoautomation/tools/__init__.py,sha256=c3IXhoodknOukOyM6db2tXIdDRodgmUZorEAkkruQf0,282
19
+ mangoautomation/tools/_mate.py,sha256=9lk_EJnAX_OyXbe5WacyHkkcEr2ScBgasl6eUnlklWA,405
20
+ mangoautomation/tools/_uiautodev.py,sha256=KYYWOQ_sp91LN_zeKAuIvCqjabb2_1-VhgOg1K7cQrw,1372
21
+ mangoautomation/uidrive/__init__.py,sha256=9N2DTDyLcmgxAHctBjZOb8LwdDeKQnwEOWZ9kNcM4Uw,350
22
+ mangoautomation/uidrives/__init__.py,sha256=JEoWqpoDIch8JiQ7WcnuDh3Bjg0Yqo_xfkbqY5iHSa8,617
23
+ mangoautomation/uidrives/_async_element.py,sha256=87BhadK9BJtcv_VzJUM3kX5sdp8b8Kk-abkU9oE3T7M,16206
24
+ mangoautomation/uidrives/_base_data.py,sha256=gp9730Hd8uarRv8xARIddgMWGhaJ_RKDd_gjewwWr04,4436
25
+ mangoautomation/uidrives/_driver_object.py,sha256=VnnmXO-BODhqEDmqwb2U0G5FwLRdrBKvkrLE2mwC6gs,1951
26
+ mangoautomation/uidrives/_sync_element.py,sha256=TU2E7AKz0Ku4qXLEtxx-whJPJ4KLYLK_EuKgChpcedM,15906
27
+ mangoautomation/uidrives/android/__init__.py,sha256=i6WjXlNq6oUZ4y79Gih_XzI9tV7du-Jrm9IAuROgSzo,5180
28
+ mangoautomation/uidrives/android/_application.py,sha256=G94m53cUzzGuXxPIsvoMuFwJ5RWL_xW5HHFE0TIkrBI,2855
29
+ mangoautomation/uidrives/android/_assertion.py,sha256=FH8sxJC4ZXCbVA9KFBp49Tu8LPWyO26EZYAK7cYaoYE,4350
30
+ mangoautomation/uidrives/android/_customization.py,sha256=7C8j2rv2wDkNu425ooxLSDrGHr_CxJ82sXz1-64id_8,382
31
+ mangoautomation/uidrives/android/_element.py,sha256=ggWEFUbrAGWPQXNvD9JpudwowwvYJrgHdrNXyytAEVw,7213
32
+ mangoautomation/uidrives/android/_equipment.py,sha256=Ul61jpoVr162FIu_2QcJtqWil82ZBC-Kn7_VFQWCUsQ,5216
33
+ mangoautomation/uidrives/android/_new_android.py,sha256=WldFsGm5QnJ9QVPtWxRgwCiWSX3jYObFxAPCQ5xSKyg,1636
34
+ mangoautomation/uidrives/android/_page.py,sha256=IaWiN3kniv2GKfudMLRdvyaqbFLuIfGh7H0HeQrDyVA,4621
35
+ mangoautomation/uidrives/ios/__init__.py,sha256=SdxI8e5AOoAb8JTaDoMkObezIluJ50nm2b6zeDHv1PI,125
36
+ mangoautomation/uidrives/pc/__init__.py,sha256=Jphhspu-3AHCyDX5ZM_-DWeC9ZerWy2Omb3MOck6CI4,2210
37
+ mangoautomation/uidrives/pc/assertion.py,sha256=mH25hZ2i4T8kA1F2loW_nuPJ-Hb0z1pwILTJqkwwpLA,125
38
+ mangoautomation/uidrives/pc/customization.py,sha256=UkpHWFSYsu_t-GmMRDmii1Bs_Y1eKD34oZfJBFHV2Ng,240
39
+ mangoautomation/uidrives/pc/element.py,sha256=OGbJHbgJPBjRjXqM-NIWUnScn7lIHoBxnrakog_s4l8,465
40
+ mangoautomation/uidrives/pc/input_device.py,sha256=k-v7tRW8NkJxzcezqSIfICGRBqEdsssBeRTmtupVTU8,299
41
+ mangoautomation/uidrives/pc/new_windows.py,sha256=lETHZa7cW8Z0iUShzgVTRxqivkYaOo8WIE58q_8KYfQ,2338
42
+ mangoautomation/uidrives/web/__init__.py,sha256=TJyYt6EUoRfWYrV193RHpopKfixipVUp4TrhB5DoEKA,434
43
+ mangoautomation/uidrives/web/_async_web.py,sha256=Uwta7cIYo-0Qe5RbaIvRSQ-IvOxCNtbH_RcIm1JNxEQ,8204
44
+ mangoautomation/uidrives/web/_sync_web.py,sha256=NCF97mYWQBLsOkcEXHKbAGLYGt4rK7NSjks6PubLe_k,8049
45
+ mangoautomation/uidrives/web/async_web/__init__.py,sha256=_jG4DvEbNe4EZTFEBKQhgwRxxIzrdK7APmIicFb0zMk,8379
46
+ mangoautomation/uidrives/web/async_web/_assertion.py,sha256=cG8g_iFMlWcAMDyIfPTJ5lx73BpbGZV5PoAbe1uAy4Q,12821
47
+ mangoautomation/uidrives/web/async_web/_browser.py,sha256=xAaawPbY-rj-HZtcy5LcWUQ_jmdN9Dj4yNUxWxXGCbQ,5421
48
+ mangoautomation/uidrives/web/async_web/_customization.py,sha256=LakibDXpSc-MMxMiwDiktoFccgyiUmWxAVpMOobY9_A,347
49
+ mangoautomation/uidrives/web/async_web/_element.py,sha256=fVJWBUI0C2eFYP8XhLkW2Cez2gdYP1j0PcIBVDzUEk4,10507
50
+ mangoautomation/uidrives/web/async_web/_input_device.py,sha256=wd36vTwsWdq7f52HmEnAF2sNiFVwNxJ2J5bq-lcuuVk,3441
51
+ mangoautomation/uidrives/web/async_web/_new_browser.py,sha256=v-OXD-uYD7XagupxSlG4g_ZBsRq_Jpo88iwE_A_Ilfs,6202
52
+ mangoautomation/uidrives/web/async_web/_page.py,sha256=B1RbnPWaQWa3Sp57ue2sTgcgEr4kTgSEz0DcpA5lOug,2176
53
+ mangoautomation/uidrives/web/sync_web/__init__.py,sha256=gThDpZPtCFdKrxnVYgAsj_6oha9lMed7xoU4XTsLOys,7945
54
+ mangoautomation/uidrives/web/sync_web/_assertion.py,sha256=GEUGvYd3LgisMTgiinFF-Z6nWqxA4EUbvHenw7rPaW0,12595
55
+ mangoautomation/uidrives/web/sync_web/_browser.py,sha256=_Z6NhhP_6N-cxak3X8yUnPzUet7b1tBpI85iAbzwoyQ,5286
56
+ mangoautomation/uidrives/web/sync_web/_customization.py,sha256=Wir5CIGN6YiyVj1-D_zvSWcFuUvQMP8rJ-8boUaU1Bs,356
57
+ mangoautomation/uidrives/web/sync_web/_element.py,sha256=T8Za5wTzSlPleJMz0XkRCbnqSk8OpLHMs3_TalF7xrE,10157
58
+ mangoautomation/uidrives/web/sync_web/_input_device.py,sha256=SwsFi4PiS3sg45MPl_NV88nDrg4SmJ14fV8sODByQ58,3288
59
+ mangoautomation/uidrives/web/sync_web/_new_browser.py,sha256=APGUFhOVAW68x-6y9tQLZJkn2utfR-PrpjgP8WE38SE,6149
60
+ mangoautomation/uidrives/web/sync_web/_page.py,sha256=GbVsK7ZBcoMBnKw2VMPWy3Yt9Jqa84qxrB2Ar2d8aR8,2046
61
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
+ tests/demo1.py,sha256=5iK5kqaMkebTk-Z4HoMnfi88CRUIBKwT8PVQXFaqgD4,736
63
+ tests/get_ope.py,sha256=SVhSowMNa87hjzGhFlS0vp-t0RB9yKHOC52FsO93UG4,236
64
+ tests/test_ai_element.py,sha256=k__iifxebvPPfGdRS-yzkEH80fBIlKJcZ-m3N6Xkz6Q,1437
65
+ tests/test_ui_and.py,sha256=A_0pqG6s5Ts02He7P3NwuDSK3g9Q3VP1Sb_P8wq6g0Q,125
66
+ tests/test_ui_web.py,sha256=RBACNYc7XdvENHzg4YElsSQlEmPVa_AyOKWTYTPXM14,2578
67
+ mangoautomation-1.1.23.dist-info/LICENSE,sha256=03WP-mgFmo8ofRYDe1HVDQUEUKQZ2q6P6Q-2A4c-46A,1085
68
+ mangoautomation-1.1.23.dist-info/METADATA,sha256=wbPR7Rb4WurD4bh8nDEoKhLSumkIIMM2008pk-Skvso,783
69
+ mangoautomation-1.1.23.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
70
+ mangoautomation-1.1.23.dist-info/top_level.txt,sha256=g-uCmjvEODG8WFbmwbGM0-G0zHntHv8ZsS0PQRaMGtE,22
71
+ mangoautomation-1.1.23.dist-info/RECORD,,
tests/__init__.py CHANGED
@@ -1,10 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # @Project: 芒果测试平台
3
- # @Description:
4
- # @Time : 2024-09-07 23:25
5
- # @Author : 毛鹏
6
- import random
7
-
8
- data_list = [{'exp': 2, 'loc': 'get_by_role("textbox", name="请输入1密码")'},
9
- {'exp': 0, 'loc': '//input[@type="password"]'}]
10
- print(random.randint(0, len(data_list) - 1), len(data_list))
tests/demo1.py ADDED
@@ -0,0 +1,21 @@
1
+ from openai import OpenAI
2
+
3
+ client = OpenAI(api_key="sk-rruuhjnqawsvduyxlcqckbtgwkprctgkvwcelenooixbhthy",
4
+ base_url="https://api.siliconflow.cn/v1")
5
+ response = client.chat.completions.create(
6
+ # model='Pro/deepseek-ai/DeepSeek-R1',
7
+ model="THUDM/GLM-Z1-9B-0414",
8
+ messages=[
9
+ {'role': 'user',
10
+ 'content': "推理模型会给市场带来哪些新的机会"}
11
+ ],
12
+ stream=True
13
+ )
14
+
15
+ for chunk in response:
16
+ if not chunk.choices:
17
+ continue
18
+ if chunk.choices[0].delta.content:
19
+ print(chunk.choices[0].delta.content, end="", flush=True)
20
+ if chunk.choices[0].delta.reasoning_content:
21
+ print(chunk.choices[0].delta.reasoning_content, end="", flush=True)
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+ # @Project: 芒果测试平台
3
+ # @Description:
4
+ # @Time : 2025-10-28 10:32
5
+ # @Author : 毛鹏
6
+ import unittest
7
+
8
+ import time
9
+
10
+ from .demo1 import WebAIFinder
11
+ from mangoautomation.uidrive import BaseData, DriverObject, SyncElement
12
+ from mangoautomation.uidrives import AsyncElement
13
+ from mangotools.data_processor import DataProcessor
14
+ from mangotools.log_collector import set_log
15
+ # api_key = 'sk-'
16
+ # b = 'https://api.siliconflow.cn/v1'
17
+ # model = 'THUDM/GLM-Z1-9B-0414'
18
+ log = set_log('D:\code\mango_automation\logs')
19
+ log.set_debug(True)
20
+ test_data = DataProcessor()
21
+
22
+
23
+ class TestUi(unittest.IsolatedAsyncioTestCase):
24
+ async def test_a(self):
25
+ driver_object = DriverObject(log, is_async=True)
26
+ driver_object.set_web(0, r"C:\Program Files\Google\Chrome\Application\chrome.exe")
27
+ base_data = BaseData(test_data, log)
28
+ base_data.url = 'https://www.baidu.com/'
29
+ base_data.context, base_data.page = await driver_object.web.new_web_page()
30
+ element = AsyncElement(base_data, 0)
31
+ await element.open_url()
32
+ loc = await WebAIFinder(log, api_key, b, model).ai_find_element_async(base_data.page, '设置', '设置在右上角', ['//*[text()="设置"]'])
33
+ await element.w_hover(loc)
34
+ print('获取元素名称:', await element.w_get_text(loc))
35
+ time.sleep(5)
36
+ assert await element.w_get_text(loc) == '设置'
tests/test_ui_web.py CHANGED
@@ -12,6 +12,7 @@ from mangotools.data_processor import DataProcessor
12
12
  from mangotools.log_collector import set_log
13
13
 
14
14
  log = set_log('D:\code\mango_automation\logs')
15
+ log.set_debug(True)
15
16
  test_data = DataProcessor()
16
17
  element_model = ElementModel(**{
17
18
  "id": 3,
@@ -20,9 +21,10 @@ element_model = ElementModel(**{
20
21
  "elements": [
21
22
  {
22
23
  "exp": 0,
23
- "loc": "//span[@name=\"tj_settingicon\"]",
24
+ "loc": "//span[@name=\"tj_settingicons\"]",
24
25
  "sub": None,
25
- "is_iframe": 0
26
+ "is_iframe": 0,
27
+ "prompt": "设置"
26
28
  }
27
29
  ],
28
30
  "sleep": None,
@@ -47,7 +49,8 @@ class TestUi(unittest.IsolatedAsyncioTestCase):
47
49
  async def test_a(self):
48
50
  driver_object = DriverObject(log, True)
49
51
  driver_object.set_web(0, r"C:\Program Files\Google\Chrome\Application\chrome.exe")
50
- base_data = BaseData(test_data, log)
52
+ base_data = BaseData(test_data, log).set_agent(True, 'sk-rruuhjnqawsvduyxlcqckbtgwkprctgkvwcelenooixbhthy')
53
+ base_data.screenshot_path = r'D:\code\mango_automation\logs'
51
54
  base_data.log = log
52
55
  base_data.url = 'https://www.baidu.com/'
53
56
 
@@ -56,6 +59,7 @@ class TestUi(unittest.IsolatedAsyncioTestCase):
56
59
  await element.open_url()
57
60
  await asyncio.sleep(5)
58
61
  await element.element_main(element_model, )
62
+ print(element.element_result_model.model_dump_json())
59
63
  assert element.element_result_model.elements[0].element_text == '设置'
60
64
 
61
65