Module: Appium::Android

Defined in:
lib/appium_lib/android/android.rb,
lib/appium_lib/android/espresso.rb,
lib/appium_lib/android/element/text.rb,
lib/appium_lib/android/uiautomator2.rb,
lib/appium_lib/android/common/helper.rb,
lib/appium_lib/android/element/alert.rb,
lib/appium_lib/android/element/button.rb,
lib/appium_lib/android/element/generic.rb,
lib/appium_lib/android/espresso/bridge.rb,
lib/appium_lib/android/espresso/helper.rb,
lib/appium_lib/android/espresso/element.rb,
lib/appium_lib/android/element/textfield.rb,
lib/appium_lib/android/uiautomator2/bridge.rb,
lib/appium_lib/android/uiautomator2/helper.rb,
lib/appium_lib/android/uiautomator2/element.rb,
lib/appium_lib/android/common/command/command.rb,
lib/appium_lib/android/espresso/element/button.rb,
lib/appium_lib/android/espresso/element/generic.rb,
lib/appium_lib/android/uiautomator2/element/button.rb

Defined Under Namespace

Modules: Command, Espresso, Uiautomator2 Classes: AndroidElements, Bridge

Constant Summary collapse

TEXT_VIEW =
'android.widget.TextView'
TextView =
TEXT_VIEW
BUTTON =
'android.widget.Button'
Button =

backward compatibility

BUTTON
IMAGE_BUTTON =
'android.widget.ImageButton'
ImageButton =

backward compatibility

IMAGE_BUTTON
EDIT_TEXT =
'android.widget.EditText'
EditText =
EDIT_TEXT

Instance Method Summary collapse

Instance Method Details

#alert_acceptvoid

This method returns an undefined value.

Accept the alert. The last button is considered “accept.”



27
28
29
# File 'lib/appium_lib/android/element/alert.rb', line 27

def alert_accept
  last_button.click
end

#alert_accept_textString

Get the text of the alert’s accept button. The last button is considered “accept.”

Returns:

  • (String)


34
35
36
# File 'lib/appium_lib/android/element/alert.rb', line 34

def alert_accept_text
  last_button.text
end

#alert_click(value) ⇒ void

This method returns an undefined value.

Click the first alert button that contains value or by index.

Parameters:

  • value (Integer, String)

    either an integer index of the button or the button’s name



20
21
22
# File 'lib/appium_lib/android/element/alert.rb', line 20

def alert_click(value)
  button(value).click
end

#alert_dismissvoid

This method returns an undefined value.

Dismiss the alert. The first button is considered “dismiss.”



41
42
43
# File 'lib/appium_lib/android/element/alert.rb', line 41

def alert_dismiss
  first_button.click
end

#alert_dismiss_textString

Get the text of the alert’s dismiss button. The first button is considered “dismiss.”

Returns:

  • (String)


48
49
50
# File 'lib/appium_lib/android/element/alert.rb', line 48

def alert_dismiss_text
  first_button.text
end

#button(value) ⇒ BUTTON

Find the first button that contains value or by index. If int then the button at that index is returned.

Parameters:

  • value (String, Integer)

    the value to exactly match.

Returns:



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/appium_lib/android/element/button.rb', line 27

def button(value)
  # Don't use ele_index because that only works on one element type.
  # Android needs to combine button and image button to match iOS.
  if value.is_a? Numeric
    index = value
    raise ArgumentError, "#{index} is not a valid index. Must be >= 1" if index <= 0

    # 1 indexed
    return find_element :uiautomator, _button_visible_selectors(index: index)
  end

  find_element :uiautomator, _button_contains_string(value)
end

#button_exact(value) ⇒ BUTTON

Find the first button that exactly matches value.

Parameters:

  • value (String)

    the value to match exactly

Returns:



75
76
77
# File 'lib/appium_lib/android/element/button.rb', line 75

def button_exact(value)
  find_element :uiautomator, _button_exact_string(value)
end

#buttons(value = false) ⇒ Array<BUTTON>

Find all buttons containing value. If value is omitted, all buttons are returned.

Parameters:

  • value (String) (defaults to: false)

    the value to search for

Returns:



45
46
47
48
49
# File 'lib/appium_lib/android/element/button.rb', line 45

def buttons(value = false)
  return find_elements :uiautomator, _button_visible_selectors unless value

  find_elements :uiautomator, _button_contains_string(value)
end

#buttons_exact(value) ⇒ Array<BUTTON>

Find all buttons that exactly match value.

Parameters:

  • value (String)

    the value to match exactly

Returns:



82
83
84
# File 'lib/appium_lib/android/element/button.rb', line 82

def buttons_exact(value)
  find_elements :uiautomator, _button_exact_string(value)
end

#complex_find_contains(class_name, value) ⇒ Element

Find the first element that contains value

Parameters:

  • class_name (String)

    the class name for the element

  • value (String)

    the value to search for

Returns:

  • (Element)


270
271
272
# File 'lib/appium_lib/android/common/helper.rb', line 270

def complex_find_contains(class_name, value)
  find_element :uiautomator, string_visible_contains(class_name, value)
end

#complex_find_exact(class_name, value) ⇒ Element

Find the first element exactly matching value

Parameters:

  • class_name (String)

    the class name for the element

  • value (String)

    the value to search for

Returns:

  • (Element)


320
321
322
# File 'lib/appium_lib/android/common/helper.rb', line 320

def complex_find_exact(class_name, value)
  find_element :uiautomator, string_visible_exact(class_name, value)
end

#complex_finds_contains(class_name, value) ⇒ Array<Element>

Find all elements containing value

Parameters:

  • class_name (String)

    the class name for the element

  • value (String)

    the value to search for

Returns:

  • (Array<Element>)


278
279
280
# File 'lib/appium_lib/android/common/helper.rb', line 278

def complex_finds_contains(class_name, value)
  find_elements :uiautomator, string_visible_contains(class_name, value)
end

#complex_finds_exact(class_name, value) ⇒ Element

Find all elements exactly matching value

Parameters:

  • class_name (String)

    the class name for the element

  • value (String)

    the value to search for

Returns:

  • (Element)


328
329
330
# File 'lib/appium_lib/android/common/helper.rb', line 328

def complex_finds_exact(class_name, value)
  find_elements :uiautomator, string_visible_exact(class_name, value)
end

#ele_index(class_name, index) ⇒ Element

Find the element of type class_name at matching index.

Parameters:

  • class_name (String)

    the class name to find

  • index (Integer)

    the index

Returns:

  • (Element)

    the found element of type class_name



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/appium_lib/android/common/helper.rb', line 147

def ele_index(class_name, index)
  results = tags(class_name)
  if index == 'last()'
    index = results.length
    index -= 1 if index >= 0
  else
    raise ArgumentError, 'Index must be >= 1' unless index >= 1

    index -= 1 if index >= 1
  end

  # uiautomator has issues with index/instance so calculate the index
  # client side.
  results[index]
end

#find(value) ⇒ Element

Find the first element containing value

Parameters:

  • value (String)

    the value to search for

Returns:

  • (Element)


20
21
22
# File 'lib/appium_lib/android/element/generic.rb', line 20

def find(value)
  complex_find_contains '*', value
end

#find_exact(value) ⇒ Element

Find the first element exactly matching value

Parameters:

  • value (String)

    the value to search for

Returns:

  • (Element)


34
35
36
# File 'lib/appium_lib/android/element/generic.rb', line 34

def find_exact(value)
  complex_find_exact '*', value
end

#finds(value) ⇒ Array<Element>

Find all elements containing value

Parameters:

  • value (String)

    the value to search for

Returns:

  • (Array<Element>)


27
28
29
# File 'lib/appium_lib/android/element/generic.rb', line 27

def finds(value)
  complex_finds_contains '*', value
end

#finds_exact(value) ⇒ Array<Element>

Find all elements exactly matching value

Parameters:

  • value (String)

    the value to search for

Returns:

  • (Array<Element>)


41
42
43
# File 'lib/appium_lib/android/element/generic.rb', line 41

def finds_exact(value)
  complex_finds_exact '*', value
end

#first_buttonBUTTON

Find the first button.

Returns:



53
54
55
# File 'lib/appium_lib/android/element/button.rb', line 53

def first_button
  find_element :uiautomator, _button_visible_selectors(button_index: 0, image_button_index: 0)
end

#first_ele(class_name) ⇒ Element

Find the first element that matches class_name

Parameters:

  • class_name (String)

    the tag to match

Returns:

  • (Element)


166
167
168
# File 'lib/appium_lib/android/common/helper.rb', line 166

def first_ele(class_name)
  tag(class_name)
end

#first_textTEXT_VIEW

Find the first TextView.

Returns:



43
44
45
# File 'lib/appium_lib/android/element/text.rb', line 43

def first_text
  first_ele TEXT_VIEW
end

#first_textfieldEDIT_TEXT

Find the first EditText.

Returns:



42
43
44
# File 'lib/appium_lib/android/element/textfield.rb', line 42

def first_textfield
  first_ele EDIT_TEXT
end

#get_android_inspect(class_name = false) ⇒ String

Android only. Returns a string containing interesting elements. The text, content description, and id are returned. if false (default) then all classes will be inspected

Parameters:

  • class_name (String) (defaults to: false)

    the class name to filter on.

Returns:

  • (String)


95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/appium_lib/android/common/helper.rb', line 95

def get_android_inspect(class_name = false)
  source = get_source

  doctype_string = '<!doctyp'
  source_header  = source[0..doctype_string.length].downcase
  source_is_html = source_header.start_with?(doctype_string, '<html')

  parser = if source_is_html # parse html from webview
             @android_html_parser ||= Nokogiri::HTML::SAX::Parser.new(Appium::Common::HTMLElements.new)
           else
             @android_native_parser ||= Nokogiri::XML::SAX::Parser.new(AndroidElements.new)
           end
  parser.document.reset # ensure document is reset before parsing
  parser.document.filter = class_name
  parser.parse source
  result = parser.document.result
  parser.document.reset # clean up any created objects after parsing
  result
end

#id(id) ⇒ Element

Find the first matching element by id

Parameters:

  • id (String)

    the id to search for

Returns:

  • (Element)


130
131
132
133
# File 'lib/appium_lib/android/common/helper.rb', line 130

def id(id)
  # Android auto resolves strings.xml ids
  find_element :id, id
end

#ids(id) ⇒ Element

Find all matching elements by id

Parameters:

  • id (String)

    the id to search for

Returns:

  • (Element)


138
139
140
141
# File 'lib/appium_lib/android/common/helper.rb', line 138

def ids(id)
  # Android auto resolves strings.xml ids
  find_elements :id, id
end

#last_buttonBUTTON

Find the last button.

Returns:



59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/appium_lib/android/element/button.rb', line 59

def last_button
  # uiautomator index doesn't support last
  # and it's 0 indexed
  button_index = tags(BUTTON).length
  button_index -= 1 if button_index.positive?
  image_button_index = tags(IMAGE_BUTTON).length
  image_button_index -= 1 if image_button_index.positive?

  find_element :uiautomator,
               _button_visible_selectors(button_index: button_index,
                                         image_button_index: image_button_index)
end

#last_ele(class_name) ⇒ Element

Find the last element that matches class_name

Parameters:

  • class_name (String)

    the tag to match

Returns:

  • (Element)


173
174
175
# File 'lib/appium_lib/android/common/helper.rb', line 173

def last_ele(class_name)
  ele_index class_name, 'last()'
end

#last_textTEXT_VIEW

Find the last TextView.

Returns:



49
50
51
# File 'lib/appium_lib/android/element/text.rb', line 49

def last_text
  last_ele TEXT_VIEW
end

#last_textfieldEDIT_TEXT

Find the last EditText.

Returns:



48
49
50
# File 'lib/appium_lib/android/element/textfield.rb', line 48

def last_textfield
  last_ele EDIT_TEXT
end

#page(opts = {}) ⇒ void

This method returns an undefined value.

Intended for use with console. Inspects and prints the current page. Will return XHTML for Web contexts because of a quirk with Nokogiri. if nil (default) then all classes will be inspected

Parameters:

  • class (Hash)

    a customizable set of options



121
122
123
124
125
# File 'lib/appium_lib/android/common/helper.rb', line 121

def page(opts = {})
  class_name = opts.is_a?(Hash) ? opts.fetch(:class, nil) : opts
  puts get_android_inspect class_name
  nil
end

#resource_id(string, on_match) ⇒ String

Detects if the string represents a resourceId resourceId is only supported on API >= 18 devices

Parameters:

  • string (String)

    the string check for a resourceId value will be auto unquoted

  • on_match (String)

    the string to return on resourceId match

Returns:

  • (String)

    empty string on failure, on_match on successful match



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/appium_lib/android/common/helper.rb', line 202

def resource_id(string, on_match)
  return '' unless string

  # unquote the string
  # "com.example.Test:id/enter" -> com.example.Test:id/enter
  unquote = string.match(/"(.+)"/)
  string = unquote[1] if unquote

  # java_package : type / name
  #
  # com.example.Test:id/enter
  #
  # ^[a-zA-Z_]      - Java package must start with letter or underscore
  # [a-zA-Z0-9\._]* - Java package may contain letters, numbers, periods and underscores
  # :               - : ends the package and starts the type
  # [^\/]+          - type is made up of at least one non-/ characters
  # \\/             - / ends the type and starts the name
  # [\S]+$          - the name contains at least one non-space character and then the line is ended
  resource_id = /^[a-zA-Z_][a-zA-Z0-9._]*:[^\/]+\/\S+$/
  string.match(resource_id) ? on_match : ''
end

#scroll_to(text, scrollable_index = 0) ⇒ Element

Scroll to the first element containing target text or description.

Parameters:

  • text (String)

    the text or resourceId to search for in the text value and content description

  • scrollable_index (Integer) (defaults to: 0)

    the index for scrollable views.

Returns:

  • (Element)

    the element scrolled to



54
55
56
57
58
59
60
61
62
63
64
# File 'lib/appium_lib/android/element/generic.rb', line 54

def scroll_to(text, scrollable_index = 0)
  text = %("#{text}")
  rid  = resource_id(text, "new UiSelector().resourceId(#{text})")
  args = rid.empty? ? ["new UiSelector().textContains(#{text})", "new UiSelector().descriptionContains(#{text})"] : [rid]
  args.each_with_index do |arg, index|
    elem = find_element :uiautomator, scroll_uiselector(arg, scrollable_index)
    return elem
  rescue StandardError => e
    raise e if index == args.size - 1
  end
end

#scroll_to_exact(text, scrollable_index = 0) ⇒ Element

Scroll to the first element with the exact target text or description.

Parameters:

  • text (String)

    the text or resourceId to search for in the text value and content description

  • scrollable_index (Integer) (defaults to: 0)

    the index for scrollable views.

Returns:

  • (Element)

    the element scrolled to



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/appium_lib/android/element/generic.rb', line 70

def scroll_to_exact(text, scrollable_index = 0)
  text = %("#{text}")
  rid  = resource_id(text, "new UiSelector().resourceId(#{text})")
  args = rid.empty? ? ["new UiSelector().text(#{text})", "new UiSelector().description(#{text})"] : [rid]
  args.each_with_index do |arg, index|
    elem = find_element :uiautomator, scroll_uiselector(arg, scrollable_index)
    return elem
  rescue StandardError => e
    raise e if index == args.size - 1
  end
end

#scroll_uiselector(content, index = 0) ⇒ Object



46
47
48
# File 'lib/appium_lib/android/element/generic.rb', line 46

def scroll_uiselector(content, index = 0)
  "new UiScrollable(new UiSelector().scrollable(true).instance(#{index})).scrollIntoView(#{content}.instance(0));"
end

#string_visible_contains(class_name, value) ⇒ String

Returns a string that matches the first element that contains value For automationName is Appium example: string_visible_contains ‘UIATextField’, ‘sign in’ note for XPath: github.com/appium/ruby_lib/pull/561

Parameters:

  • class_name (String)

    the class name for the element

  • value (String)

    the value to search for

Returns:

  • (String)


252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/appium_lib/android/common/helper.rb', line 252

def string_visible_contains(class_name, value)
  value = %("#{value}")
  if class_name == '*'
    return (resource_id(value, "new UiSelector().resourceId(#{value});") +
      "new UiSelector().descriptionContains(#{value});" \
      "new UiSelector().textContains(#{value});")
  end

  class_name = %("#{class_name}")
  resource_id(value, "new UiSelector().className(#{class_name}).resourceId(#{value});") +
    "new UiSelector().className(#{class_name}).descriptionContains(#{value});" \
    "new UiSelector().className(#{class_name}).textContains(#{value});"
end

#string_visible_contains_xpath(class_name, value) ⇒ String

Returns a string that matches the first element that contains value For automationName is uiautomator2 example: string_visible_contains_xpath ‘UIATextField’, ‘sign in’ note for XPath: github.com/appium/ruby_lib/pull/561

Parameters:

  • class_name (String)

    the class name for the element

  • value (String)

    the value to search for

Returns:

  • (String)


232
233
234
235
236
237
238
239
240
241
242
# File 'lib/appium_lib/android/common/helper.rb', line 232

def string_visible_contains_xpath(class_name, value)
  r_id = resource_id(value, " or @resource-id='#{value}'")

  if class_name == '*'
    return "//*[contains(translate(@text,'#{value.upcase}', '#{value}'), '#{value}') " \
           "or contains(translate(@content-desc,'#{value.upcase}', '#{value}'), '#{value}')" + r_id + ']'
  end

  "//#{class_name}[contains(translate(@text,'#{value.upcase}', '#{value}'), '#{value}') " \
  "or contains(translate(@content-desc,'#{value.upcase}', '#{value}'), '#{value}')" + r_id + ']'
end

#string_visible_exact(class_name, value) ⇒ String

Create an string to exactly match the first element with target value

Parameters:

  • class_name (String)

    the class name for the element

  • value (String)

    the value to search for

Returns:

  • (String)


301
302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/appium_lib/android/common/helper.rb', line 301

def string_visible_exact(class_name, value)
  value = %("#{value}")

  if class_name == '*'
    return (resource_id(value, "new UiSelector().resourceId(#{value});") +
      "new UiSelector().description(#{value});" \
      "new UiSelector().text(#{value});")
  end

  class_name = %("#{class_name}")
  resource_id(value, "new UiSelector().className(#{class_name}).resourceId(#{value});") +
    "new UiSelector().className(#{class_name}).description(#{value});" \
    "new UiSelector().className(#{class_name}).text(#{value});"
end

#string_visible_exact_xpath(class_name, value) ⇒ String

Create an string to exactly match the first element with target value For automationName is uiautomator2

Parameters:

  • class_name (String)

    the class name for the element

  • value (String)

    the value to search for

Returns:

  • (String)


288
289
290
291
292
293
294
# File 'lib/appium_lib/android/common/helper.rb', line 288

def string_visible_exact_xpath(class_name, value)
  r_id = resource_id(value, " or @resource-id='#{value}'")

  return "//*[@text='#{value}' or @content-desc='#{value}'" + r_id + ']' if class_name == '*'

  "//#{class_name}[@text='#{value}' or @content-desc='#{value}'" + r_id + ']'
end

#tag(class_name) ⇒ Element

Find the first element of type class_name

Parameters:

  • class_name (String)

    the class_name to search for

Returns:

  • (Element)


181
182
183
# File 'lib/appium_lib/android/common/helper.rb', line 181

def tag(class_name)
  find_element :class, class_name
end

#tags(class_name) ⇒ Element

Find all elements of type class_name

Parameters:

  • class_name (String)

    the class_name to search for

Returns:

  • (Element)


189
190
191
# File 'lib/appium_lib/android/common/helper.rb', line 189

def tags(class_name)
  find_elements :class, class_name
end

#text(value) ⇒ TextView

Find the first TextView that contains value or by index. If int then the TextView at that index is returned.

Parameters:

  • value (String, Integer)

    the value to find.

Returns:



25
26
27
28
29
# File 'lib/appium_lib/android/element/text.rb', line 25

def text(value)
  return ele_index TEXT_VIEW, value if value.is_a? Numeric

  complex_find_contains TEXT_VIEW, value
end

#text_exact(value) ⇒ TEXT_VIEW

Find the first TextView that exactly matches value.

Parameters:

  • value (String)

    the value to match exactly

Returns:



56
57
58
# File 'lib/appium_lib/android/element/text.rb', line 56

def text_exact(value)
  complex_find_exact TEXT_VIEW, value
end

#textfield(value) ⇒ EDIT_TEXT

Find the first EditText that contains value or by index. If int then the EditText at that index is returned.

Parameters:

  • value (String, Integer)

    the text to match exactly.

Returns:



24
25
26
27
28
# File 'lib/appium_lib/android/element/textfield.rb', line 24

def textfield(value)
  return ele_index EDIT_TEXT, value if value.is_a? Numeric

  complex_find_contains EDIT_TEXT, value
end

#textfield_exact(value) ⇒ EDIT_TEXT

Find the first EditText that exactly matches value.

Parameters:

  • value (String)

    the value to match exactly

Returns:



55
56
57
# File 'lib/appium_lib/android/element/textfield.rb', line 55

def textfield_exact(value)
  complex_find_exact EDIT_TEXT, value
end

#textfields(value = false) ⇒ Array<EDIT_TEXT>

Find all EditTexts containing value. If value is omitted, all EditTexts are returned.

Parameters:

  • value (String) (defaults to: false)

    the value to search for

Returns:



34
35
36
37
38
# File 'lib/appium_lib/android/element/textfield.rb', line 34

def textfields(value = false)
  return tags EDIT_TEXT unless value

  complex_finds_contains EDIT_TEXT, value
end

#textfields_exact(value) ⇒ Array<EDIT_TEXT>

Find all EditTexts that exactly match value.

Parameters:

  • value (String)

    the value to match exactly

Returns:



62
63
64
# File 'lib/appium_lib/android/element/textfield.rb', line 62

def textfields_exact(value)
  complex_finds_exact EDIT_TEXT, value
end

#texts(value = false) ⇒ Array<TEXT_VIEW>

Find all TextViews containing value. If value is omitted, all texts are returned.

Parameters:

  • value (String) (defaults to: false)

    the value to search for

Returns:



35
36
37
38
39
# File 'lib/appium_lib/android/element/text.rb', line 35

def texts(value = false)
  return tags TEXT_VIEW unless value

  complex_finds_contains TEXT_VIEW, value
end

#texts_exact(value) ⇒ Array<TEXT_VIEW>

Find all TextViews that exactly match value.

Parameters:

  • value (String)

    the value to match exactly

Returns:



63
64
65
# File 'lib/appium_lib/android/element/text.rb', line 63

def texts_exact(value)
  complex_finds_exact TEXT_VIEW, value
end