mops 0.0.1a2__tar.gz

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.
mops-0.0.1a2/PKG-INFO ADDED
@@ -0,0 +1,96 @@
1
+ Metadata-Version: 2.1
2
+ Name: mops
3
+ Version: 0.0.1a2
4
+ Summary: Wrapper of Selenium, Appium and Playwright with single API
5
+ Author-email: Podolian Vladimir <vladimir.podolyan64@gmail.com>
6
+ License: MIT
7
+ Project-URL: Changelog, https://github.com/CustomEnv/mops/blob/master/CHANGELOG.md
8
+ Project-URL: Documentation, https://mops.readthedocs.io
9
+ Project-URL: Homepage, https://github.com/CustomEnv/mops
10
+ Project-URL: Source, https://github.com/CustomEnv/mops
11
+ Project-URL: Tracker, https://github.com/CustomEnv/mops/issues
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Classifier: Topic :: Software Development :: Quality Assurance
21
+ Classifier: Topic :: Software Development :: Testing :: Acceptance
22
+ Requires-Python: >=3.8
23
+ Description-Content-Type: text/markdown
24
+ Requires-Dist: Appium-Python-Client>=3.1.0
25
+ Requires-Dist: playwright>=1.41.0
26
+ Requires-Dist: selenium>=4.12.0
27
+ Requires-Dist: numpy>=2.0.1; python_version >= "3.11"
28
+ Requires-Dist: numpy<2.0.0,>=1.24.2; python_version >= "3.8" and python_version <= "3.10"
29
+ Requires-Dist: opencv-python>=4.10.0.84; python_version >= "3.11"
30
+ Requires-Dist: opencv-python<4.10.0.84,>=4.5.5.64; python_version >= "3.8" and python_version <= "3.10"
31
+ Requires-Dist: scikit-image>=0.24.0; python_version >= "3.11"
32
+ Requires-Dist: scikit-image<0.24.0,>=0.20.0; python_version >= "3.8" and python_version <= "3.10"
33
+ Requires-Dist: Pillow>=10.4.0; python_version >= "3.12"
34
+ Requires-Dist: Pillow<10.4.0,>=9.4.0; python_version >= "3.8" and python_version <= "3.11"
35
+
36
+ <p align="center">
37
+ <a href="https://mops.readthedocs.io"><img src="docs/source/_static/preview.png"></a>
38
+ </p>
39
+
40
+ <h2 align="center">Automation Beyond Limits</h2>
41
+
42
+ <p align="center">
43
+ <a href="https://github.com/CustomEnv/mops/blob/master/LICENSE"><img alt="GitHub License" src="https://img.shields.io/github/license/CustomEnv/mops?logo=github&color=%234F2684&labelColor=%232E353B"></a>
44
+ <a href="https://pypi.org/project/mops/"><img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/mops?logo=pypi&labelColor=%232E353B"></a>
45
+ <a href="https://pypi.org/project/mops/"><img alt="PyPI - Version" src="https://img.shields.io/pypi/v/mops?logo=pypi&labelColor=%232E353B"></a>
46
+ </p>
47
+
48
+ <p align="center">
49
+ <a href="https://mops.readthedocs.io"><img alt="Documentation Status" src="https://img.shields.io/readthedocs/mops?logo=readthedocs&labelColor=%232E353B&label=docs"></a>
50
+ <a href="https://github.com/CustomEnv/mops/actions/workflows/static_tests.yml"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/CustomEnv/mops/static_tests.yml?logo=github&label=Unit%20Tests&labelColor=%232E353B"></a>
51
+ <a href="https://github.com/CustomEnv/mops/actions/workflows/playwright_tests.yml"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/CustomEnv/mops/playwright_tests.yml?logo=github&label=Playwright%20Tests&labelColor=%232E353B"></a>
52
+ </p>
53
+
54
+ <p align="center">
55
+ <a href="https://github.com/CustomEnv/mops/actions/workflows/selenium_tests.yml"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/CustomEnv/mops/selenium_tests.yml?logo=github&label=Selenium%20Tests&labelColor=%232E353B"></a>
56
+ <a href="https://github.com/CustomEnv/mops/actions/workflows/selenium_safari_tests.yml"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/CustomEnv/mops/selenium_safari_tests.yml?logo=github&label=Selenium%20Safari%20Tests&labelColor=%232E353B"></a>
57
+ <a href="https://github.com/CustomEnv/mops/actions/workflows/appium_android_tests.yml"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/CustomEnv/mops/appium_android_tests.yml?logo=github&label=Android%20Tests&labelColor=%232E353B"></a>
58
+ <a href="https://github.com/CustomEnv/mops/actions/workflows/appium_ios_tests.yml"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/CustomEnv/mops/appium_ios_tests.yml?logo=github&label=iOS%20Tests&labelColor=%232E353B"></a>
59
+ </p>
60
+
61
+
62
+ Mops is a Python framework that seamlessly wraps over Selenium, Appium, and sync Playwright,
63
+ providing a unified interface for browser and mobile automation. With Mops, you can effortlessly switch
64
+ between these engines within the same test, allowing you to leverage the unique features of each framework without boundaries.
65
+
66
+ Whether you're running tests on web browsers, mobile devices, or a combination of both, Mops simplifies the
67
+ process, giving you the flexibility and power to automate complex testing scenarios with ease.
68
+
69
+ ## Key Features
70
+
71
+ - **Seamless Integration**: Mops integrates with Selenium, Appium, and Playwright, allowing you to use the best-suited engine for your specific testing needs.
72
+ - **Unified API**: A single, easy-to-use API that abstracts away the differences between Selenium, Appium, and Playwright, making your test scripts more readable and maintainable.
73
+ - **Engine Switching**: Switch between Selenium, Appium, and Playwright within the same test case, enabling cross-platform and cross-browser testing with minimal effort.
74
+ - **Visual Regression Testing**: Perform visual regression tests using the integrated visual regression tool, available across all supported frameworks. This ensures your UI remains consistent across different browsers and devices.
75
+ - **Advanced Features**: Leverage the advanced features of each framework, such as Playwright's mocks and Appium's real mobile devices support, all while using the same testing framework.
76
+ - **Extensibility**: Extend the framework with custom functionality tailored to your project's specific requirements.
77
+ - **Automatic Locator Type Definition**: The locator type will be automatically determined based on the provided locator string or `Locator` object.
78
+
79
+
80
+ ## Installation and usage
81
+ For information on installation and usage, please refer to our **[ReadTheDocs documentation](https://mops.readthedocs.io)**. Check it out for more details.
82
+
83
+
84
+ ## Contributing
85
+
86
+ Mops is an open-source project, and we welcome contributions from the community. If you'd like to contribute, please open an pull request from your fork
87
+
88
+ ## License
89
+
90
+ Mops is licensed under the Apache License. See the [LICENSE](https://github.com/CustomEnv/mops/blob/master/LICENSE) file for more details.
91
+
92
+ ## Support
93
+
94
+ If you encounter any issues or have questions, please feel free to reach out via our [GitHub Issues](https://github.com/CustomEnv/mops/issues) page.
95
+
96
+ Thank you for choosing Mops for your automation needs!
mops-0.0.1a2/README.md ADDED
@@ -0,0 +1,61 @@
1
+ <p align="center">
2
+ <a href="https://mops.readthedocs.io"><img src="docs/source/_static/preview.png"></a>
3
+ </p>
4
+
5
+ <h2 align="center">Automation Beyond Limits</h2>
6
+
7
+ <p align="center">
8
+ <a href="https://github.com/CustomEnv/mops/blob/master/LICENSE"><img alt="GitHub License" src="https://img.shields.io/github/license/CustomEnv/mops?logo=github&color=%234F2684&labelColor=%232E353B"></a>
9
+ <a href="https://pypi.org/project/mops/"><img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/mops?logo=pypi&labelColor=%232E353B"></a>
10
+ <a href="https://pypi.org/project/mops/"><img alt="PyPI - Version" src="https://img.shields.io/pypi/v/mops?logo=pypi&labelColor=%232E353B"></a>
11
+ </p>
12
+
13
+ <p align="center">
14
+ <a href="https://mops.readthedocs.io"><img alt="Documentation Status" src="https://img.shields.io/readthedocs/mops?logo=readthedocs&labelColor=%232E353B&label=docs"></a>
15
+ <a href="https://github.com/CustomEnv/mops/actions/workflows/static_tests.yml"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/CustomEnv/mops/static_tests.yml?logo=github&label=Unit%20Tests&labelColor=%232E353B"></a>
16
+ <a href="https://github.com/CustomEnv/mops/actions/workflows/playwright_tests.yml"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/CustomEnv/mops/playwright_tests.yml?logo=github&label=Playwright%20Tests&labelColor=%232E353B"></a>
17
+ </p>
18
+
19
+ <p align="center">
20
+ <a href="https://github.com/CustomEnv/mops/actions/workflows/selenium_tests.yml"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/CustomEnv/mops/selenium_tests.yml?logo=github&label=Selenium%20Tests&labelColor=%232E353B"></a>
21
+ <a href="https://github.com/CustomEnv/mops/actions/workflows/selenium_safari_tests.yml"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/CustomEnv/mops/selenium_safari_tests.yml?logo=github&label=Selenium%20Safari%20Tests&labelColor=%232E353B"></a>
22
+ <a href="https://github.com/CustomEnv/mops/actions/workflows/appium_android_tests.yml"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/CustomEnv/mops/appium_android_tests.yml?logo=github&label=Android%20Tests&labelColor=%232E353B"></a>
23
+ <a href="https://github.com/CustomEnv/mops/actions/workflows/appium_ios_tests.yml"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/CustomEnv/mops/appium_ios_tests.yml?logo=github&label=iOS%20Tests&labelColor=%232E353B"></a>
24
+ </p>
25
+
26
+
27
+ Mops is a Python framework that seamlessly wraps over Selenium, Appium, and sync Playwright,
28
+ providing a unified interface for browser and mobile automation. With Mops, you can effortlessly switch
29
+ between these engines within the same test, allowing you to leverage the unique features of each framework without boundaries.
30
+
31
+ Whether you're running tests on web browsers, mobile devices, or a combination of both, Mops simplifies the
32
+ process, giving you the flexibility and power to automate complex testing scenarios with ease.
33
+
34
+ ## Key Features
35
+
36
+ - **Seamless Integration**: Mops integrates with Selenium, Appium, and Playwright, allowing you to use the best-suited engine for your specific testing needs.
37
+ - **Unified API**: A single, easy-to-use API that abstracts away the differences between Selenium, Appium, and Playwright, making your test scripts more readable and maintainable.
38
+ - **Engine Switching**: Switch between Selenium, Appium, and Playwright within the same test case, enabling cross-platform and cross-browser testing with minimal effort.
39
+ - **Visual Regression Testing**: Perform visual regression tests using the integrated visual regression tool, available across all supported frameworks. This ensures your UI remains consistent across different browsers and devices.
40
+ - **Advanced Features**: Leverage the advanced features of each framework, such as Playwright's mocks and Appium's real mobile devices support, all while using the same testing framework.
41
+ - **Extensibility**: Extend the framework with custom functionality tailored to your project's specific requirements.
42
+ - **Automatic Locator Type Definition**: The locator type will be automatically determined based on the provided locator string or `Locator` object.
43
+
44
+
45
+ ## Installation and usage
46
+ For information on installation and usage, please refer to our **[ReadTheDocs documentation](https://mops.readthedocs.io)**. Check it out for more details.
47
+
48
+
49
+ ## Contributing
50
+
51
+ Mops is an open-source project, and we welcome contributions from the community. If you'd like to contribute, please open an pull request from your fork
52
+
53
+ ## License
54
+
55
+ Mops is licensed under the Apache License. See the [LICENSE](https://github.com/CustomEnv/mops/blob/master/LICENSE) file for more details.
56
+
57
+ ## Support
58
+
59
+ If you encounter any issues or have questions, please feel free to reach out via our [GitHub Issues](https://github.com/CustomEnv/mops/issues) page.
60
+
61
+ Thank you for choosing Mops for your automation needs!
@@ -0,0 +1,2 @@
1
+ __version__ = '0.0.1a2'
2
+ __project_name__ = 'mops'
@@ -0,0 +1,133 @@
1
+ from typing import Any
2
+
3
+
4
+ class DriverWrapperException(Exception):
5
+ """
6
+ Base driver wrapper exceptions
7
+ """
8
+
9
+ def __init__(
10
+ self,
11
+ msg: str,
12
+ actual: Any = None,
13
+ expected: Any = None,
14
+ timeout: Any = None,
15
+ info: Any = None
16
+ ):
17
+ self._msg = ''
18
+ self._original_msg = msg
19
+ self._timeout = timeout
20
+ self._actual = actual
21
+ self._expected = expected
22
+ self._info = info
23
+ self.__suppress_context__ = True
24
+
25
+ def __str__(self) -> str:
26
+ return f"\nMessage: {self.msg}"
27
+
28
+ @property
29
+ def msg(self):
30
+ self._msg = f'{self._original_msg} '
31
+
32
+ if self._timeout:
33
+ self._msg += f'after {self._timeout} seconds. '
34
+ if self._expected is not None:
35
+ self._msg += f'Actual: {self.wrap_by_quotes(self._actual)}; ' \
36
+ f'Expected: {self.wrap_by_quotes(self._expected)}. '
37
+ if self._info:
38
+ self._msg += f'{self._info.get_element_info()}. '
39
+
40
+ return self._msg.rstrip()
41
+
42
+ def wrap_by_quotes(self, data):
43
+ if data is None:
44
+ data = ""
45
+
46
+ if isinstance(data, str):
47
+ return f'"{data}"'
48
+
49
+ return data
50
+
51
+
52
+ class UnexpectedElementsCountException(DriverWrapperException):
53
+ """
54
+ Thrown when elements count isn't equal to expected
55
+ """
56
+ pass
57
+
58
+
59
+ class UnexpectedElementSizeException(DriverWrapperException):
60
+ """
61
+ Thrown when element size isn't equal to expected
62
+ """
63
+ pass
64
+
65
+
66
+ class UnexpectedValueException(DriverWrapperException):
67
+ """
68
+ Thrown when element contains incorrect value
69
+ """
70
+ pass
71
+
72
+
73
+ class UnexpectedTextException(DriverWrapperException):
74
+ """
75
+ Thrown when element contains incorrect text
76
+ """
77
+ pass
78
+
79
+
80
+ class TimeoutException(DriverWrapperException):
81
+ """
82
+ Thrown when timeout exceeded
83
+ """
84
+ pass
85
+
86
+
87
+ class InvalidSelectorException(DriverWrapperException):
88
+ """
89
+ Thrown when element have invalid selector
90
+ """
91
+ pass
92
+
93
+
94
+ class NoSuchElementException(DriverWrapperException):
95
+ """
96
+ Thrown when element could not be found
97
+ """
98
+ pass
99
+
100
+
101
+ class NoSuchParentException(DriverWrapperException):
102
+ """
103
+ Thrown when parent could not be found
104
+ """
105
+ pass
106
+
107
+
108
+ class ElementNotInteractableException(DriverWrapperException):
109
+ """
110
+ Thrown when element found and enabled but not interactable
111
+ """
112
+ pass
113
+
114
+
115
+ class UnsuitableArgumentsException(DriverWrapperException):
116
+ """
117
+ Thrown when object initialised with unsuitable arguments
118
+ """
119
+ pass
120
+
121
+
122
+ class NotInitializedException(DriverWrapperException):
123
+ """
124
+ Thrown when getting access to not initialized object
125
+ """
126
+ pass
127
+
128
+
129
+ class InvalidLocatorException(DriverWrapperException):
130
+ """
131
+ Thrown when locator is invalid
132
+ """
133
+ pass
@@ -0,0 +1,216 @@
1
+ get_inner_height_js = 'return window.innerHeight'
2
+ get_inner_width_js = 'return window.innerWidth'
3
+ js_click = 'arguments[0].click();'
4
+
5
+ get_element_position_on_screen_js = """
6
+ function getPositionOnScreen(elem) {
7
+ let box = elem.getBoundingClientRect();
8
+ var y;
9
+ var x;
10
+ y = Math.round(box.top)
11
+ x = Math.round(box.left)
12
+ return {
13
+ x: x,
14
+ y: y
15
+ };
16
+ };
17
+ return getPositionOnScreen(arguments[0])
18
+ """
19
+
20
+ get_element_size_js = """
21
+ function getSize(elem) {
22
+ let box = elem.getBoundingClientRect();
23
+ var width;
24
+ var height;
25
+ width = Math.round(box.width)
26
+ height = Math.round(box.height)
27
+ return {
28
+ width: width,
29
+ height: height
30
+ };
31
+ };
32
+ return getSize(arguments[0])
33
+ """
34
+
35
+ delete_element_over_js = """
36
+ const elements = document.getElementsByClassName("driver-wrapper-visual-comparison-support-element");
37
+
38
+ for (var i=0, max=elements.length; i < max; i++) {
39
+ elements[0].remove()
40
+ };
41
+ """
42
+
43
+ add_element_over_js = """
44
+ function appendElement(given_obj) {
45
+ given_obj = given_obj.getBoundingClientRect();
46
+ driver_wrapper_obj = document.createElement("div");
47
+
48
+ driver_wrapper_obj.style.zIndex=9999999;
49
+ driver_wrapper_obj.setAttribute("class","driver-wrapper-comparison-support-element");
50
+
51
+ driver_wrapper_obj.style.position = "absolute";
52
+ driver_wrapper_obj.style.backgroundColor = "#000";
53
+
54
+ driver_wrapper_obj.style.width = given_obj.width + "px";
55
+ driver_wrapper_obj.style.height = given_obj.height + "px";
56
+ driver_wrapper_obj.style.top = (given_obj.top + window.scrollY) + "px";
57
+ driver_wrapper_obj.style.left = (given_obj.left + window.scrollX) + "px";
58
+
59
+ document.body.appendChild(driver_wrapper_obj);
60
+ };
61
+
62
+ return appendElement(arguments[0]);
63
+ """
64
+
65
+
66
+ add_driver_index_comment_js = """
67
+ function addComment(driver_index) {
68
+ comment = document.createComment(" " + driver_index + " ");
69
+ document.body.appendChild(comment);
70
+ };
71
+
72
+ addComment(arguments[0])
73
+ """
74
+
75
+ find_comments_js = """
76
+ function filterNone() {
77
+ return NodeFilter.FILTER_ACCEPT;
78
+ }
79
+
80
+ function getAllComments(rootElem) {
81
+ var comments = [];
82
+ // Fourth argument, which is actually obsolete according to the DOM4 standard, is required in IE 11
83
+ var iterator = document.createNodeIterator(rootElem, NodeFilter.SHOW_COMMENT, filterNone, false);
84
+ var curNode;
85
+ while (curNode = iterator.nextNode()) {
86
+ comments.push(curNode.nodeValue);
87
+ }
88
+ return comments;
89
+ }
90
+
91
+ return getAllComments(document.body);
92
+ """
93
+
94
+ trigger_react = """
95
+ function reactTriggerChange(node) {
96
+ var supportedInputTypes = {
97
+ color: true,
98
+ date: true,
99
+ datetime: true,
100
+ 'datetime-local': true,
101
+ email: true,
102
+ month: true,
103
+ number: true,
104
+ password: true,
105
+ range: true,
106
+ search: true,
107
+ tel: true,
108
+ text: true,
109
+ time: true,
110
+ url: true,
111
+ week: true
112
+ };
113
+ var nodeName = node.nodeName.toLowerCase();
114
+ var type = node.type;
115
+ var event;
116
+ var descriptor;
117
+ var initialValue;
118
+ var initialChecked;
119
+ var initialCheckedRadio;
120
+ function deletePropertySafe(elem, prop) {
121
+ var desc = Object.getOwnPropertyDescriptor(elem, prop);
122
+ if (desc && desc.configurable) {
123
+ delete elem[prop];
124
+ }
125
+ }
126
+ function changeRangeValue(range) {
127
+ var initMin = range.min;
128
+ var initMax = range.max;
129
+ var initStep = range.step;
130
+ var initVal = Number(range.value);
131
+ range.min = initVal;
132
+ range.max = initVal + 1;
133
+ range.step = 1;
134
+ range.value = initVal + 1;
135
+ deletePropertySafe(range, 'value');
136
+ range.min = initMin;
137
+ range.max = initMax;
138
+ range.step = initStep;
139
+ range.value = initVal;
140
+ }
141
+ function getCheckedRadio(radio) {
142
+ var name = radio.name;
143
+ var radios;
144
+ var i;
145
+ if (name) {
146
+ radios = document.querySelectorAll('input[type="radio"][name="' + name + '"]');
147
+ for (i = 0; i < radios.length; i += 1) {
148
+ if (radios[i].checked) {
149
+ return radios[i] !== radio ? radios[i] : null;
150
+ }
151
+ }
152
+ }
153
+ return null;
154
+ }
155
+ function preventChecking(e) {
156
+ e.preventDefault();
157
+ if (!initialChecked) {
158
+ e.target.checked = false;
159
+ }
160
+ if (initialCheckedRadio) {
161
+ initialCheckedRadio.checked = true;
162
+ }
163
+ }
164
+ if (nodeName === 'select' ||
165
+ (nodeName === 'input' && type === 'file')) {
166
+ event = document.createEvent('HTMLEvents');
167
+ event.initEvent('change', true, false);
168
+ node.dispatchEvent(event);
169
+ } else if ((nodeName === 'input' && supportedInputTypes[type]) ||
170
+ nodeName === 'textarea') {
171
+ descriptor = Object.getOwnPropertyDescriptor(node, 'value');
172
+ event = document.createEvent('UIEvents');
173
+ event.initEvent('focus', false, false);
174
+ node.dispatchEvent(event);
175
+ if (type === 'range') {
176
+ changeRangeValue(node);
177
+ } else {
178
+ initialValue = node.value;
179
+ node.value = initialValue + '#';
180
+ deletePropertySafe(node, 'value');
181
+ node.value = initialValue;
182
+ }
183
+ event = document.createEvent('HTMLEvents');
184
+ event.initEvent('propertychange', false, false);
185
+ event.propertyName = 'value';
186
+ node.dispatchEvent(event);
187
+ event = document.createEvent('HTMLEvents');
188
+ event.initEvent('input', true, false);
189
+ node.dispatchEvent(event);
190
+ if (descriptor) {
191
+ Object.defineProperty(node, 'value', descriptor);
192
+ }
193
+ } else if (nodeName === 'input' && type === 'checkbox') {
194
+ node.checked = !node.checked;
195
+ event = document.createEvent('MouseEvents');
196
+ event.initEvent('click', true, true);
197
+ node.dispatchEvent(event);
198
+ } else if (nodeName === 'input' && type === 'radio') {
199
+ initialChecked = node.checked;
200
+ initialCheckedRadio = getCheckedRadio(node);
201
+ descriptor = Object.getOwnPropertyDescriptor(node, 'checked');
202
+ node.checked = !initialChecked;
203
+ deletePropertySafe(node, 'checked');
204
+ node.checked = initialChecked;
205
+ node.addEventListener('click', preventChecking, true);
206
+ event = document.createEvent('MouseEvents');
207
+ event.initEvent('click', true, true);
208
+ node.dispatchEvent(event);
209
+ node.removeEventListener('click', preventChecking, true);
210
+ if (descriptor) {
211
+ Object.defineProperty(node, 'checked', descriptor);
212
+ }
213
+ }
214
+ };
215
+ reactTriggerChange(arguments[0]);
216
+ """
@@ -0,0 +1,92 @@
1
+ from selenium.webdriver import Keys as SeleniumSourceKeys
2
+
3
+ from mops.base.driver_wrapper import DriverWrapper
4
+
5
+
6
+ class SeleniumKeys(SeleniumSourceKeys):
7
+ pass
8
+
9
+
10
+ class PlaywrightKeys:
11
+
12
+ # NULL = '\ue000'
13
+ # CANCEL = '\ue001' # ^break
14
+ # HELP = '\ue002'
15
+ BACKSPACE = 'Backspace'
16
+ BACK_SPACE = BACKSPACE
17
+ TAB = 'Tab'
18
+ # CLEAR = '\ue005'
19
+ # RETURN = '\ue006'
20
+ ENTER = 'Enter'
21
+ SHIFT = 'Shift'
22
+ LEFT_SHIFT = SHIFT
23
+ CONTROL = 'Control'
24
+ LEFT_CONTROL = CONTROL
25
+ ALT = 'Alt'
26
+ LEFT_ALT = ALT
27
+ # PAUSE = '\ue00b'
28
+ ESCAPE = 'Escape'
29
+ # SPACE = '\ue00d'
30
+ PAGE_UP = 'PageUp'
31
+ PAGE_DOWN = 'PageDown'
32
+ END = 'End'
33
+ HOME = 'Home'
34
+ LEFT = 'ArrowLeft'
35
+ ARROW_LEFT = LEFT
36
+ UP = 'ArrowUp'
37
+ ARROW_UP = UP
38
+ RIGHT = 'ArrowRight'
39
+ ARROW_RIGHT = RIGHT
40
+ DOWN = 'ArrowDown'
41
+ ARROW_DOWN = DOWN
42
+ INSERT = 'Insert'
43
+ DELETE = 'Delete'
44
+ # SEMICOLON = '\ue018'
45
+ EQUALS = 'Equal'
46
+
47
+ NUMPAD0 = 'Digit0' # number pad keys
48
+ NUMPAD1 = 'Digit1'
49
+ NUMPAD2 = 'Digit2'
50
+ NUMPAD3 = 'Digit3'
51
+ NUMPAD4 = 'Digit4'
52
+ NUMPAD5 = 'Digit5'
53
+ NUMPAD6 = 'Digit6'
54
+ NUMPAD7 = 'Digit7'
55
+ NUMPAD8 = 'Digit8'
56
+ NUMPAD9 = 'Digit9'
57
+ # MULTIPLY = '\ue024'
58
+ # ADD = '\ue025'
59
+ # SEPARATOR = '\ue026'
60
+ # SUBTRACT = '\ue027'
61
+ # DECIMAL = '\ue028'
62
+ # DIVIDE = '\ue029'
63
+
64
+ F1 = 'F1'
65
+ F2 = 'F2'
66
+ F3 = 'F3'
67
+ F4 = 'F4'
68
+ F5 = 'F5'
69
+ F6 = 'F6'
70
+ F7 = 'F7'
71
+ F8 = 'F8'
72
+ F9 = 'F9'
73
+ F10 = 'F10'
74
+ F11 = 'F11'
75
+ F12 = 'F12'
76
+
77
+ META = 'Meta'
78
+ # COMMAND = '\ue03d'
79
+ # ZENKAKU_HANKAKU = '\ue040'
80
+
81
+
82
+ class Interceptor(type):
83
+
84
+ def __getattribute__(self, item):
85
+ if DriverWrapper.is_selenium:
86
+ return getattr(SeleniumKeys, item)
87
+ else:
88
+ return getattr(PlaywrightKeys, item, NotImplementedError(f'Key is not added to Mops framework'))
89
+
90
+
91
+ class KeyboardKeys(SeleniumKeys, PlaywrightKeys, metaclass=Interceptor):
92
+ pass