# encoding: utf-8 module Appium::Ios =begin name, names, text, text should match substring and case insensitive. iOS .name() is the accessibility attribute. If not defined, then .label() is used instead. This differs from Android where name (the content description) is empty when not set. name defaults to label when undefined. value is never a default so that must be included in a new search. Find - search everything. The search order is: 1. name 2. label (implied by name) 3. value Android name = iOS name & label Android text = iOS value =end # @private # returnElems requires a wrapped $(element). # set to empty array when length is zero to prevent hang. # # UIAElementNil when not matched # # 1. secureTextFields # 2. textFields # 3. buttons # 4. elements # # search takes the window to search. # start searching webview first. # window 0 is the main window. # window 1 is the 1st webview (if it exists) # must break instead of return because it's not a function. # # single element length is undefined when found and 0 when not found. # @param predicate [String] the predicate # @return [String] the completed JavaScript program def first_ele_js predicate (<<-JS).strip # remove trailing newline au.mainApp().getFirstWithPredicateWeighted("#{predicate}"); JS end # @private # @param predicate [String] the predicate # @return [String] the completed JavaScript program def all_ele_js predicate (<<-JS).strip # remove trailing newline au.mainApp().getAllWithPredicate("#{predicate}"); JS end # Return the first element matching text. # @param text [String] the text to search for # @return [Element] the first matching element def find text text = escape_single_quote text ele = nil # prefer value search. this may error with: # Can't use in/contains operator with collection 1 js = first_ele_js "value contains[c] '#{text}'" ele = ignore { execute_script js } # now search name and label if the value search didn't match. unless ele js = first_ele_js "name contains[c] '#{text}' || label contains[c] '#{text}'" ele = ignore { execute_script js } end # manually raise error if no element was found raise Selenium::WebDriver::Error::NoSuchElementError, 'An element could not be located on the page using the given search parameters.' unless ele ele end # Return all elements matching text. # @param text [String] the text to search for # @return [Array] all matching elements def finds text text = escape_single_quote text eles = [] # value contains may error js = all_ele_js "value contains[c] '#{text}'" eles = ignore { execute_script js } js = all_ele_js "name contains[c] '#{text}' || label contains[c] '#{text}'" eles += ignore { execute_script js } eles end # Return the first element matching text. # @param text [String] the text to search for # @return [Element] the first matching element def text text text = escape_single_quote text js = first_ele_js "value contains[c] '#{text}'" execute_script js end # Return all elements matching text. # @param text [String] the text to search for # @return [Array] all matching elements def texts text text = escape_single_quote text # XPath //* is not implemented on iOS # https://github.com/appium/appium/issues/430 js = all_ele_js "value contains[c] '#{text}'" execute_script js end # Return the first element matching name. # on Android name is content description # on iOS name is the accessibility label or the text. # # ```ruby # # find element with name or label containing example and access the name attribute. # name('example').name # # # find element with name or label containing example and access the label attribute. # name('example').label # ``` # # @param name [String] the name to search for # @return [Element] the first matching element def name name name = escape_single_quote name mobile :findElementNameContains, name: name end def name_exact name name = escape_single_quote name js = all_ele_js "name == '#{name}'" result = execute_script js return result if result.kind_of? Selenium::WebDriver::Element if result.length > 0 result.first else Appium::Common.raise_no_element_error end end # Return all elements matching name. # on Android name is content description # on iOS name is the accessibility label or the text. # @param name [String] the name to search for # @return [Array] all matching elements def names name name = escape_single_quote name # :name is not consistent across iOS and Android so use custom JavaScript # https://github.com/appium/appium/issues/379 js = all_ele_js "name contains[c] '#{name}' || label contains[c] '#{name}'" execute_script js end def escape_single_quote text_to_escape text_to_escape.gsub("'", '\\' * 4 + "'") end end # module Appium::Ios