Module: Appium::Ios
- Defined in:
- lib/appium_lib/ios/patch.rb,
lib/appium_lib/ios/helper.rb,
lib/appium_lib/ios/element/text.rb,
lib/appium_lib/ios/element/alert.rb,
lib/appium_lib/ios/element/button.rb,
lib/appium_lib/ios/mobile_methods.rb,
lib/appium_lib/ios/element/generic.rb,
lib/appium_lib/ios/element/textfield.rb
Constant Summary collapse
- UIAStaticText =
'UIAStaticText'- UIAButton =
'UIAButton'- UIATextField =
'UIATextField'- UIASecureTextField =
'UIASecureTextField'
Class Method Summary collapse
- .extended(_mod) ⇒ Object
-
.uiautomation_find ⇒ Object
find_element/s can be used with a [UIAutomation command](developer.apple.com/library/ios/documentation/ToolsLanguages/Reference/UIAWindowClassReference/UIAWindow/UIAWindow.html#//apple_ref/doc/uid/TP40009930).
Instance Method Summary collapse
-
#_all_pred(opts) ⇒ Object
predicate - the predicate to evaluate on the main app.
-
#_by_json(opts) ⇒ Object
typeArray - array of string types to search for.
- #_validate_object(*objects) ⇒ Object
-
#alert_accept ⇒ void
Accept the alert.
-
#alert_dismiss ⇒ void
Dismiss the alert.
-
#button(value) ⇒ UIAButton
Find the first UIAButton that contains value or by index.
-
#button_exact(value) ⇒ UIAButton
Find the first UIAButton that exactly matches value.
-
#buttons(value = false) ⇒ Array<UIAButton>
Find all UIAButtons containing value.
-
#buttons_exact(value) ⇒ Array<UIAButton>
Find all UIAButtons that exactly match value.
-
#ele_by_json(opts) ⇒ Object
see eles_by_json.
-
#ele_by_json_visible_contains(element, value) ⇒ Element
Find the first element that contains value.
-
#ele_by_json_visible_exact(element, value) ⇒ Element
Find the first element exactly matching value.
-
#ele_index(class_name, index) ⇒ Element
Get the element of type class_name at matching index.
-
#ele_with_pred(opts) ⇒ Element
returns element matching predicate contained in the main app.
-
#eles_by_json(opts) ⇒ Object
example usage:.
-
#eles_by_json_visible_contains(element, value) ⇒ Array<Element>
Find all elements containing value.
-
#eles_by_json_visible_exact(element, value) ⇒ Element
Find all elements exactly matching value.
-
#eles_with_pred(opts) ⇒ Array<Element>
returns elements matching predicate contained in the main app.
- #empty(ele) ⇒ Object
-
#find(value) ⇒ Element
Find the first element containing value.
-
#find_ele_by_attr(class_name, attr, value) ⇒ Element
Find the first element exactly matching class and attribute value.
-
#find_ele_by_attr_include(class_name, attr, value) ⇒ Element
Get the first tag by attribute that exactly matches value.
-
#find_eles_by_attr(class_name, attr, value) ⇒ Array<Element>
Find all elements exactly matching class and attribute value.
-
#find_eles_by_attr_include(class_name, attr, value) ⇒ Array<Element>
Get tags by attribute that include value.
-
#find_exact(value) ⇒ Element
Find the first element exactly matching value.
-
#finds(value) ⇒ Array<Element>
Find all elements containing value.
-
#finds_exact(value) ⇒ Array<Element>
Find all elements exactly matching value.
-
#first_button ⇒ UIAButton
Find the first UIAButton.
-
#first_ele(class_name) ⇒ Element
Get the first tag that matches class_name.
-
#first_text ⇒ UIAStaticText
Find the first UIAStaticText.
-
#first_textfield ⇒ TextField
Find the first TextField.
- #fix_space(s) ⇒ Object
-
#get_page(element = source_window(0), class_name = nil) ⇒ String
Returns a string of interesting elements.
-
#get_source ⇒ String
Returns XML string for the current page Same as driver.page_source.
-
#hide_ios_keyboard(close_key = 'Done') ⇒ void
If there’s no keyboard, then do nothing.
-
#id(id) ⇒ Element
Find by id.
-
#ios_password(length = 1) ⇒ String
iOS only.
-
#ios_version ⇒ Array<Integer>
Return the iOS version as an array of integers.
-
#last_button ⇒ UIAButton
Find the last UIAButton.
-
#last_ele(class_name) ⇒ Element
Get the last tag that matches class_name.
-
#last_text ⇒ UIAStaticText
Find the last UIAStaticText.
-
#last_textfield ⇒ TextField
Find the last TextField.
-
#page(opts = {}) ⇒ void
Prints a string of interesting elements to the console.
-
#page_window(window_number = 0) ⇒ void
Prints parsed page source to console.
-
#patch_webdriver_element ⇒ Object
class_eval inside a method because class Selenium::WebDriver::Element will trigger as soon as the file is required.
-
#source ⇒ void
Prints xml of the current page.
-
#source_window(window_number = 0) ⇒ JSON
Gets the JSON source of window number.
- #string_attr_exact(class_name, attr, value) ⇒ Object
- #string_attr_include(class_name, attr, value) ⇒ Object
-
#string_visible_contains(element, value) ⇒ String
Returns an object that matches the first element that contains value.
-
#string_visible_exact(element, value) ⇒ String
Create an object to exactly match the first element with target value.
-
#tag(class_name) ⇒ Element
Returns the first visible element matching class_name.
-
#tags(class_name) ⇒ Element
Returns all visible elements matching class_name.
-
#text(value) ⇒ UIAStaticText
Find the first UIAStaticText that contains value or by index.
-
#text_exact(value) ⇒ UIAStaticText
Find the first UIAStaticText that exactly matches value.
-
#textfield(value) ⇒ TextField
Find the first TextField that contains value or by index.
-
#textfield_exact(value) ⇒ TextField
Find the first TextField that exactly matches value.
-
#textfields(value = false) ⇒ Array<TextField>
Find all TextFields containing value.
-
#textfields_exact(value) ⇒ Array<TextField>
Find all TextFields that exactly match value.
-
#texts(value = false) ⇒ Array<UIAStaticText>
Find all UIAStaticText containing value.
-
#texts_exact(value) ⇒ Array<UIAStaticText>
Find all UIAStaticTexts that exactly match value.
Class Method Details
.extended(_mod) ⇒ Object
10 11 12 13 14 |
# File 'lib/appium_lib/ios/mobile_methods.rb', line 10 def extended(_mod) Selenium::WebDriver::SearchContext.class_eval do Selenium::WebDriver::SearchContext::FINDERS[:uiautomation] = '-ios uiautomation' end end |
.uiautomation_find ⇒ Object
find_element/s can be used with a [UIAutomation command](developer.apple.com/library/ios/documentation/ToolsLanguages/Reference/UIAWindowClassReference/UIAWindow/UIAWindow.html#//apple_ref/doc/uid/TP40009930).
“‘ruby
find_elements :uiautomation, 'elements()
“‘
10 11 12 13 14 |
# File 'lib/appium_lib/ios/mobile_methods.rb', line 10 def extended(_mod) Selenium::WebDriver::SearchContext.class_eval do Selenium::WebDriver::SearchContext::FINDERS[:uiautomation] = '-ios uiautomation' end end |
Instance Method Details
#_all_pred(opts) ⇒ Object
predicate - the predicate to evaluate on the main app
visible - if true, only visible elements are returned. default true
438 439 440 441 442 443 |
# File 'lib/appium_lib/ios/helper.rb', line 438 def _all_pred(opts) predicate = opts[:predicate] fail 'predicate must be provided' unless predicate visible = opts.fetch :visible, true %($.mainApp().getAllWithPredicate("#{predicate}", #{visible});) end |
#_by_json(opts) ⇒ Object
typeArray - array of string types to search for. Example: [“UIAStaticText”] onlyFirst - boolean. returns only the first result if true. Example: true onlyVisible - boolean. returns only visible elements if true. Example: true target - string. the target value to search for. Example: “Buttons, Various uses of UIButton” substring - boolean. matches on substrings if true otherwise an exact mathc is required. Example: true insensitive - boolean. ignores case sensitivity if true otherwise it’s case sensitive. Example: true
opts = {
typeArray: ["UIAStaticText"],
onlyFirst: true,
onlyVisible: true,
name: {
target: "Buttons, Various uses of UIButton",
substring: false,
insensitive: false,
},
label: {
target: "Buttons, Various uses of UIButton",
substring: false,
insensitive: false,
},
value: {
target: "Buttons, Various uses of UIButton",
substring: false,
insensitive: false,
}
}
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 |
# File 'lib/appium_lib/ios/helper.rb', line 520 def _by_json(opts) valid_keys = [:typeArray, :onlyFirst, :onlyVisible, :name, :label, :value] unknown_keys = opts.keys - valid_keys fail "Unknown keys: #{unknown_keys}" unless unknown_keys.empty? type_array = opts[:typeArray] fail 'typeArray must be an array' unless type_array.is_a? Array only_first = opts[:onlyFirst] fail 'onlyFirst must be a boolean' unless [true, false].include? only_first only_visible = opts[:onlyVisible] fail 'onlyVisible must be a boolean' unless [true, false].include? only_visible # name/label/value are optional. when searching for class only, then none # will be present. _validate_object opts[:name], opts[:label], opts[:value] # note that mainWindow is sometimes nil so it's passed as a param # $._elementOrElementsByType will validate that the window isn't nil element_or_elements_by_type = <<-JS (function() { var opts = #{opts.to_json}; var result = false; try { result = $._elementOrElementsByType($.mainWindow(), opts); } catch (e) { } return result; })(); JS res = execute_script element_or_elements_by_type res ? res : fail(Selenium::Client::CommandError, 'mainWindow is nil') end |
#_validate_object(*objects) ⇒ Object
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 |
# File 'lib/appium_lib/ios/helper.rb', line 472 def _validate_object(*objects) fail 'objects must be an array' unless objects.is_a? Array objects.each do |obj| next unless obj # obj may be nil. if so, ignore. valid_keys = [:target, :substring, :insensitive] unknown_keys = obj.keys - valid_keys fail "Unknown keys: #{unknown_keys}" unless unknown_keys.empty? target = obj[:target] fail 'target must be a string' unless target.is_a? String substring = obj[:substring] fail 'substring must be a boolean' unless [true, false].include? substring insensitive = obj[:insensitive] fail 'insensitive must be a boolean' unless [true, false].include? insensitive end end |
#alert_accept ⇒ void
This method returns an undefined value.
Accept the alert.
5 6 7 8 9 |
# File 'lib/appium_lib/ios/element/alert.rb', line 5 def alert_accept # @driver.switch_to.alert.accept # ".switch_to.alert" calls getAlertText so use bridge directly driver.send(:bridge).acceptAlert end |
#alert_dismiss ⇒ void
This method returns an undefined value.
Dismiss the alert.
13 14 15 16 17 |
# File 'lib/appium_lib/ios/element/alert.rb', line 13 def alert_dismiss # @driver.switch_to.alert.dismiss # ".switch_to.alert" calls getAlertText so use bridge directly driver.send(:bridge).dismissAlert end |
#button(value) ⇒ UIAButton
Find the first UIAButton that contains value or by index. If int then the UIAButton at that index is returned.
10 11 12 13 14 |
# File 'lib/appium_lib/ios/element/button.rb', line 10 def (value) # return button at index. return ele_index UIAButton, value if value.is_a? Numeric ele_by_json_visible_contains UIAButton, value end |
#button_exact(value) ⇒ UIAButton
Find the first UIAButton that exactly matches value.
40 41 42 |
# File 'lib/appium_lib/ios/element/button.rb', line 40 def (value) ele_by_json_visible_exact UIAButton, value end |
#buttons(value = false) ⇒ Array<UIAButton>
Find all UIAButtons containing value. If value is omitted, all UIAButtons are returned.
20 21 22 23 |
# File 'lib/appium_lib/ios/element/button.rb', line 20 def (value = false) return UIAButton unless value eles_by_json_visible_contains UIAButton, value end |
#buttons_exact(value) ⇒ Array<UIAButton>
Find all UIAButtons that exactly match value.
47 48 49 |
# File 'lib/appium_lib/ios/element/button.rb', line 47 def (value) eles_by_json_visible_exact UIAButton, value end |
#ele_by_json(opts) ⇒ Object
see eles_by_json
575 576 577 578 579 580 |
# File 'lib/appium_lib/ios/helper.rb', line 575 def ele_by_json(opts) opts[:onlyFirst] = true result = _by_json(opts).first fail _no_such_element if result.nil? result end |
#ele_by_json_visible_contains(element, value) ⇒ Element
Find the first element that contains value
329 330 331 |
# File 'lib/appium_lib/ios/helper.rb', line 329 def ele_by_json_visible_contains(element, value) ele_by_json string_visible_contains element, value end |
#ele_by_json_visible_exact(element, value) ⇒ Element
Find the first element exactly matching value
366 367 368 |
# File 'lib/appium_lib/ios/helper.rb', line 366 def ele_by_json_visible_exact(element, value) ele_by_json string_visible_exact element, value end |
#ele_index(class_name, index) ⇒ Element
Get the element of type class_name at matching index.
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/appium_lib/ios/helper.rb', line 198 def ele_index(class_name, index) fail 'Index must be >= 1' unless index == 'last()' || (index.is_a?(Integer) && index >= 1) elements = (class_name) if index == 'last()' result = elements.last else # elements array is 0 indexed index -= 1 result = elements[index] end fail _no_such_element if result.nil? result end |
#ele_with_pred(opts) ⇒ Element
returns element matching predicate contained in the main app
predicate - the predicate to evaluate on the main app
visible - if true, only visible elements are returned. default true
451 452 453 454 |
# File 'lib/appium_lib/ios/helper.rb', line 451 def ele_with_pred(opts) # true = return only visible find_element(:uiautomation, _all_pred(opts)) end |
#eles_by_json(opts) ⇒ Object
example usage:
eles_by_json({
typeArray: ["UIAStaticText"],
onlyVisible: true,
name: {
target: "Buttons, Various uses of UIButton",
substring: false,
insensitive: false,
},
})
569 570 571 572 |
# File 'lib/appium_lib/ios/helper.rb', line 569 def eles_by_json(opts) opts[:onlyFirst] = false _by_json opts end |
#eles_by_json_visible_contains(element, value) ⇒ Array<Element>
Find all elements containing value
337 338 339 |
# File 'lib/appium_lib/ios/helper.rb', line 337 def eles_by_json_visible_contains(element, value) eles_by_json string_visible_contains element, value end |
#eles_by_json_visible_exact(element, value) ⇒ Element
Find all elements exactly matching value
374 375 376 |
# File 'lib/appium_lib/ios/helper.rb', line 374 def eles_by_json_visible_exact(element, value) eles_by_json string_visible_exact element, value end |
#eles_with_pred(opts) ⇒ Array<Element>
returns elements matching predicate contained in the main app
predicate - the predicate to evaluate on the main app
visible - if true, only visible elements are returned. default true
462 463 464 |
# File 'lib/appium_lib/ios/helper.rb', line 462 def eles_with_pred(opts) find_elements(:uiautomation, _all_pred(opts)) end |
#empty(ele) ⇒ Object
25 26 27 |
# File 'lib/appium_lib/ios/helper.rb', line 25 def empty(ele) (ele['name'] || ele['label'] || ele['value']).nil? end |
#find(value) ⇒ Element
Find the first element containing value
6 7 8 |
# File 'lib/appium_lib/ios/element/generic.rb', line 6 def find(value) ele_by_json_visible_contains '*', value end |
#find_ele_by_attr(class_name, attr, value) ⇒ Element
Find the first element exactly matching class and attribute value. Note: Uses XPath
225 226 227 |
# File 'lib/appium_lib/ios/helper.rb', line 225 def find_ele_by_attr(class_name, attr, value) @driver.find_element :xpath, string_attr_exact(class_name, attr, value) end |
#find_ele_by_attr_include(class_name, attr, value) ⇒ Element
Get the first tag by attribute that exactly matches value. Note: Uses XPath
250 251 252 |
# File 'lib/appium_lib/ios/helper.rb', line 250 def find_ele_by_attr_include(class_name, attr, value) @driver.find_element :xpath, string_attr_include(class_name, attr, value) end |
#find_eles_by_attr(class_name, attr, value) ⇒ Array<Element>
Find all elements exactly matching class and attribute value. Note: Uses XPath
235 236 237 |
# File 'lib/appium_lib/ios/helper.rb', line 235 def find_eles_by_attr(class_name, attr, value) @driver.find_elements :xpath, string_attr_exact(class_name, attr, value) end |
#find_eles_by_attr_include(class_name, attr, value) ⇒ Array<Element>
Get tags by attribute that include value. Note: Uses XPath
260 261 262 |
# File 'lib/appium_lib/ios/helper.rb', line 260 def find_eles_by_attr_include(class_name, attr, value) @driver.find_elements :xpath, string_attr_include(class_name, attr, value) end |
#find_exact(value) ⇒ Element
Find the first element exactly matching value
20 21 22 |
# File 'lib/appium_lib/ios/element/generic.rb', line 20 def find_exact(value) ele_by_json_visible_exact '*', value end |
#finds(value) ⇒ Array<Element>
Find all elements containing value
13 14 15 |
# File 'lib/appium_lib/ios/element/generic.rb', line 13 def finds(value) eles_by_json_visible_contains '*', value end |
#finds_exact(value) ⇒ Array<Element>
Find all elements exactly matching value
27 28 29 |
# File 'lib/appium_lib/ios/element/generic.rb', line 27 def finds_exact(value) eles_by_json_visible_exact '*', value end |
#first_button ⇒ UIAButton
Find the first UIAButton.
27 28 29 |
# File 'lib/appium_lib/ios/element/button.rb', line 27 def first_ele UIAButton end |
#first_ele(class_name) ⇒ Element
Get the first tag that matches class_name
267 268 269 270 |
# File 'lib/appium_lib/ios/helper.rb', line 267 def first_ele(class_name) # XPath index starts at 1 ele_index class_name, 1 end |
#first_text ⇒ UIAStaticText
Find the first UIAStaticText.
26 27 28 |
# File 'lib/appium_lib/ios/element/text.rb', line 26 def first_text first_ele UIAStaticText end |
#first_textfield ⇒ TextField
Find the first TextField.
79 80 81 |
# File 'lib/appium_lib/ios/element/textfield.rb', line 79 def first_textfield ele_by_json _textfield_visible end |
#fix_space(s) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/appium_lib/ios/helper.rb', line 30 def fix_space(s) # if s is an int, we can't call .empty return nil if s.nil? || (s.respond_to?(:empty) && s.empty?) # ints don't respond to force encoding # ensure we're converting to a string unless s.respond_to? :force_encoding s_s = s.to_s return s_s.empty? ? nil : s_s end # char code 160 (name, label) vs 32 (value) will break comparison. # convert string to binary and remove 160. # \xC2\xA0 s = s.force_encoding('binary').gsub("\xC2\xA0".force_encoding('binary'), ' ') if s s.empty? ? nil : s.force_encoding('UTF-8') end |
#get_page(element = source_window(0), class_name = nil) ⇒ String
Returns a string of interesting elements. iOS only.
Defaults to inspecting the 1st windows source only. use get_page(get_source) for all window sources
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/appium_lib/ios/helper.rb', line 20 def get_page(element = source_window(0), class_name = nil) lazy_load_strings # populate @strings_xml class_name = class_name.to_s.downcase # @private def empty(ele) (ele['name'] || ele['label'] || ele['value']).nil? end # @private def fix_space(s) # if s is an int, we can't call .empty return nil if s.nil? || (s.respond_to?(:empty) && s.empty?) # ints don't respond to force encoding # ensure we're converting to a string unless s.respond_to? :force_encoding s_s = s.to_s return s_s.empty? ? nil : s_s end # char code 160 (name, label) vs 32 (value) will break comparison. # convert string to binary and remove 160. # \xC2\xA0 s = s.force_encoding('binary').gsub("\xC2\xA0".force_encoding('binary'), ' ') if s s.empty? ? nil : s.force_encoding('UTF-8') end unless empty(element) || element['visible'] == false name = fix_space element['name'] label = fix_space element['label'] value = fix_space element['value'] hint = fix_space element['hint'] visible = fix_space element['visible'] type = fix_space element['type'] # TODO: Rubocop warning cleanup # rubocop:disable Metrics/BlockNesting # if class_name is set, mark non-matches as invisible visible = (type.downcase.include?(class_name)).to_s if class_name if visible && visible == 'true' if name == label && name == value puts "#{type}" if name || label || value || hint puts " name, label, value: #{name}" if name puts " hint: #{hint}" if hint elsif name == label puts "#{type}" if name || label || value || hint puts " name, label: #{name}" if name puts " value: #{value}" if value puts " hint: #{hint}" if hint elsif name == value puts "#{type}" if name || label || value || hint puts " name, value: #{name}" if name puts " label: #{label}" if label puts " hint: #{hint}" if hint else puts "#{type}" if name || label || value || hint puts " name: #{name}" if name puts " label: #{label}" if label puts " value: #{value}" if value puts " hint: #{hint}" if hint end # rubocop:enable Metrics/BlockNesting # there may be many ids with the same value. # output all exact matches. attributes = [name, label, value, hint].select { |attr| !attr.nil? } partial = {} id_matches = @strings_xml.select do |key, val| next if val.nil? || val.empty? partial[key] = val if attributes.detect { |attr| attr.include?(val) } attributes.detect { |attr| val == attr } end # If there are no exact matches, display partial matches. id_matches = partial if id_matches.empty? unless id_matches.empty? match_str = '' max_len = id_matches.keys.max_by(&:length).length # [0] = key, [1] = val id_matches.each do |key, val| arrow_space = ' ' * (max_len - key.length).to_i match_str += ' ' * 7 + "#{key} #{arrow_space}=> #{val}\n" end puts " id: #{match_str.strip}\n" end end end children = element['children'] children.each { |c| get_page c, class_name } if children nil end |
#get_source ⇒ String
Returns XML string for the current page Same as driver.page_source
585 586 587 |
# File 'lib/appium_lib/ios/helper.rb', line 585 def get_source @driver.page_source end |
#hide_ios_keyboard(close_key = 'Done') ⇒ void
This method returns an undefined value.
If there’s no keyboard, then do nothing. If there’s no close key, fallback to window tap. If close key is present then tap it.
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 |
# File 'lib/appium_lib/ios/helper.rb', line 384 def hide_ios_keyboard(close_key = 'Done') # # TODO: there are many various ways to hide the keyboard that work in different # app specific circumstances. webview keyboard will require a window.tap for example. # # Find the top left corner of the keyboard and move up 10 pixels (origin.y - 10) # now swipe down until the end of the window - 10 pixels. # -10 to ensure we're not going outside the window bounds. # # Swiping inside the keyboard will not dismiss it. # # If the 'Done' key exists then that should be pressed to dismiss the keyboard # because swiping to dismiss works only if such key doesn't exist. # # Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28 # dismiss_keyboard = (<<-JS).strip if (!au.mainApp().keyboard().isNil()) { var key = au.mainApp().keyboard().buttons()['#{close_key}'] if (key.isNil()) { var startY = au.mainApp().keyboard().rect().origin.y - 10; var endY = au.mainWindow().rect().size.height - 10; au.flickApp(0, startY, 0, endY); } else { key.tap(); } au.delay(1000); } JS ignore do # wait 5 seconds for a wild keyboard to appear. if the textfield is disabled # then setValue will work, however the keyboard will never display # because users are normally not allowed to type into it. wait_true(5) do execute_script '!au.mainApp().keyboard().isNil()' end # dismiss keyboard execute_script dismiss_keyboard end # wait 5 seconds for keyboard to go away. # if the keyboard isn't dismissed then wait_true will error. wait_true(5) do execute_script 'au.mainApp().keyboard().isNil()' end end |
#id(id) ⇒ Element
Find by id
183 184 185 |
# File 'lib/appium_lib/ios/helper.rb', line 183 def id(id) find_element :id, id end |
#ios_password(length = 1) ⇒ String
iOS only. On Android uiautomator always returns an empty string for EditText password.
Password character returned from value of UIASecureTextField
8 9 10 |
# File 'lib/appium_lib/ios/helper.rb', line 8 def ios_password(length = 1) 8226.chr('UTF-8') * length end |
#ios_version ⇒ Array<Integer>
Return the iOS version as an array of integers
189 190 191 192 |
# File 'lib/appium_lib/ios/helper.rb', line 189 def ios_version ios_version = execute_script 'UIATarget.localTarget().systemVersion()' ios_version.split('.').map(&:to_i) end |
#last_button ⇒ UIAButton
Find the last UIAButton.
33 34 35 |
# File 'lib/appium_lib/ios/element/button.rb', line 33 def last_ele UIAButton end |
#last_ele(class_name) ⇒ Element
Get the last tag that matches class_name
275 276 277 |
# File 'lib/appium_lib/ios/helper.rb', line 275 def last_ele(class_name) ele_index class_name, 'last()' end |
#last_text ⇒ UIAStaticText
Find the last UIAStaticText.
32 33 34 |
# File 'lib/appium_lib/ios/element/text.rb', line 32 def last_text last_ele UIAStaticText end |
#last_textfield ⇒ TextField
Find the last TextField.
85 86 87 88 89 |
# File 'lib/appium_lib/ios/element/textfield.rb', line 85 def last_textfield result = eles_by_json(_textfield_visible).last fail _no_such_element if result.nil? result end |
#page(opts = {}) ⇒ void
This method returns an undefined value.
Prints a string of interesting elements to the console.
Example
“‘ruby page class: :UIAButton # filter on buttons page window: 1 # show source for window 1 page class: :UIAButton, window: 1 “`
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/appium_lib/ios/helper.rb', line 129 def page(opts = {}) if opts.is_a?(Hash) window_number = opts.fetch :window, -1 class_name = opts.fetch :class, nil else window_number = -1 class_name = opts end # current_context may be nil which breaks start_with if current_context && current_context.start_with?('WEBVIEW') s = get_source parser = @android_html_parser ||= Nokogiri::HTML::SAX::Parser.new(Common::HTMLElements.new) parser.document.reset parser.document.filter = class_name parser.parse s parser.document.result else if window_number == -1 # if the 0th window has no children, find the next window that does. target_window = source_window 0 target_window = source_window 1 if target_window['children'].empty? get_page target_window, class_name else get_page source_window(window_number || 0), class_name end nil end end |
#page_window(window_number = 0) ⇒ void
This method returns an undefined value.
Prints parsed page source to console.
example: page_window 0
175 176 177 178 |
# File 'lib/appium_lib/ios/helper.rb', line 175 def page_window(window_number = 0) get_page source_window window_number nil end |
#patch_webdriver_element ⇒ Object
class_eval inside a method because class Selenium::WebDriver::Element will trigger as soon as the file is required. in contrast a method will trigger only when invoked.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/appium_lib/ios/patch.rb', line 7 def patch_webdriver_element Selenium::WebDriver::Element.class_eval do # Enable access to iOS accessibility label # accessibility identifier is supported as 'name' def label attribute('label') end # Cross platform way of entering text into a textfield def type(text) # type $driver.execute_script %(au.getElement('#{ref}').setValue('#{text}');) end # def type end # Selenium::WebDriver::Element.class_eval end |
#source ⇒ void
This method returns an undefined value.
Prints xml of the current page
468 469 470 |
# File 'lib/appium_lib/ios/helper.rb', line 468 def source _print_source get_source end |
#source_window(window_number = 0) ⇒ JSON
Gets the JSON source of window number
161 162 163 164 165 166 167 |
# File 'lib/appium_lib/ios/helper.rb', line 161 def source_window(window_number = 0) # appium 1.0 still returns JSON when getTree() is invoked so this # doesn't need to change to XML. If getTree() is removed then # source_window will need to parse the elements of getTreeForXML()\ # https://github.com/appium/appium-uiauto/blob/247eb71383fa1a087ff8f8fc96fac25025731f3f/uiauto/appium/element.js#L145 execute_script "UIATarget.localTarget().frontMostApp().windows()[#{window_number}].getTree()" end |
#string_attr_exact(class_name, attr, value) ⇒ Object
215 216 217 |
# File 'lib/appium_lib/ios/helper.rb', line 215 def string_attr_exact(class_name, attr, value) %(//#{class_name}[@visible="true" and @#{attr}='#{value}']) end |
#string_attr_include(class_name, attr, value) ⇒ Object
240 241 242 |
# File 'lib/appium_lib/ios/helper.rb', line 240 def string_attr_include(class_name, attr, value) %(//#{class_name}[@visible="true" and contains(translate(@#{attr},'#{value.upcase}', '#{value}'), '#{value}')]) end |
#string_visible_contains(element, value) ⇒ String
Returns an object that matches the first element that contains value
example: ele_by_json_visible_contains ‘UIATextField’, ‘sign in’
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/appium_lib/ios/helper.rb', line 309 def string_visible_contains(element, value) contains = { target: value, substring: true, insensitive: true } { typeArray: [element], onlyVisible: true, name: contains, label: contains, value: contains } end |
#string_visible_exact(element, value) ⇒ String
Create an object to exactly match the first element with target value
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 |
# File 'lib/appium_lib/ios/helper.rb', line 346 def string_visible_exact(element, value) exact = { target: value, substring: false, insensitive: false } { typeArray: [element], onlyVisible: true, name: exact, label: exact, value: exact } end |
#tag(class_name) ⇒ Element
Returns the first visible element matching class_name
283 284 285 286 287 288 |
# File 'lib/appium_lib/ios/helper.rb', line 283 def tag(class_name) ele_by_json( typeArray: [class_name], onlyVisible: true ) end |
#tags(class_name) ⇒ Element
Returns all visible elements matching class_name
294 295 296 297 298 299 |
# File 'lib/appium_lib/ios/helper.rb', line 294 def (class_name) eles_by_json( typeArray: [class_name], onlyVisible: true ) end |
#text(value) ⇒ UIAStaticText
Find the first UIAStaticText that contains value or by index. If int then the UIAStaticText at that index is returned.
10 11 12 13 |
# File 'lib/appium_lib/ios/element/text.rb', line 10 def text(value) return ele_index UIAStaticText, value if value.is_a? Numeric ele_by_json_visible_contains UIAStaticText, value end |
#text_exact(value) ⇒ UIAStaticText
Find the first UIAStaticText that exactly matches value.
39 40 41 |
# File 'lib/appium_lib/ios/element/text.rb', line 39 def text_exact(value) ele_by_json_visible_exact UIAStaticText, value end |
#textfield(value) ⇒ TextField
Find the first TextField that contains value or by index. If int then the TextField at that index is returned.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/appium_lib/ios/element/textfield.rb', line 52 def textfield(value) # Don't use ele_index because that only works on one element type. # iOS needs to combine textfield and secure to match Android. if value.is_a? Numeric index = value fail "#{index} is not a valid index. Must be >= 1" if index <= 0 index -= 1 # eles_by_json is 0 indexed. result = eles_by_json(_textfield_visible)[index] fail _no_such_element if result.nil? return result end ele_by_json _textfield_contains_string value end |
#textfield_exact(value) ⇒ TextField
Find the first TextField that exactly matches value.
94 95 96 |
# File 'lib/appium_lib/ios/element/textfield.rb', line 94 def textfield_exact(value) ele_by_json _textfield_exact_string value end |
#textfields(value = false) ⇒ Array<TextField>
Find all TextFields containing value. If value is omitted, all TextFields are returned.
72 73 74 75 |
# File 'lib/appium_lib/ios/element/textfield.rb', line 72 def textfields(value = false) return eles_by_json _textfield_visible unless value eles_by_json _textfield_contains_string value end |
#textfields_exact(value) ⇒ Array<TextField>
Find all TextFields that exactly match value.
101 102 103 |
# File 'lib/appium_lib/ios/element/textfield.rb', line 101 def textfields_exact(value) eles_by_json _textfield_exact_string value end |
#texts(value = false) ⇒ Array<UIAStaticText>
Find all UIAStaticText containing value. If value is omitted, all UIAStaticTexts are returned
19 20 21 22 |
# File 'lib/appium_lib/ios/element/text.rb', line 19 def texts(value = false) return UIAStaticText unless value eles_by_json_visible_contains UIAStaticText, value end |
#texts_exact(value) ⇒ Array<UIAStaticText>
Find all UIAStaticTexts that exactly match value.
46 47 48 |
# File 'lib/appium_lib/ios/element/text.rb', line 46 def texts_exact(value) eles_by_json_visible_exact UIAStaticText, value end |