Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
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
61 changes: 61 additions & 0 deletions appium/webdriver/extensions/search_context/android.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,66 @@
class AndroidSearchContext(BaseSearchContext):
"""Define search context for Android"""

def find_element_by_android_view_matcher(self, name=None, args=None, className=None):
"""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:`str`, 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`

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='hasEntry', args=['title', 'Animation'])

# 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_elements_by_android_view_matcher(self, name=None, args=None, className=None):
"""Finds elements 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:`str`, 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`

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

Usage:
driver.find_elements_by_android_view_matcher(name='hasEntry', args=['title', 'Animation'])

:rtype: `appium.webdriver.webelement.WebElement`
"""

return self.find_elements(
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=None, args=None, className=None):
"""Finds element by [onData](https://medium.com/androiddevelopers/adapterviews-and-espresso-f4172aa853cf) in Android

Expand Down Expand Up @@ -58,6 +118,7 @@ def find_element_by_android_data_matcher(self, name=None, args=None, className=N

def find_elements_by_android_data_matcher(self, name=None, args=None, className=None):
"""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:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env python

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import unittest

from appium import webdriver
from test.functional.android.helper.test_helper import (
desired_capabilities,
is_ci
)


class FindByViewMatcherTests(unittest.TestCase):

def setUp(self):
desired_caps = desired_capabilities.get_desired_capabilities('ApiDemos-debug.apk.zip')
desired_caps['automationName'] = 'Espresso'
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

def tearDown(self):
if is_ci():
# Take the screenshot to investigate when tests failed only on CI
img_path = os.path.join(os.getcwd(), self._testMethodName + '.png')
self.driver.get_screenshot_as_file(img_path)
self.driver.quit()

def test_find_single_element(self):
els = self.driver.find_elements_by_android_view_matcher(name='hasEntry', args=['title', 'Animation'])
assert len(els) == 1


if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(FindByViewMatcherTests)
unittest.TextTestRunner(verbosity=2).run(suite)