From a3c2d6f8eeeb37d01ab904a29718ecde574d87b2 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Wed, 29 Jan 2025 00:06:09 -0800 Subject: [PATCH] add module and class to make them readable in docs --- lib/appium_lib_core/common/base/driver.rb | 2 +- .../common/base/search_context.rb | 204 +++++++++--------- lib/appium_lib_core/element.rb | 2 +- 3 files changed, 108 insertions(+), 100 deletions(-) diff --git a/lib/appium_lib_core/common/base/driver.rb b/lib/appium_lib_core/common/base/driver.rb index 7f74c517..4bacdc35 100644 --- a/lib/appium_lib_core/common/base/driver.rb +++ b/lib/appium_lib_core/common/base/driver.rb @@ -39,7 +39,7 @@ class Driver < ::Selenium::WebDriver::Driver include ::Appium::Core::Waitable - ::Selenium::WebDriver::SearchContext.extra_finders = APPIUM_EXTRA_FINDERS + ::Selenium::WebDriver::SearchContext.extra_finders = ::Appium::Core::Base::SearchContext::APPIUM_EXTRA_FINDERS # Private API. # Do not use this for general use. Used by flutter driver to get bridge for creating a new element diff --git a/lib/appium_lib_core/common/base/search_context.rb b/lib/appium_lib_core/common/base/search_context.rb index 66797950..d52849ef 100644 --- a/lib/appium_lib_core/common/base/search_context.rb +++ b/lib/appium_lib_core/common/base/search_context.rb @@ -12,102 +12,110 @@ # See the License for the specific language governing permissions and # limitations under the License. -# rubocop:disable Layout/LineLength -# -# Find the first element matching the given arguments -# -# - Android can find with uiautomator like a {http://developer.android.com/tools/help/uiautomator/UiSelector.html UISelector}. -# - iOS can find with a {https://developer.apple.com/library/ios/documentation/ToolsLanguages/Reference/UIAWindowClassReference/UIAWindow/UIAWindow.html#//apple_ref/doc/uid/TP40009930 UIAutomation command}. -# - iOS, only for XCUITest(WebDriverAgent), can find with a {https://github.com/facebook/WebDriverAgent/wiki/Queries class chain} -# -# == Find with image -# Return an element if current view has a partial image. The logic depends on template matching by OpenCV. -# {https://github.com/appium/appium/blob/1.x/docs/en/writing-running-appium/image-comparison.md image-comparison} -# -# You can handle settings for the comparision following {https://github.com/appium/appium-base-driver/blob/master/lib/basedriver/device-settings.js#L6 here} -# -# == Espresso viewmatcher and datamatcher -# Espresso has {https://developer.android.com/training/testing/espresso/basics _onView_ matcher} -# and {https://medium.com/androiddevelopers/adapterviews-and-espresso-f4172aa853cf _onData_ matcher} for more reference -# that allows you to target adapters instead of Views. This method find methods based on reflections -# -# This is a selector strategy that allows users to pass a selector of the form: -# -# { name: '', args: ['arg1', 'arg2', '...'], class: '' } -# -# - _name_: The name of a method to invoke. The method must return -# a Hamcrest {http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matcher.html Matcher} -# - _args_: The args provided to the method -# - _class_: 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 -# -# See example how to send viewmatcher and datamatcher in Ruby client -# -# -# @overload find_element(how, what) -# @param [Symbol, String] how The method to find the element by -# @param [String] what The locator to use -# -# @overload find_element(opts) -# @param [Hash] opts Find options -# @option opts [Symbol] :how Key named after the method to find the element by, containing the locator -# @return [Element] -# @raise [Error::NoSuchElementError] if the element doesn't exist -# -# @example Find element with each keys -# -# # with accessibility id. All platforms. -# @driver.find_elements :accessibility_id, 'Animation' -# @driver.find_elements :accessibility_id, 'Animation' -# -# # with base64 encoded template image. All platforms. -# @driver.find_elements :image, Base64.strict_encode64(File.read(file_path)) -# -# # For Android -# ## With uiautomator -# @driver.find_elements :uiautomator, 'new UiSelector().clickable(true)' -# ## With viewtag, but only for Espresso -# ## 'setTag'/'getTag' in https://developer.android.com/reference/android/view/View -# @driver.find_elements :viewtag, 'new UiSelector().clickable(true)' -# # With data_matcher. The argument should be JSON format. -# @driver.find_elements :data_matcher, { name: 'hasEntry', args: %w(title Animation) }.to_json -# -# # For iOS -# ## With :predicate -# @driver.find_elements :predicate, "isWDVisible == 1" -# @driver.find_elements :predicate, 'wdName == "Buttons"' -# @driver.find_elements :predicate, 'wdValue == "SearchBar" AND isWDDivisible == 1' -# -# ## With Class Chain -# ### select the third child button of the first child window element -# @driver.find_elements :class_chain, 'XCUIElementTypeWindow/XCUIElementTypeButton[3]' -# ### select all the children windows -# @driver.find_elements :class_chain, 'XCUIElementTypeWindow' -# ### select the second last child of the second child window -# @driver.find_elements :class_chain, 'XCUIElementTypeWindow[2]/XCUIElementTypeAny[-2]' -# ### matching predicate. ' is the mark. -# @driver.find_elements :class_chain, 'XCUIElementTypeWindow['visible = 1]['name = "bla"']' -# ### containing predicate. '$' is the mark. -# ### Require appium-xcuitest-driver 2.54.0+. PR: https://github.com/facebook/WebDriverAgent/pull/707/files -# @driver.find_elements :class_chain, 'XCUIElementTypeWindow[$name = \"bla$$$bla\"$]' -# e = find_element :class_chain, "**/XCUIElementTypeWindow[$name == 'Buttons'$]" -# e.tag_name #=> "XCUIElementTypeWindow" -# e = find_element :class_chain, "**/XCUIElementTypeStaticText[$name == 'Buttons'$]" -# e.tag_name #=> "XCUIElementTypeStaticText" -# -# rubocop:enable Layout/LineLength +module Appium + module Core + class Base + module SearchContext + # rubocop:disable Layout/LineLength + # + # Find the first element matching the given arguments + # + # - Android can find with uiautomator like a {http://developer.android.com/tools/help/uiautomator/UiSelector.html UISelector}. + # - iOS can find with a {https://developer.apple.com/library/ios/documentation/ToolsLanguages/Reference/UIAWindowClassReference/UIAWindow/UIAWindow.html#//apple_ref/doc/uid/TP40009930 UIAutomation command}. + # - iOS, only for XCUITest(WebDriverAgent), can find with a {https://github.com/facebook/WebDriverAgent/wiki/Queries class chain} + # + # == Find with image + # Return an element if current view has a partial image. The logic depends on template matching by OpenCV. + # {https://github.com/appium/appium/blob/1.x/docs/en/writing-running-appium/image-comparison.md image-comparison} + # + # You can handle settings for the comparision following {https://github.com/appium/appium-base-driver/blob/master/lib/basedriver/device-settings.js#L6 here} + # + # == Espresso viewmatcher and datamatcher + # Espresso has {https://developer.android.com/training/testing/espresso/basics _onView_ matcher} + # and {https://medium.com/androiddevelopers/adapterviews-and-espresso-f4172aa853cf _onData_ matcher} for more reference + # that allows you to target adapters instead of Views. This method find methods based on reflections + # + # This is a selector strategy that allows users to pass a selector of the form: + # + # { name: '', args: ['arg1', 'arg2', '...'], class: '' } + # + # - _name_: The name of a method to invoke. The method must return + # a Hamcrest {http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matcher.html Matcher} + # - _args_: The args provided to the method + # - _class_: 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 + # + # See example how to send viewmatcher and datamatcher in Ruby client + # + # + # @overload find_element(how, what) + # @param [Symbol, String] how The method to find the element by + # @param [String] what The locator to use + # + # @overload find_element(opts) + # @param [Hash] opts Find options + # @option opts [Symbol] :how Key named after the method to find the element by, containing the locator + # @return [Element] + # @raise [Error::NoSuchElementError] if the element doesn't exist + # + # @example Find element with each keys + # + # # with accessibility id. All platforms. + # @driver.find_elements :accessibility_id, 'Animation' + # @driver.find_elements :accessibility_id, 'Animation' + # + # # with base64 encoded template image. All platforms. + # @driver.find_elements :image, Base64.strict_encode64(File.read(file_path)) + # + # # For Android + # ## With uiautomator + # @driver.find_elements :uiautomator, 'new UiSelector().clickable(true)' + # ## With viewtag, but only for Espresso + # ## 'setTag'/'getTag' in https://developer.android.com/reference/android/view/View + # @driver.find_elements :viewtag, 'new UiSelector().clickable(true)' + # # With data_matcher. The argument should be JSON format. + # @driver.find_elements :data_matcher, { name: 'hasEntry', args: %w(title Animation) }.to_json + # + # # For iOS + # ## With :predicate + # @driver.find_elements :predicate, "isWDVisible == 1" + # @driver.find_elements :predicate, 'wdName == "Buttons"' + # @driver.find_elements :predicate, 'wdValue == "SearchBar" AND isWDDivisible == 1' + # + # ## With Class Chain + # ### select the third child button of the first child window element + # @driver.find_elements :class_chain, 'XCUIElementTypeWindow/XCUIElementTypeButton[3]' + # ### select all the children windows + # @driver.find_elements :class_chain, 'XCUIElementTypeWindow' + # ### select the second last child of the second child window + # @driver.find_elements :class_chain, 'XCUIElementTypeWindow[2]/XCUIElementTypeAny[-2]' + # ### matching predicate. ' is the mark. + # @driver.find_elements :class_chain, 'XCUIElementTypeWindow['visible = 1]['name = "bla"']' + # ### containing predicate. '$' is the mark. + # ### Require appium-xcuitest-driver 2.54.0+. PR: https://github.com/facebook/WebDriverAgent/pull/707/files + # @driver.find_elements :class_chain, 'XCUIElementTypeWindow[$name = \"bla$$$bla\"$]' + # e = find_element :class_chain, "**/XCUIElementTypeWindow[$name == 'Buttons'$]" + # e.tag_name #=> "XCUIElementTypeWindow" + # e = find_element :class_chain, "**/XCUIElementTypeStaticText[$name == 'Buttons'$]" + # e.tag_name #=> "XCUIElementTypeStaticText" + # + # rubocop:enable Layout/LineLength -APPIUM_EXTRA_FINDERS = { - accessibility_id: 'accessibility id', - image: '-image', - custom: '-custom', - # Android - uiautomator: '-android uiautomator', # Unavailable in Espresso - viewtag: '-android viewtag', # Available in Espresso - data_matcher: '-android datamatcher', # Available in Espresso - view_matcher: '-android viewmatcher', # Available in Espresso - # iOS - predicate: '-ios predicate string', - class_chain: '-ios class chain' -}.freeze + APPIUM_EXTRA_FINDERS = { + accessibility_id: 'accessibility id', + image: '-image', + custom: '-custom', + # Android + uiautomator: '-android uiautomator', # Unavailable in Espresso + viewtag: '-android viewtag', # Available in Espresso + data_matcher: '-android datamatcher', # Available in Espresso + view_matcher: '-android viewmatcher', # Available in Espresso + # iOS + predicate: '-ios predicate string', + class_chain: '-ios class chain' + }.freeze + end + end + end +end diff --git a/lib/appium_lib_core/element.rb b/lib/appium_lib_core/element.rb index 23ca2568..9b7c2b65 100644 --- a/lib/appium_lib_core/element.rb +++ b/lib/appium_lib_core/element.rb @@ -19,7 +19,7 @@ module Core class Element < ::Selenium::WebDriver::Element include ::Appium::Core::Base::TakesScreenshot - ::Selenium::WebDriver::SearchContext.extra_finders = APPIUM_EXTRA_FINDERS + ::Selenium::WebDriver::SearchContext.extra_finders = ::Appium::Core::Base::SearchContext::APPIUM_EXTRA_FINDERS # Retuns the element id. #