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 +96 -0
- mops-0.0.1a2/README.md +61 -0
- mops-0.0.1a2/mops/__init__.py +2 -0
- mops-0.0.1a2/mops/exceptions.py +133 -0
- mops-0.0.1a2/mops/js_scripts.py +216 -0
- mops-0.0.1a2/mops/keyboard_keys.py +92 -0
- mops-0.0.1a2/mops/shared_utils.py +102 -0
- mops-0.0.1a2/mops/visual_comparison.py +461 -0
- mops-0.0.1a2/mops.egg-info/PKG-INFO +96 -0
- mops-0.0.1a2/mops.egg-info/SOURCES.txt +13 -0
- mops-0.0.1a2/mops.egg-info/dependency_links.txt +1 -0
- mops-0.0.1a2/mops.egg-info/requires.txt +19 -0
- mops-0.0.1a2/mops.egg-info/top_level.txt +1 -0
- mops-0.0.1a2/pyproject.toml +82 -0
- mops-0.0.1a2/setup.cfg +4 -0
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,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
|