Skip to content

Rebase python3 branch with master #522

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Apr 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6e1a2a7
Update pytest-cov requirement from ~=2.6 to ~=2.8 (#489)
dependabot-preview[bot] Jan 26, 2020
53dc75f
Update autopep8 requirement from ~=1.4 to ~=1.5 (#490)
dependabot-preview[bot] Jan 26, 2020
3359a44
Update tox-travis requirement from ~=0.11 to ~=0.12 (#491)
dependabot-preview[bot] Jan 26, 2020
4d269f8
Update tox requirement from ~=3.6 to ~=3.14 (#494)
dependabot-preview[bot] Jan 27, 2020
b95776d
chore: Fix find_by_images_tests.py (#495)
ki4070ma Jan 30, 2020
f2bf259
feat: Add viewmatcher (#480)
ki4070ma Feb 9, 2020
864b045
Bump 0.50
KazuCocoa Feb 10, 2020
f14291b
Update changelog for 0.50
KazuCocoa Feb 10, 2020
446b8c4
Fix flaky functional tests (#473)
ki4070ma Feb 10, 2020
4641b45
feat: Add idempotency key header to create session requests (#514)
mykola-mokhnach Apr 11, 2020
34427a1
feat: Override send_keys without file upload function (#515)
KazuCocoa Apr 12, 2020
5a545d7
Bump 0.51
KazuCocoa Apr 12, 2020
2141dbd
Update changelog for 0.51
KazuCocoa Apr 12, 2020
9bdf1f7
test: Fix test_clear flaky functional test (#519)
iamnrupesh Apr 15, 2020
ba64adf
test: Add unit test for set_value (setImmediateValue) (#518)
iamnrupesh Apr 15, 2020
9e1959c
chore: Fix int - str comparison error in ios desired capabilities (#517)
Akulavenkatesh Apr 19, 2020
a2e21d1
fix: Handling of dictionary-values in WebElement.get_attribute() (#521)
hanneshauer Apr 23, 2020
c702cef
Bump 0.52
KazuCocoa Apr 23, 2020
cfd99cf
Update changelog for 0.52
KazuCocoa Apr 23, 2020
569342e
Merge branch 'master' into rebase-master
ki4070ma Apr 25, 2020
c8d1af3
Fix mypy error
ki4070ma Apr 26, 2020
91a26e8
tweak
ki4070ma Apr 26, 2020
e800ce7
Add wait to test
ki4070ma Apr 26, 2020
efd0655
Skip tap_twice test
ki4070ma Apr 26, 2020
c378859
review comments
ki4070ma Apr 26, 2020
56e8e0c
Remove unnecessary import
ki4070ma Apr 26, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@ MANIFEST
build
dist

# Cache
.cache
__pycache__
.idea
.pytest_cache
.mypy_cache

# Virtual Environments
venv*
.tox

Pipfile.lock

.coverage
165 changes: 165 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,171 @@ Changelog
=========


v0.52 (2020-04-23)
------------------

Fix
~~~
- Handling of dictionary-values in WebElement.get_attribute() (#521)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense to mention that this is the last version supporting Python 2 (because of its EOL)

[Hannes Hauer]

Other
~~~~~
- Bump 0.52. [Kazuaki Matsuo]
- Chore: Fix int - str comparison error in ios desired capabilities
(#517) [Venkatesh]

if number >= PytestXdistWorker.COUNT:
- Test: Add unit test for set_value (setImmediateValue) (#518) [Nrupesh
Patel]
- Test: Fix test_clear flaky functional test (#519) [Nrupesh Patel]
- Update changelog for 0.51. [Kazuaki Matsuo]


v0.51 (2020-04-12)
------------------
- Bump 0.51. [Kazuaki Matsuo]
- Feat: Override send_keys without file upload function (#515) [Kazuaki
Matsuo]

* add send_keys_direct

* override send_keys

* tune

* add unittest instead of functional test

* tweak syntax
- Feat: Add idempotency key header to create session requests (#514)
[Mykola Mokhnach]
- Fix flaky functional tests (#473) [Mori Atsushi]

* 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
- Update changelog for 0.50. [Kazuaki Matsuo]


v0.50 (2020-02-10)
------------------
- Bump 0.50. [Kazuaki Matsuo]
- Feat: Add viewmatcher (#480) [Mori Atsushi]

* Add android view matcher as strategy locator

* Add docstring

* Add functional test

* Remove find_elements_by_android_data_matcher

* Fix docstring

* tweak docstring
- Chore: Fix find_by_images_tests.py (#495) [Mori Atsushi]

* 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
- Update tox requirement from ~=3.6 to ~=3.14 (#494) [dependabot-
preview[bot]]

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](https://github.com/tox-dev/tox/compare/3.6.0...3.14.3)
- Update tox-travis requirement from ~=0.11 to ~=0.12 (#491)
[dependabot-preview[bot]]

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](https://github.com/tox-dev/tox-travis/compare/0.11...0.12)
- Update autopep8 requirement from ~=1.4 to ~=1.5 (#490) [dependabot-
preview[bot]]

Updates the requirements on [autopep8](https://github.com/hhatto/autopep8) to permit the latest version.
- [Release notes](https://github.com/hhatto/autopep8/releases)
- [Commits](https://github.com/hhatto/autopep8/compare/v1.4...v1.5)
- Update pytest-cov requirement from ~=2.6 to ~=2.8 (#489) [dependabot-
preview[bot]]

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](https://github.com/pytest-dev/pytest-cov/compare/v2.6.0...v2.8.1)
- Chore: add try/catch in release script (#479) [Kazuaki Matsuo]

* Add m and try/catch in pushing

* fix error message

* remove -m since it does not work for this usage
- [CI] Run with iOS 13.3 and Xcode 11.3 (#477) [Mori Atsushi]

* [CI] Run with iOS 13.3 and Xcode 11.3

* Skip the case which has problem on Xcode 11.3

* Update FyndByIOClassChainTests along to iOS13

* Update FyndByElementWebelementTests along to iOS13

* Update KeyboardTests along to iOS13

* Update webdriver_tests along to iOS13

* Run test_find_element_by_isvisible with simpleIsVisibleCheck caps

* Run test_hide_keyboard_no_key_name

* Remove unused codes

* [Readme] py.test -> pytest
- Ci: Take screen record as evidence (#481) [Mori Atsushi]

* Take screen record for android

* Take screen record for iOS

* Save screen record for iOS
- Update changelog for 0.49. [Kazuaki Matsuo]


v0.49 (2019-12-24)
------------------
- Bump 0.49. [Kazuaki Matsuo]
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,18 @@ $ pytest -n 2 test/unit
### Functional

```
$ pytest test/functional/ios/find_by_ios_class_chain_tests.py
$ pytest test/functional/ios/search_context/find_by_ios_class_chain_tests.py
```

### In parallel for iOS
1. Create simulators named 'iPhone 6s - 8100' and 'iPhone 6s - 8101'
1. Create simulators named 'iPhone 8 - 8100' and 'iPhone 8 - 8101'
2. Install test libraries via pip
```
$ pip install pytest pytest-xdist
```
3. Run tests
```
$ pytest -n 2 test/functional/ios/find_by_ios_class_chain_tests.py
$ pytest -n 2 test/functional/ios/search_context/find_by_ios_class_chain_tests.py
```

# Release
Expand Down
2 changes: 1 addition & 1 deletion appium/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version = '0.49'
version = '0.52'
11 changes: 9 additions & 2 deletions appium/webdriver/appium_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,26 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Any, Dict
import uuid
from typing import TYPE_CHECKING, Any, Dict

from selenium.webdriver.remote.remote_connection import RemoteConnection

from appium.common.helper import library_version

if TYPE_CHECKING:
from urllib.parse import ParseResult


class AppiumConnection(RemoteConnection):

@classmethod
def get_remote_connection_headers(cls, parsed_url: str, keep_alive: bool = True) -> Dict[str, Any]:
def get_remote_connection_headers(cls, parsed_url: 'ParseResult', keep_alive: bool = True) -> Dict[str, Any]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love mypy

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's nice catch by mypy.

"""Override get_remote_connection_headers in RemoteConnection"""
headers = RemoteConnection.get_remote_connection_headers(parsed_url, keep_alive=keep_alive)
headers['User-Agent'] = 'appium/python {} ({})'.format(library_version(), headers['User-Agent'])
if parsed_url.path.endswith('/session'):
# https://github.com/appium/appium-base-driver/pull/400
headers['X-Idempotency-Key'] = str(uuid.uuid4())

return headers
2 changes: 1 addition & 1 deletion appium/webdriver/appium_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ def start(self, **kwargs: Any) -> sp.Popen:
if not self.is_running or (timeout_ms > 0 and not poll_url(host, port, STATUS_URL, timeout_ms)):
error_msg = f'Appium has failed to start on {host}:{port} within {timeout_ms}ms timeout'
if error_msg is not None:
if stderr == sp.PIPE:
if stderr == sp.PIPE and self._process.stderr is not None:
Copy link
Collaborator Author

@ki4070ma ki4070ma Apr 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Notes] To fix mypy error

err_output = self._process.stderr.read()
if err_output:
error_msg += f'\nOriginal error: {str(err_output)}'
Expand Down
1 change: 1 addition & 0 deletions appium/webdriver/common/mobileby.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class MobileBy(By):
ANDROID_UIAUTOMATOR = '-android uiautomator'
ANDROID_VIEWTAG = '-android viewtag'
ANDROID_DATA_MATCHER = '-android datamatcher'
ANDROID_VIEW_MATCHER = '-android viewmatcher'
WINDOWS_UI_AUTOMATION = '-windows uiautomation'
ACCESSIBILITY_ID = 'accessibility id'
IMAGE = '-image'
Expand Down
46 changes: 40 additions & 6 deletions appium/webdriver/extensions/search_context/android.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# pylint: disable=abstract-method

import json
from typing import TYPE_CHECKING, List, Optional
from typing import TYPE_CHECKING, Any, List, Optional

from appium.webdriver.common.mobileby import MobileBy

Expand All @@ -28,8 +28,42 @@
class AndroidSearchContext(BaseSearchContext):
"""Define search context for Android"""

def find_element_by_android_view_matcher(
self, name: Optional[str] = None, args: Optional[Any] = None, className: Optional[str] = None) -> 'WebElement':
"""Finds element by [onView](https://developer.android.com/training/testing/espresso/basics) in Android

It works with [Espresso Driver](https://github.com/appium/appium-espresso-driver).

Args:
name (:obj:`str`, optional): The name of a method to invoke.
The method must return a Hamcrest
[Matcher](http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matcher.html)
args (:obj:`Any`, optional): The args provided to the method
className (:obj:`str`, optional): The class name that the method is part of (defaults to `org.hamcrest.Matchers`).
Can be fully qualified by having the androidx.test.espresso.matcher. prefix.
If the prefix is not provided then it is going to be added implicitly.
(e.g.: `class=CursorMatchers` fully qualified is `class=androidx.test.espresso.matcher.CursorMatchers`

Returns:
`appium.webdriver.webelement.WebElement`: The found element

Raises:
TypeError - Raises a TypeError if the arguments are not validated for JSON format

Usage:
driver.find_element_by_android_view_matcher(name='withText', args=['Accessibility'], className='ViewMatchers')

# To enable auto completion in PyCharm(IDE)
:rtype: `appium.webdriver.webelement.WebElement`
"""

return self.find_element(
by=MobileBy.ANDROID_VIEW_MATCHER,
value=self._build_data_matcher(name=name, args=args, className=className)
)

def find_element_by_android_data_matcher(
self, name: Optional[str] = None, args: Optional[str] = None, className: Optional[str] = None) -> 'WebElement':
self, name: Optional[str] = None, args: Optional[Any] = None, className: Optional[str] = None) -> 'WebElement':
"""Finds element by [onData](https://medium.com/androiddevelopers/adapterviews-and-espresso-f4172aa853cf) in Android

It works with [Espresso Driver](https://github.com/appium/appium-espresso-driver).
Expand All @@ -38,7 +72,7 @@ def find_element_by_android_data_matcher(
name (:obj:`str`, optional): The name of a method to invoke.
The method must return a Hamcrest
[Matcher](http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matcher.html)
args (:obj:`str`, optional): The args provided to the method
args (:obj:`Any`, optional): The args provided to the method
className (:obj:`str`, optional): The class name that the method is part of (defaults to `org.hamcrest.Matchers`).
Can be fully qualified, or simple, and simple defaults to `androidx.test.espresso.matcher` package
(e.g.: `class=CursorMatchers` fully qualified is `class=androidx.test.espresso.matcher.CursorMatchers`
Expand All @@ -62,15 +96,15 @@ def find_element_by_android_data_matcher(
)

def find_elements_by_android_data_matcher(
self, name: Optional[str] = None, args: Optional[str] = None, className: Optional[str] = None) -> List['WebElement']:
self, name: Optional[str] = None, args: Optional[Any] = None, className: Optional[str] = None) -> List['WebElement']:
"""Finds elements by [onData](https://medium.com/androiddevelopers/adapterviews-and-espresso-f4172aa853cf) in Android
It works with [Espresso Driver](https://github.com/appium/appium-espresso-driver).

Args:
name (:obj:`str`, optional): The name of a method to invoke.
The method must return a Hamcrest
[Matcher](http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matcher.html)
args (:obj:`str`, optional): The args provided to the method
args (:obj:`Any`, optional): The args provided to the method
className (:obj:`str`, optional): The class name that the method is part of (defaults to `org.hamcrest.Matchers`).
Can be fully qualified, or simple, and simple defaults to `androidx.test.espresso.matcher` package
(e.g.: `class=CursorMatchers` fully qualified is `class=androidx.test.espresso.matcher.CursorMatchers`
Expand All @@ -89,7 +123,7 @@ def find_elements_by_android_data_matcher(
value=self._build_data_matcher(name=name, args=args, className=className)
)

def _build_data_matcher(self, name: Optional[str] = None, args: Optional[str]
def _build_data_matcher(self, name: Optional[str] = None, args: Optional[Any]
= None, className: Optional[str] = None) -> str:
result = {}

Expand Down
21 changes: 20 additions & 1 deletion appium/webdriver/webelement.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from typing import Dict, List, Optional, TypeVar, Union

from selenium.webdriver.common.by import By
from selenium.webdriver.common.utils import keys_to_typing
from selenium.webdriver.remote.command import Command as RemoteCommand

from .extensions.search_context import AppiumWebElementSearchContext
Expand All @@ -24,7 +25,7 @@


class WebElement(AppiumWebElementSearchContext):
def get_attribute(self, name: str) -> Optional[str]:
def get_attribute(self, name: str) -> Optional[Union[str, Dict]]:
"""Gets the given attribute or property of the element.

Override for Appium
Expand Down Expand Up @@ -56,6 +57,9 @@ def get_attribute(self, name: str) -> Optional[str]:
if attributeValue is None:
return None

if isinstance(attributeValue, dict):
return attributeValue

# Convert to str along to the spec
if not isinstance(attributeValue, str):
attributeValue = str(attributeValue)
Expand Down Expand Up @@ -205,3 +209,18 @@ def set_value(self, value: str) -> T:
}
self._execute(Command.SET_IMMEDIATE_VALUE, data)
return self

# Override
def send_keys(self, *value: str) -> T:
"""Simulates typing into the element.

Args:
value (str): A string for typing.

Returns:
`appium.webdriver.webelement.WebElement`
"""
keys = keys_to_typing(value)
self._execute(RemoteCommand.SEND_KEYS_TO_ELEMENT,
{'text': ''.join(keys), 'value': keys})
return self
Loading