Skip to content

Commit d721297

Browse files
authoredApr 18, 2017
separate find_element/s for uiautomator and xpath (#547)
* separate find_element/s for uiautomator and xpath * fix button methods * check uiautomator2 for button methods * fix rubocop * add somments
1 parent 9492690 commit d721297

File tree

3 files changed

+154
-24
lines changed

3 files changed

+154
-24
lines changed
 

‎lib/appium_lib/android/element/button.rb

+82-16
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,47 @@ module Android
77
private
88

99
# @private
10-
def _button_visible_selectors
10+
def _button_visible_selectors_xpath
1111
"//#{Button}|#{ImageButton}"
1212
end
1313

14+
def _button_visible_selectors(opts = {})
15+
button_index = opts.fetch :button_index, false
16+
image_button_index = opts.fetch :image_button_index, false
17+
18+
if button_index && image_button_index
19+
"new UiSelector().className(#{Button}).instance(#{button_index});" \
20+
"new UiSelector().className(#{ImageButton}).instance(#{image_button_index});"
21+
else
22+
"new UiSelector().className(#{Button});" \
23+
"new UiSelector().className(#{ImageButton});"
24+
end
25+
end
26+
1427
# @private
28+
# For automationName is uiautomator2
29+
def _button_exact_string_xpath(value)
30+
string_visible_exact_xpath(Button, value) +
31+
string_visible_exact_xpath(ImageButton, value).sub(/\A\/\//, '|')
32+
end
33+
1534
def _button_exact_string(value)
16-
string_visible_exact(Button, value) +
17-
string_visible_exact(ImageButton, value).sub(/\A\/\//, '|')
35+
button = string_visible_exact Button, value
36+
image_button = string_visible_exact ImageButton, value
37+
button + image_button
1838
end
1939

2040
# @private
41+
# For automationName is uiautomator2
42+
def _button_contains_string_xpath(value)
43+
string_visible_contains_xpath(Button, value) +
44+
string_visible_contains_xpath(ImageButton, value).sub(/\A\/\//, '|')
45+
end
46+
2147
def _button_contains_string(value)
22-
string_visible_contains(Button, value) +
23-
string_visible_contains(ImageButton, value).sub(/\A\/\//, '|')
48+
button = string_visible_contains Button, value
49+
image_button = string_visible_contains ImageButton, value
50+
button + image_button
2451
end
2552

2653
public
@@ -36,49 +63,88 @@ def button(value)
3663
index = value
3764
raise "#{index} is not a valid index. Must be >= 1" if index <= 0
3865

39-
result = find_elements(:xpath, _button_visible_selectors)[value - 1]
40-
raise Selenium::WebDriver::Error::NoSuchElementError unless result
66+
if automation_name_is_uiautomator2?
67+
result = find_elements(:xpath, _button_visible_selectors_xpath)[value - 1]
68+
raise Selenium::WebDriver::Error::NoSuchElementError unless result
69+
else
70+
result = find_element :uiautomator, _button_visible_selectors(index: index)
71+
end
72+
4173
return result
4274
end
4375

44-
find_element :xpath, _button_contains_string(value)
76+
if automation_name_is_uiautomator2?
77+
find_element :xpath, _button_contains_string_xpath(value)
78+
else
79+
find_element :uiautomator, _button_contains_string(value)
80+
end
4581
end
4682

4783
# Find all buttons containing value.
4884
# If value is omitted, all buttons are returned.
4985
# @param value [String] the value to search for
5086
# @return [Array<Button>]
5187
def buttons(value = false)
52-
return find_elements :xpath, _button_visible_selectors unless value
53-
find_elements :xpath, _button_contains_string(value)
88+
if automation_name_is_uiautomator2?
89+
return find_elements :xpath, _button_visible_selectors_xpath unless value
90+
find_elements :xpath, _button_contains_string_xpath(value)
91+
else
92+
return find_elements :uiautomator, _button_visible_selectors unless value
93+
find_elements :uiautomator, _button_contains_string(value)
94+
end
5495
end
5596

5697
# Find the first button.
5798
# @return [Button]
5899
def first_button
59-
find_element :xpath, _button_visible_selectors
100+
if automation_name_is_uiautomator2?
101+
find_element :xpath, _button_visible_selectors_xpath
102+
else
103+
find_element :uiautomator, _button_visible_selectors(button_index: 0, image_button_index: 0)
104+
end
60105
end
61106

62107
# Find the last button.
63108
# @return [Button]
64109
def last_button
65-
result = find_elements(:xpath, _button_visible_selectors).last
66-
raise Selenium::WebDriver::Error::NoSuchElementError unless result
67-
result
110+
if automation_name_is_uiautomator2?
111+
result = find_elements(:xpath, _button_visible_selectors_xpath).last
112+
raise Selenium::WebDriver::Error::NoSuchElementError unless result
113+
result
114+
else
115+
# uiautomator index doesn't support last
116+
# and it's 0 indexed
117+
button_index = tags(Button).length
118+
button_index -= 1 if button_index > 0
119+
image_button_index = tags(ImageButton).length
120+
image_button_index -= 1 if image_button_index > 0
121+
122+
find_element :uiautomator,
123+
_button_visible_selectors(button_index: button_index,
124+
image_button_index: image_button_index)
125+
end
68126
end
69127

70128
# Find the first button that exactly matches value.
71129
# @param value [String] the value to match exactly
72130
# @return [Button]
73131
def button_exact(value)
74-
find_element :xpath, _button_exact_string(value)
132+
if automation_name_is_uiautomator2?
133+
find_element :xpath, _button_exact_string_xpath(value)
134+
else
135+
find_element :uiautomator, _button_exact_string(value)
136+
end
75137
end
76138

77139
# Find all buttons that exactly match value.
78140
# @param value [String] the value to match exactly
79141
# @return [Array<Button>]
80142
def buttons_exact(value)
81-
find_elements :xpath, _button_exact_string(value)
143+
if automation_name_is_uiautomator2?
144+
find_elements :xpath, _button_exact_string_xpath(value)
145+
else
146+
find_elements :uiautomator, _button_exact_string(value)
147+
end
82148
end
83149
end # module Android
84150
end # module Appium

‎lib/appium_lib/android/helper.rb

+66-8
Original file line numberDiff line numberDiff line change
@@ -279,13 +279,13 @@ def resource_id(string, on_match)
279279
end
280280

281281
# Returns a string that matches the first element that contains value
282-
#
283-
# example: complex_find_contains 'UIATextField', 'sign in'
282+
# For automationName is uiautomator2
283+
# example: string_visible_contains_xpath 'UIATextField', 'sign in'
284284
#
285285
# @param class_name [String] the class name for the element
286286
# @param value [String] the value to search for
287287
# @return [String]
288-
def string_visible_contains(class_name, value)
288+
def string_visible_contains_xpath(class_name, value)
289289
r_id = resource_id(value, " or @resource-id='#{value}'")
290290

291291
if class_name == '*'
@@ -297,28 +297,58 @@ def string_visible_contains(class_name, value)
297297
" or contains(translate(@content-desc,'#{value.upcase}', '#{value}'), '#{value}')" + r_id + ']'
298298
end
299299

300+
# Returns a string that matches the first element that contains value
301+
# For automationName is Appium
302+
# example: string_visible_contains 'UIATextField', 'sign in'
303+
#
304+
# @param class_name [String] the class name for the element
305+
# @param value [String] the value to search for
306+
# @return [String]
307+
def string_visible_contains(class_name, value)
308+
value = %("#{value}")
309+
if class_name == '*'
310+
return (resource_id(value, "new UiSelector().resourceId(#{value});") +
311+
"new UiSelector().descriptionContains(#{value});" \
312+
"new UiSelector().textContains(#{value});")
313+
end
314+
315+
class_name = %("#{class_name}")
316+
resource_id(value, "new UiSelector().className(#{class_name}).resourceId(#{value});") +
317+
"new UiSelector().className(#{class_name}).descriptionContains(#{value});" \
318+
"new UiSelector().className(#{class_name}).textContains(#{value});"
319+
end
320+
300321
# Find the first element that contains value
301322
# @param element [String] the class name for the element
302323
# @param value [String] the value to search for
303324
# @return [Element]
304325
def complex_find_contains(element, value)
305-
find_element :xpath, string_visible_contains(element, value)
326+
if automation_name_is_uiautomator2?
327+
find_element :xpath, string_visible_contains_xpath(element, value)
328+
else
329+
find_element :uiautomator, string_visible_contains(element, value)
330+
end
306331
end
307332

308333
# Find all elements containing value
309334
# @param element [String] the class name for the element
310335
# @param value [String] the value to search for
311336
# @return [Array<Element>]
312337
def complex_finds_contains(element, value)
313-
find_elements :xpath, string_visible_contains(element, value)
338+
if automation_name_is_uiautomator2?
339+
find_elements :xpath, string_visible_contains_xpath(element, value)
340+
else
341+
find_elements :uiautomator, string_visible_contains(element, value)
342+
end
314343
end
315344

316345
# @private
317346
# Create an string to exactly match the first element with target value
347+
# For automationName is uiautomator2
318348
# @param class_name [String] the class name for the element
319349
# @param value [String] the value to search for
320350
# @return [String]
321-
def string_visible_exact(class_name, value)
351+
def string_visible_exact_xpath(class_name, value)
322352
r_id = resource_id(value, " or @resource-id='#{value}'")
323353

324354
if class_name == '*'
@@ -328,20 +358,48 @@ def string_visible_exact(class_name, value)
328358
"//#{class_name}[@text='#{value}' or @content-desc='#{value}'" + r_id + ']'
329359
end
330360

361+
# @private
362+
# Create an string to exactly match the first element with target value
363+
# @param class_name [String] the class name for the element
364+
# @param value [String] the value to search for
365+
# @return [String]
366+
def string_visible_exact(class_name, value)
367+
value = %("#{value}")
368+
369+
if class_name == '*'
370+
return (resource_id(value, "new UiSelector().resourceId(#{value});") +
371+
"new UiSelector().description(#{value});" \
372+
"new UiSelector().text(#{value});")
373+
end
374+
375+
class_name = %("#{class_name}")
376+
resource_id(value, "new UiSelector().className(#{class_name}).resourceId(#{value});") +
377+
"new UiSelector().className(#{class_name}).description(#{value});" \
378+
"new UiSelector().className(#{class_name}).text(#{value});"
379+
end
380+
331381
# Find the first element exactly matching value
332382
# @param class_name [String] the class name for the element
333383
# @param value [String] the value to search for
334384
# @return [Element]
335385
def complex_find_exact(class_name, value)
336-
find_element :xpath, string_visible_exact(class_name, value)
386+
if automation_name_is_uiautomator2?
387+
find_element :xpath, string_visible_exact_xpath(class_name, value)
388+
else
389+
find_element :uiautomator, string_visible_exact(class_name, value)
390+
end
337391
end
338392

339393
# Find all elements exactly matching value
340394
# @param class_name [String] the class name for the element
341395
# @param value [String] the value to search for
342396
# @return [Element]
343397
def complex_finds_exact(class_name, value)
344-
find_elements :xpath, string_visible_exact(class_name, value)
398+
if automation_name_is_uiautomator2?
399+
find_elements :xpath, string_visible_exact_xpath(class_name, value)
400+
else
401+
find_elements :uiautomator, string_visible_exact(class_name, value)
402+
end
345403
end
346404

347405
# Returns XML string for the current page

‎lib/appium_lib/driver.rb

+6
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,12 @@ def automation_name_is_xcuitest?
474474
!@automation_name.nil? && 'xcuitest'.casecmp(@automation_name).zero?
475475
end
476476

477+
# Return true if automationName is 'uiautomator2'
478+
# @return [Boolean]
479+
def automation_name_is_uiautomator2?
480+
!@automation_name.nil? && 'uiautomator2'.casecmp(@automation_name).zero?
481+
end
482+
477483
# Return true if the target Appium server is over REQUIRED_VERSION_XCUITEST.
478484
# If the Appium server is under REQUIRED_VERSION_XCUITEST, then error is raised.
479485
# @return [Boolean]

0 commit comments

Comments
 (0)
Please sign in to comment.