Skip to content

Commit 78926d2

Browse files
ki4070madependabot-preview[bot]KazuCocoamykola-mokhnachiamnrupesh
authored
Rebase python3 branch with master (#522)
* Update pytest-cov requirement from ~=2.6 to ~=2.8 (#489) Updates the requirements on [pytest-cov](https://github.com/pytest-dev/pytest-cov) to permit the latest version. - [Release notes](https://github.com/pytest-dev/pytest-cov/releases) - [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst) - [Commits](pytest-dev/pytest-cov@v2.6.0...v2.8.1) Signed-off-by: dependabot-preview[bot] <support@dependabot.com> * Update autopep8 requirement from ~=1.4 to ~=1.5 (#490) Updates the requirements on [autopep8](https://github.com/hhatto/autopep8) to permit the latest version. - [Release notes](https://github.com/hhatto/autopep8/releases) - [Commits](hhatto/autopep8@v1.4...v1.5) Signed-off-by: dependabot-preview[bot] <support@dependabot.com> * Update tox-travis requirement from ~=0.11 to ~=0.12 (#491) Updates the requirements on [tox-travis](https://github.com/tox-dev/tox-travis) to permit the latest version. - [Release notes](https://github.com/tox-dev/tox-travis/releases) - [Changelog](https://github.com/tox-dev/tox-travis/blob/master/HISTORY.rst) - [Commits](tox-dev/tox-travis@0.11...0.12) Signed-off-by: dependabot-preview[bot] <support@dependabot.com> * Update tox requirement from ~=3.6 to ~=3.14 (#494) Updates the requirements on [tox](https://github.com/tox-dev/tox) to permit the latest version. - [Release notes](https://github.com/tox-dev/tox/releases) - [Changelog](https://github.com/tox-dev/tox/blob/master/docs/changelog.rst) - [Commits](tox-dev/tox@3.6.0...3.14.3) Signed-off-by: dependabot-preview[bot] <support@dependabot.com> * chore: Fix find_by_images_tests.py (#495) * chore: Fix find_by_images_tests.py * Add installation opencv4nodejs * Fix typo * Add taking screen record to find_by_image_test * Fix errors on the emulator * Remove unused imports * feat: Add viewmatcher (#480) * Add android view matcher as strategy locator * Add docstring * Add functional test * Remove find_elements_by_android_data_matcher * Fix docstring * tweak docstring * Bump 0.50 * Update changelog for 0.50 * Fix flaky functional tests (#473) * Run all tests * Fix apk file path * Skip find_element_by_image test cases * Skip context switching test * Skip multi tap test on CI * Change strategy for waiting element * Add functions for same steps * Restore unexpected changes * Fix touch_action_tests * Fix * Fix Fix test_driver_swipe * fix * Create _move_to_[target_view] * [test_driver_swipe] Add wait * feat: Add idempotency key header to create session requests (#514) * feat: Override send_keys without file upload function (#515) * add send_keys_direct * override send_keys * tune * add unittest instead of functional test * tweak syntax * Bump 0.51 * Update changelog for 0.51 * test: Fix test_clear flaky functional test (#519) * test: Add unit test for set_value (setImmediateValue) (#518) * chore: Fix int - str comparison error in ios desired capabilities (#517) if number >= PytestXdistWorker.COUNT: TypeError: '>=' not supported between instances of 'int' and 'str' 2. Updated test case path and iPhone model in Readme file * fix: Handling of dictionary-values in WebElement.get_attribute() (#521) * Bump 0.52 * Update changelog for 0.52 * Fix mypy error * tweak * Add wait to test * Skip tap_twice test * review comments * Remove unnecessary import Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> Co-authored-by: Kazuaki Matsuo <fly.49.89.over@gmail.com> Co-authored-by: Mykola Mokhnach <mokhnach@gmail.com> Co-authored-by: Nrupesh Patel <nrupesh.patel2912@gmail.com> Co-authored-by: Venkatesh <venkatesh@poshmark.com> Co-authored-by: Hannes Hauer <hanneshauer@beeware.at>
1 parent 4bc8677 commit 78926d2

21 files changed

+495
-124
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,17 @@ MANIFEST
1515
build
1616
dist
1717

18+
# Cache
1819
.cache
1920
__pycache__
2021
.idea
2122
.pytest_cache
23+
.mypy_cache
2224

2325
# Virtual Environments
2426
venv*
2527
.tox
2628

2729
Pipfile.lock
30+
31+
.coverage

CHANGELOG.rst

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,171 @@ Changelog
22
=========
33

44

5+
v0.52 (2020-04-23)
6+
------------------
7+
8+
Fix
9+
~~~
10+
- Handling of dictionary-values in WebElement.get_attribute() (#521)
11+
[Hannes Hauer]
12+
13+
Other
14+
~~~~~
15+
- Bump 0.52. [Kazuaki Matsuo]
16+
- Chore: Fix int - str comparison error in ios desired capabilities
17+
(#517) [Venkatesh]
18+
19+
if number >= PytestXdistWorker.COUNT:
20+
- Test: Add unit test for set_value (setImmediateValue) (#518) [Nrupesh
21+
Patel]
22+
- Test: Fix test_clear flaky functional test (#519) [Nrupesh Patel]
23+
- Update changelog for 0.51. [Kazuaki Matsuo]
24+
25+
26+
v0.51 (2020-04-12)
27+
------------------
28+
- Bump 0.51. [Kazuaki Matsuo]
29+
- Feat: Override send_keys without file upload function (#515) [Kazuaki
30+
Matsuo]
31+
32+
* add send_keys_direct
33+
34+
* override send_keys
35+
36+
* tune
37+
38+
* add unittest instead of functional test
39+
40+
* tweak syntax
41+
- Feat: Add idempotency key header to create session requests (#514)
42+
[Mykola Mokhnach]
43+
- Fix flaky functional tests (#473) [Mori Atsushi]
44+
45+
* Run all tests
46+
47+
* Fix apk file path
48+
49+
* Skip find_element_by_image test cases
50+
51+
* Skip context switching test
52+
53+
* Skip multi tap test on CI
54+
55+
* Change strategy for waiting element
56+
57+
* Add functions for same steps
58+
59+
* Restore unexpected changes
60+
61+
* Fix touch_action_tests
62+
63+
* Fix
64+
65+
* Fix
66+
Fix test_driver_swipe
67+
68+
* fix
69+
70+
* Create _move_to_[target_view]
71+
72+
* [test_driver_swipe] Add wait
73+
- Update changelog for 0.50. [Kazuaki Matsuo]
74+
75+
76+
v0.50 (2020-02-10)
77+
------------------
78+
- Bump 0.50. [Kazuaki Matsuo]
79+
- Feat: Add viewmatcher (#480) [Mori Atsushi]
80+
81+
* Add android view matcher as strategy locator
82+
83+
* Add docstring
84+
85+
* Add functional test
86+
87+
* Remove find_elements_by_android_data_matcher
88+
89+
* Fix docstring
90+
91+
* tweak docstring
92+
- Chore: Fix find_by_images_tests.py (#495) [Mori Atsushi]
93+
94+
* chore: Fix find_by_images_tests.py
95+
96+
* Add installation opencv4nodejs
97+
98+
* Fix typo
99+
100+
* Add taking screen record to find_by_image_test
101+
102+
* Fix errors on the emulator
103+
104+
* Remove unused imports
105+
- Update tox requirement from ~=3.6 to ~=3.14 (#494) [dependabot-
106+
preview[bot]]
107+
108+
Updates the requirements on [tox](https://github.com/tox-dev/tox) to permit the latest version.
109+
- [Release notes](https://github.com/tox-dev/tox/releases)
110+
- [Changelog](https://github.com/tox-dev/tox/blob/master/docs/changelog.rst)
111+
- [Commits](https://github.com/tox-dev/tox/compare/3.6.0...3.14.3)
112+
- Update tox-travis requirement from ~=0.11 to ~=0.12 (#491)
113+
[dependabot-preview[bot]]
114+
115+
Updates the requirements on [tox-travis](https://github.com/tox-dev/tox-travis) to permit the latest version.
116+
- [Release notes](https://github.com/tox-dev/tox-travis/releases)
117+
- [Changelog](https://github.com/tox-dev/tox-travis/blob/master/HISTORY.rst)
118+
- [Commits](https://github.com/tox-dev/tox-travis/compare/0.11...0.12)
119+
- Update autopep8 requirement from ~=1.4 to ~=1.5 (#490) [dependabot-
120+
preview[bot]]
121+
122+
Updates the requirements on [autopep8](https://github.com/hhatto/autopep8) to permit the latest version.
123+
- [Release notes](https://github.com/hhatto/autopep8/releases)
124+
- [Commits](https://github.com/hhatto/autopep8/compare/v1.4...v1.5)
125+
- Update pytest-cov requirement from ~=2.6 to ~=2.8 (#489) [dependabot-
126+
preview[bot]]
127+
128+
Updates the requirements on [pytest-cov](https://github.com/pytest-dev/pytest-cov) to permit the latest version.
129+
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
130+
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
131+
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v2.6.0...v2.8.1)
132+
- Chore: add try/catch in release script (#479) [Kazuaki Matsuo]
133+
134+
* Add m and try/catch in pushing
135+
136+
* fix error message
137+
138+
* remove -m since it does not work for this usage
139+
- [CI] Run with iOS 13.3 and Xcode 11.3 (#477) [Mori Atsushi]
140+
141+
* [CI] Run with iOS 13.3 and Xcode 11.3
142+
143+
* Skip the case which has problem on Xcode 11.3
144+
145+
* Update FyndByIOClassChainTests along to iOS13
146+
147+
* Update FyndByElementWebelementTests along to iOS13
148+
149+
* Update KeyboardTests along to iOS13
150+
151+
* Update webdriver_tests along to iOS13
152+
153+
* Run test_find_element_by_isvisible with simpleIsVisibleCheck caps
154+
155+
* Run test_hide_keyboard_no_key_name
156+
157+
* Remove unused codes
158+
159+
* [Readme] py.test -> pytest
160+
- Ci: Take screen record as evidence (#481) [Mori Atsushi]
161+
162+
* Take screen record for android
163+
164+
* Take screen record for iOS
165+
166+
* Save screen record for iOS
167+
- Update changelog for 0.49. [Kazuaki Matsuo]
168+
169+
5170
v0.49 (2019-12-24)
6171
------------------
7172
- Bump 0.49. [Kazuaki Matsuo]

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,18 @@ $ pytest -n 2 test/unit
9696
### Functional
9797
9898
```
99-
$ pytest test/functional/ios/find_by_ios_class_chain_tests.py
99+
$ pytest test/functional/ios/search_context/find_by_ios_class_chain_tests.py
100100
```
101101
102102
### In parallel for iOS
103-
1. Create simulators named 'iPhone 6s - 8100' and 'iPhone 6s - 8101'
103+
1. Create simulators named 'iPhone 8 - 8100' and 'iPhone 8 - 8101'
104104
2. Install test libraries via pip
105105
```
106106
$ pip install pytest pytest-xdist
107107
```
108108
3. Run tests
109109
```
110-
$ pytest -n 2 test/functional/ios/find_by_ios_class_chain_tests.py
110+
$ pytest -n 2 test/functional/ios/search_context/find_by_ios_class_chain_tests.py
111111
```
112112
113113
# Release

appium/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version = '0.49'
1+
version = '0.52'

appium/webdriver/appium_connection.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,26 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from typing import Any, Dict
15+
import uuid
16+
from typing import TYPE_CHECKING, Any, Dict
1617

1718
from selenium.webdriver.remote.remote_connection import RemoteConnection
1819

1920
from appium.common.helper import library_version
2021

22+
if TYPE_CHECKING:
23+
from urllib.parse import ParseResult
24+
2125

2226
class AppiumConnection(RemoteConnection):
2327

2428
@classmethod
25-
def get_remote_connection_headers(cls, parsed_url: str, keep_alive: bool = True) -> Dict[str, Any]:
29+
def get_remote_connection_headers(cls, parsed_url: 'ParseResult', keep_alive: bool = True) -> Dict[str, Any]:
2630
"""Override get_remote_connection_headers in RemoteConnection"""
2731
headers = RemoteConnection.get_remote_connection_headers(parsed_url, keep_alive=keep_alive)
2832
headers['User-Agent'] = 'appium/python {} ({})'.format(library_version(), headers['User-Agent'])
33+
if parsed_url.path.endswith('/session'):
34+
# https://github.com/appium/appium-base-driver/pull/400
35+
headers['X-Idempotency-Key'] = str(uuid.uuid4())
2936

3037
return headers

appium/webdriver/appium_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ def start(self, **kwargs: Any) -> sp.Popen:
170170
if not self.is_running or (timeout_ms > 0 and not poll_url(host, port, STATUS_URL, timeout_ms)):
171171
error_msg = f'Appium has failed to start on {host}:{port} within {timeout_ms}ms timeout'
172172
if error_msg is not None:
173-
if stderr == sp.PIPE:
173+
if stderr == sp.PIPE and self._process.stderr is not None:
174174
err_output = self._process.stderr.read()
175175
if err_output:
176176
error_msg += f'\nOriginal error: {str(err_output)}'

appium/webdriver/common/mobileby.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class MobileBy(By):
2222
ANDROID_UIAUTOMATOR = '-android uiautomator'
2323
ANDROID_VIEWTAG = '-android viewtag'
2424
ANDROID_DATA_MATCHER = '-android datamatcher'
25+
ANDROID_VIEW_MATCHER = '-android viewmatcher'
2526
WINDOWS_UI_AUTOMATION = '-windows uiautomation'
2627
ACCESSIBILITY_ID = 'accessibility id'
2728
IMAGE = '-image'

appium/webdriver/extensions/search_context/android.py

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# pylint: disable=abstract-method
1616

1717
import json
18-
from typing import TYPE_CHECKING, List, Optional
18+
from typing import TYPE_CHECKING, Any, List, Optional
1919

2020
from appium.webdriver.common.mobileby import MobileBy
2121

@@ -28,8 +28,42 @@
2828
class AndroidSearchContext(BaseSearchContext):
2929
"""Define search context for Android"""
3030

31+
def find_element_by_android_view_matcher(
32+
self, name: Optional[str] = None, args: Optional[Any] = None, className: Optional[str] = None) -> 'WebElement':
33+
"""Finds element by [onView](https://developer.android.com/training/testing/espresso/basics) in Android
34+
35+
It works with [Espresso Driver](https://github.com/appium/appium-espresso-driver).
36+
37+
Args:
38+
name (:obj:`str`, optional): The name of a method to invoke.
39+
The method must return a Hamcrest
40+
[Matcher](http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matcher.html)
41+
args (:obj:`Any`, optional): The args provided to the method
42+
className (:obj:`str`, optional): The class name that the method is part of (defaults to `org.hamcrest.Matchers`).
43+
Can be fully qualified by having the androidx.test.espresso.matcher. prefix.
44+
If the prefix is not provided then it is going to be added implicitly.
45+
(e.g.: `class=CursorMatchers` fully qualified is `class=androidx.test.espresso.matcher.CursorMatchers`
46+
47+
Returns:
48+
`appium.webdriver.webelement.WebElement`: The found element
49+
50+
Raises:
51+
TypeError - Raises a TypeError if the arguments are not validated for JSON format
52+
53+
Usage:
54+
driver.find_element_by_android_view_matcher(name='withText', args=['Accessibility'], className='ViewMatchers')
55+
56+
# To enable auto completion in PyCharm(IDE)
57+
:rtype: `appium.webdriver.webelement.WebElement`
58+
"""
59+
60+
return self.find_element(
61+
by=MobileBy.ANDROID_VIEW_MATCHER,
62+
value=self._build_data_matcher(name=name, args=args, className=className)
63+
)
64+
3165
def find_element_by_android_data_matcher(
32-
self, name: Optional[str] = None, args: Optional[str] = None, className: Optional[str] = None) -> 'WebElement':
66+
self, name: Optional[str] = None, args: Optional[Any] = None, className: Optional[str] = None) -> 'WebElement':
3367
"""Finds element by [onData](https://medium.com/androiddevelopers/adapterviews-and-espresso-f4172aa853cf) in Android
3468
3569
It works with [Espresso Driver](https://github.com/appium/appium-espresso-driver).
@@ -38,7 +72,7 @@ def find_element_by_android_data_matcher(
3872
name (:obj:`str`, optional): The name of a method to invoke.
3973
The method must return a Hamcrest
4074
[Matcher](http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matcher.html)
41-
args (:obj:`str`, optional): The args provided to the method
75+
args (:obj:`Any`, optional): The args provided to the method
4276
className (:obj:`str`, optional): The class name that the method is part of (defaults to `org.hamcrest.Matchers`).
4377
Can be fully qualified, or simple, and simple defaults to `androidx.test.espresso.matcher` package
4478
(e.g.: `class=CursorMatchers` fully qualified is `class=androidx.test.espresso.matcher.CursorMatchers`
@@ -62,15 +96,15 @@ def find_element_by_android_data_matcher(
6296
)
6397

6498
def find_elements_by_android_data_matcher(
65-
self, name: Optional[str] = None, args: Optional[str] = None, className: Optional[str] = None) -> List['WebElement']:
99+
self, name: Optional[str] = None, args: Optional[Any] = None, className: Optional[str] = None) -> List['WebElement']:
66100
"""Finds elements by [onData](https://medium.com/androiddevelopers/adapterviews-and-espresso-f4172aa853cf) in Android
67101
It works with [Espresso Driver](https://github.com/appium/appium-espresso-driver).
68102
69103
Args:
70104
name (:obj:`str`, optional): The name of a method to invoke.
71105
The method must return a Hamcrest
72106
[Matcher](http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matcher.html)
73-
args (:obj:`str`, optional): The args provided to the method
107+
args (:obj:`Any`, optional): The args provided to the method
74108
className (:obj:`str`, optional): The class name that the method is part of (defaults to `org.hamcrest.Matchers`).
75109
Can be fully qualified, or simple, and simple defaults to `androidx.test.espresso.matcher` package
76110
(e.g.: `class=CursorMatchers` fully qualified is `class=androidx.test.espresso.matcher.CursorMatchers`
@@ -89,7 +123,7 @@ def find_elements_by_android_data_matcher(
89123
value=self._build_data_matcher(name=name, args=args, className=className)
90124
)
91125

92-
def _build_data_matcher(self, name: Optional[str] = None, args: Optional[str]
126+
def _build_data_matcher(self, name: Optional[str] = None, args: Optional[Any]
93127
= None, className: Optional[str] = None) -> str:
94128
result = {}
95129

appium/webdriver/webelement.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from typing import Dict, List, Optional, TypeVar, Union
1616

1717
from selenium.webdriver.common.by import By
18+
from selenium.webdriver.common.utils import keys_to_typing
1819
from selenium.webdriver.remote.command import Command as RemoteCommand
1920

2021
from .extensions.search_context import AppiumWebElementSearchContext
@@ -24,7 +25,7 @@
2425

2526

2627
class WebElement(AppiumWebElementSearchContext):
27-
def get_attribute(self, name: str) -> Optional[str]:
28+
def get_attribute(self, name: str) -> Optional[Union[str, Dict]]:
2829
"""Gets the given attribute or property of the element.
2930
3031
Override for Appium
@@ -56,6 +57,9 @@ def get_attribute(self, name: str) -> Optional[str]:
5657
if attributeValue is None:
5758
return None
5859

60+
if isinstance(attributeValue, dict):
61+
return attributeValue
62+
5963
# Convert to str along to the spec
6064
if not isinstance(attributeValue, str):
6165
attributeValue = str(attributeValue)
@@ -205,3 +209,18 @@ def set_value(self, value: str) -> T:
205209
}
206210
self._execute(Command.SET_IMMEDIATE_VALUE, data)
207211
return self
212+
213+
# Override
214+
def send_keys(self, *value: str) -> T:
215+
"""Simulates typing into the element.
216+
217+
Args:
218+
value (str): A string for typing.
219+
220+
Returns:
221+
`appium.webdriver.webelement.WebElement`
222+
"""
223+
keys = keys_to_typing(value)
224+
self._execute(RemoteCommand.SEND_KEYS_TO_ELEMENT,
225+
{'text': ''.join(keys), 'value': keys})
226+
return self

0 commit comments

Comments
 (0)