Skip to content

use xpath instead of uiselectors #544

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions android_tests/lib/android/specs/common/device.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
end

t 'get_performance_data_types' do
expected = %w(cpuinfo batteryinfo networkinfo memoryinfo)
get_performance_data_types.must_equal expected
expected = %w(batteryinfo cpuinfo memoryinfo networkinfo)
get_performance_data_types.sort.must_equal expected

get_performance_data(package_name: 'io.appium.android.apis',
data_type: 'cpuinfo').must_equal [%w(user kernel), %w(0 0)]
Expand Down
2 changes: 1 addition & 1 deletion android_tests/lib/android/specs/common/patch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
set_wait 30
end
value = value.split("\n").first.strip
exp = 'No element found'
exp = 'An element could not be located on the page using the given search parameters.'
value.must_equal exp
end

Expand Down
52 changes: 18 additions & 34 deletions lib/appium_lib/android/element/button.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,20 @@ module Android
private

# @private
def _button_visible_selectors(opts = {})
button_index = opts.fetch :button_index, false
image_button_index = opts.fetch :image_button_index, false

if button_index && image_button_index
"new UiSelector().className(#{Button}).instance(#{button_index});" \
"new UiSelector().className(#{ImageButton}).instance(#{image_button_index});"
else
"new UiSelector().className(#{Button});" \
"new UiSelector().className(#{ImageButton});"
end
def _button_visible_selectors
"//#{Button}|#{ImageButton}"
end

# @private
def _button_exact_string(value)
button = string_visible_exact Button, value
image_button = string_visible_exact ImageButton, value
button + image_button
string_visible_exact(Button, value) +
string_visible_exact(ImageButton, value).sub(/\A\/\//, '|')
end

# @private
def _button_contains_string(value)
button = string_visible_contains Button, value
image_button = string_visible_contains ImageButton, value
button + image_button
string_visible_contains(Button, value) +
string_visible_contains(ImageButton, value).sub(/\A\/\//, '|')
end

public
Expand All @@ -47,54 +36,49 @@ def button(value)
index = value
raise "#{index} is not a valid index. Must be >= 1" if index <= 0

return find_element :uiautomator, _button_visible_selectors(index: index)
result = find_elements(:xpath, _button_visible_selectors)[value - 1]
raise Selenium::WebDriver::Error::NoSuchElementError unless result
return result
end

find_element :uiautomator, _button_contains_string(value)
find_element :xpath, _button_contains_string(value)
end

# Find all buttons containing value.
# If value is omitted, all buttons are returned.
# @param value [String] the value to search for
# @return [Array<Button>]
def buttons(value = false)
return find_elements :uiautomator, _button_visible_selectors unless value
find_elements :uiautomator, _button_contains_string(value)
return find_elements :xpath, _button_visible_selectors unless value
find_elements :xpath, _button_contains_string(value)
end

# Find the first button.
# @return [Button]
def first_button
find_element :uiautomator, _button_visible_selectors(button_index: 0, image_button_index: 0)
find_element :xpath, _button_visible_selectors
end

# Find the last button.
# @return [Button]
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 > 0
image_button_index = tags(ImageButton).length
image_button_index -= 1 if image_button_index > 0

find_element :uiautomator,
_button_visible_selectors(button_index: button_index,
image_button_index: image_button_index)
result = find_elements(:xpath, _button_visible_selectors).last
raise Selenium::WebDriver::Error::NoSuchElementError unless result
result
end

# Find the first button that exactly matches value.
# @param value [String] the value to match exactly
# @return [Button]
def button_exact(value)
find_element :uiautomator, _button_exact_string(value)
find_element :xpath, _button_exact_string(value)
end

# Find all buttons that exactly match value.
# @param value [String] the value to match exactly
# @return [Array<Button>]
def buttons_exact(value)
find_elements :uiautomator, _button_exact_string(value)
find_elements :xpath, _button_exact_string(value)
end
end # module Android
end # module Appium
34 changes: 12 additions & 22 deletions lib/appium_lib/android/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -286,35 +286,31 @@ def resource_id(string, on_match)
# @param value [String] the value to search for
# @return [String]
def string_visible_contains(class_name, value)
value = %("#{value}")
r_id = resource_id(value, " or @resource-id='#{value}'")

if class_name == '*'
return (resource_id(value, "new UiSelector().resourceId(#{value});") +
"new UiSelector().descriptionContains(#{value});" \
"new UiSelector().textContains(#{value});")
return "//*[contains(translate(@text,'#{value.upcase}', '#{value}'), '#{value}')" \
" or contains(translate(@content-desc,'#{value.upcase}', '#{value}'), '#{value}')" + r_id + ']'
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});"
"//#{class_name}[contains(translate(@text,'#{value.upcase}', '#{value}'), '#{value}')" \
" or contains(translate(@content-desc,'#{value.upcase}', '#{value}'), '#{value}')" + r_id + ']'
end

# Find the first element that contains value
# @param element [String] the class name for the element
# @param value [String] the value to search for
# @return [Element]
def complex_find_contains(element, value)
find_element :uiautomator, string_visible_contains(element, value)
find_element :xpath, string_visible_contains(element, value)
end

# Find all elements containing value
# @param element [String] the class name for the element
# @param value [String] the value to search for
# @return [Array<Element>]
def complex_finds_contains(element, value)
find_elements :uiautomator, string_visible_contains(element, value)
find_elements :xpath, string_visible_contains(element, value)
end

# @private
Expand All @@ -323,35 +319,29 @@ def complex_finds_contains(element, value)
# @param value [String] the value to search for
# @return [String]
def string_visible_exact(class_name, value)
value = %("#{value}")
r_id = resource_id(value, " or @resource-id='#{value}'")

if class_name == '*'
return (resource_id(value, "new UiSelector().resourceId(#{value});") +
"new UiSelector().description(#{value});" \
"new UiSelector().text(#{value});")
return "//*[@text='#{value}' or @content-desc='#{value}'" + r_id + ']'
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});"
"//#{class_name}[@text='#{value}' or @content-desc='#{value}'" + r_id + ']'
end

# Find the first element exactly matching value
# @param class_name [String] the class name for the element
# @param value [String] the value to search for
# @return [Element]
def complex_find_exact(class_name, value)
find_element :uiautomator, string_visible_exact(class_name, value)
find_element :xpath, string_visible_exact(class_name, value)
end

# Find all elements exactly matching value
# @param class_name [String] the class name for the element
# @param value [String] the value to search for
# @return [Element]
def complex_finds_exact(class_name, value)
find_elements :uiautomator, string_visible_exact(class_name, value)
find_elements :xpath, string_visible_exact(class_name, value)
end

# Returns XML string for the current page
Expand Down