appium_lib 3.0.3 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/android_tests/Rakefile +0 -3
- data/android_tests/appium.txt +1 -0
- data/android_tests/lib/android/specs/android/element/alert.rb +9 -2
- data/android_tests/lib/android/specs/android/element/textfield.rb +5 -0
- data/android_tests/lib/android/specs/android/helper.rb +6 -15
- data/android_tests/lib/android/specs/android/patch.rb +16 -3
- data/android_tests/lib/android/specs/common/device.rb +41 -41
- data/android_tests/lib/android/specs/common/patch.rb +1 -1
- data/android_tests/lib/android/specs/common/web_context.rb +55 -7
- data/android_tests/lib/android/specs/driver.rb +4 -3
- data/android_tests/lib/android/specs/install.rb +25 -0
- data/android_tests/lib/run.rb +4 -3
- data/docs/android_docs.md +357 -187
- data/docs/docs.md +8 -28
- data/docs/ios_docs.md +341 -179
- data/docs/migration.md +6 -0
- data/ios_tests/Rakefile +0 -3
- data/ios_tests/appium.txt +1 -0
- data/ios_tests/lib/common.rb +30 -0
- data/ios_tests/lib/ios/specs/device/device.rb +6 -1
- data/ios_tests/lib/ios/specs/driver.rb +3 -3
- data/ios_tests/lib/ios/specs/ios/element/alert.rb +0 -5
- data/ios_tests/lib/ios/specs/ios/element/textfield.rb +10 -0
- data/ios_tests/lib/run.rb +4 -106
- data/lib/appium_lib.rb +2 -2
- data/lib/appium_lib/android/element/button.rb +16 -26
- data/lib/appium_lib/android/element/generic.rb +15 -12
- data/lib/appium_lib/android/helper.rb +39 -53
- data/lib/appium_lib/common/patch.rb +10 -39
- data/lib/appium_lib/common/version.rb +2 -2
- data/lib/appium_lib/device/device.rb +54 -70
- data/lib/appium_lib/driver.rb +29 -19
- data/lib/appium_lib/ios/helper.rb +50 -1
- data/lib/appium_lib/ios/patch.rb +1 -23
- data/release_notes.md +38 -0
- metadata +4 -4
- data/android_tests/lib/android/specs/android/dynamic.rb +0 -5
- data/lib/appium_lib/android/dynamic.rb +0 -47
data/docs/migration.md
CHANGED
data/ios_tests/Rakefile
CHANGED
@@ -36,9 +36,6 @@ task :ios, :args, :test_file do |args, test_file|
|
|
36
36
|
# args = android
|
37
37
|
# test_file = {:args=>"ok"}
|
38
38
|
test_file = test_file[:args]
|
39
|
-
path = File.expand_path('appium.txt', Rake.application.original_dir)
|
40
|
-
ENV['APPIUM_TXT'] = path
|
41
|
-
puts "Rake appium.txt path is: #{path}"
|
42
39
|
cmd = 'bundle exec ruby ./lib/run.rb ios'
|
43
40
|
cmd += %Q( "#{test_file}") if test_file
|
44
41
|
bash cmd
|
data/ios_tests/appium.txt
CHANGED
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
# common methods
|
3
|
+
def back_click(opts={})
|
4
|
+
opts ||= {}
|
5
|
+
search_wait = opts.fetch(:wait, 60 * 1.7)
|
6
|
+
# iOS may have multiple 'back' buttons
|
7
|
+
# select the first displayed? back button.
|
8
|
+
wait(search_wait) do
|
9
|
+
button_exact('Back').click
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def leave_textfields
|
14
|
+
back_click
|
15
|
+
screen.must_equal catalog
|
16
|
+
end
|
17
|
+
|
18
|
+
def go_to_textfields
|
19
|
+
screen.must_equal catalog
|
20
|
+
wait_true { text('textfield').click; screen == 'TextFields' } # wait for screen transition
|
21
|
+
screen.must_equal 'TextFields'
|
22
|
+
end
|
23
|
+
|
24
|
+
def screen
|
25
|
+
$driver.find_element(:class, 'UIANavigationBar').name
|
26
|
+
end
|
27
|
+
|
28
|
+
def catalog
|
29
|
+
'UICatalog'
|
30
|
+
end
|
@@ -76,8 +76,13 @@ describe 'device/device' do
|
|
76
76
|
pinch 75
|
77
77
|
end
|
78
78
|
|
79
|
-
t '
|
79
|
+
t 'pull_file' do
|
80
80
|
read_file = pull_file 'Library/AddressBook/AddressBook.sqlitedb'
|
81
81
|
read_file.start_with?('SQLite format').must_equal true
|
82
82
|
end
|
83
|
+
|
84
|
+
t 'pull_folder' do
|
85
|
+
data = pull_folder 'Library/AddressBook'
|
86
|
+
data.length.must_be :>, 1
|
87
|
+
end
|
83
88
|
end
|
@@ -21,9 +21,8 @@ describe 'driver' do
|
|
21
21
|
# skip this test if we're using Sauce
|
22
22
|
# the storage API doesn't have an on disk file
|
23
23
|
skip if is_sauce
|
24
|
-
|
25
|
-
|
26
|
-
opts = Appium.load_appium_txt file: path, verbose: true
|
24
|
+
appium_txt = File.expand_path(File.join(Dir.pwd, 'lib'))
|
25
|
+
opts = Appium.load_appium_txt file: appium_txt, verbose: true
|
27
26
|
|
28
27
|
actual = ''
|
29
28
|
actual = File.basename opts[:caps][:app] if opts && opts[:caps]
|
@@ -37,6 +36,7 @@ describe 'driver' do
|
|
37
36
|
actual = driver_attributes
|
38
37
|
actual[:caps][:app] = File.basename actual[:caps][:app]
|
39
38
|
expected = { caps: { platformName: 'ios',
|
39
|
+
deviceName: 'iPhone Simulator',
|
40
40
|
app: 'UICatalog.app' },
|
41
41
|
custom_url: false,
|
42
42
|
export_session: false,
|
@@ -29,11 +29,6 @@ describe 'ios/element/alert' do
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
# iOS 7 is not using the alert methods. alert is nil.
|
33
|
-
def ios7_alert_detected
|
34
|
-
execute_script 'UIATarget.localTarget().frontMostApp().alert().isNil()'
|
35
|
-
end
|
36
|
-
|
37
32
|
t 'alert_accept' do
|
38
33
|
alert_accept
|
39
34
|
end
|
@@ -33,6 +33,11 @@ describe 'ios/element/textfield' do
|
|
33
33
|
textfields.length.must_equal 4
|
34
34
|
end
|
35
35
|
|
36
|
+
t 'predicate textfields' do
|
37
|
+
textfield_count = execute_script(%Q(au.mainApp().getAllWithPredicate("type contains[c] 'textfield'", true))).length
|
38
|
+
textfield_count.must_equal 4
|
39
|
+
end
|
40
|
+
|
36
41
|
t 'first_textfield' do
|
37
42
|
first_textfield.text.must_equal enter_text
|
38
43
|
end
|
@@ -110,6 +115,11 @@ describe 'ios/element/textfield' do
|
|
110
115
|
textfields_exact('does not exist').length.must_equal 0
|
111
116
|
end
|
112
117
|
|
118
|
+
t 'hide_keyboard' do
|
119
|
+
first_textfield.click
|
120
|
+
hide_keyboard
|
121
|
+
end
|
122
|
+
|
113
123
|
t 'after_last' do
|
114
124
|
after_last
|
115
125
|
end
|
data/ios_tests/lib/run.rb
CHANGED
@@ -1,106 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
require_relative '../../lib/appium_lib'
|
6
|
-
|
7
|
-
=begin
|
8
|
-
Run all Android tests:
|
9
|
-
ruby run.rb android
|
10
|
-
|
11
|
-
Run only the view album test:
|
12
|
-
ruby run.rb ios view_album
|
13
|
-
=end
|
14
|
-
|
15
|
-
# Sanity check
|
16
|
-
a = OpenStruct.new x: 'ok'
|
17
|
-
raise 'x issue' unless a.x == 'ok'
|
18
|
-
|
19
|
-
# common methods
|
20
|
-
def back_click(opts={})
|
21
|
-
opts ||= {}
|
22
|
-
search_wait = opts.fetch(:wait, 60 * 1.7)
|
23
|
-
# iOS may have multiple 'back' buttons
|
24
|
-
# select the first displayed? back button.
|
25
|
-
wait(search_wait) do
|
26
|
-
button_exact('Back').click
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def leave_textfields
|
31
|
-
back_click
|
32
|
-
screen.must_equal catalog
|
33
|
-
end
|
34
|
-
|
35
|
-
def go_to_textfields
|
36
|
-
screen.must_equal catalog
|
37
|
-
wait_true { text('textfield').click; screen == 'TextFields' } # wait for screen transition
|
38
|
-
screen.must_equal 'TextFields'
|
39
|
-
end
|
40
|
-
|
41
|
-
def screen
|
42
|
-
$driver.find_element(:class, 'UIANavigationBar').name
|
43
|
-
end
|
44
|
-
|
45
|
-
def catalog
|
46
|
-
'UICatalog'
|
47
|
-
end
|
48
|
-
|
49
|
-
##
|
50
|
-
|
51
|
-
caps = Appium.load_appium_txt file: File.expand_path('..', __FILE__), verbose: true
|
52
|
-
caps = caps.merge({ appium_lib: { debug: true, wait: 30 } })
|
53
|
-
|
54
|
-
dir = File.expand_path '..', __FILE__
|
55
|
-
device = ARGV[0].downcase.strip
|
56
|
-
devices = %w[ android selendroid ios ]
|
57
|
-
raise 'Expected android, selendroid or ios as first argument' unless devices.include? device
|
58
|
-
|
59
|
-
one_test = ARGV[1]
|
60
|
-
test_dir = "/#{device}/"
|
61
|
-
|
62
|
-
caps[:app] = ENV['SAUCE_PATH'] if ENV['SAUCE_USERNAME'] && ENV['SAUCE_ACCESS_KEY']
|
63
|
-
|
64
|
-
trace_files = []
|
65
|
-
|
66
|
-
if one_test
|
67
|
-
unless File.exists? one_test
|
68
|
-
# ensure ext is .rb
|
69
|
-
one_test = File.join(File.dirname(one_test),
|
70
|
-
File.basename(one_test, '.*') + '.rb')
|
71
|
-
one_test = File.join(dir, test_dir + 'specs/', one_test)
|
72
|
-
else
|
73
|
-
one_test = File.expand_path one_test
|
74
|
-
end
|
75
|
-
raise "\nTest #{one_test} does not exist.\n" unless File.exists?(one_test)
|
76
|
-
Appium::Driver.new(caps).start_driver
|
77
|
-
# require support (common.rb)
|
78
|
-
Dir.glob(File.join dir, test_dir + '/*.rb') do |test|
|
79
|
-
require test
|
80
|
-
trace_files << test
|
81
|
-
end
|
82
|
-
puts "Loading one test: #{one_test}"
|
83
|
-
require one_test
|
84
|
-
trace_files << one_test
|
85
|
-
else
|
86
|
-
# require all
|
87
|
-
Dir.glob(File.join dir, test_dir + '**/*.rb') do |test|
|
88
|
-
# load all tests
|
89
|
-
trace_files << test
|
90
|
-
puts " #{File.basename(test, '.*')}"
|
91
|
-
require test
|
92
|
-
end
|
93
|
-
Appium::Driver.new(caps).start_driver
|
94
|
-
end
|
95
|
-
|
96
|
-
trace_files.map! do |f|
|
97
|
-
f = File.expand_path f
|
98
|
-
# ensure all traced files end in .rb
|
99
|
-
f = File.join(File.dirname(f), File.basename(f, '.*') + '.rb')
|
100
|
-
f
|
101
|
-
end
|
102
|
-
|
103
|
-
# Exit after tests.
|
104
|
-
Minitest.after_run { $driver.x if $driver }
|
105
|
-
# Run Minitest. Provide test file array for tracing.
|
106
|
-
Minitest.run_specs({ :trace => trace_files })
|
1
|
+
# ios tests have a set of common helper methods
|
2
|
+
require_relative 'common'
|
3
|
+
# run file is identical to android
|
4
|
+
require_relative '../../android_tests/lib/run'
|
data/lib/appium_lib.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
Encoding.default_external = Encoding::UTF_8
|
3
3
|
Encoding.default_internal = Encoding::UTF_8
|
4
4
|
|
5
|
-
require '
|
5
|
+
require 'forwardable' unless defined? Forwardable
|
6
6
|
require_relative 'appium_lib/rails/duplicable'
|
7
7
|
|
8
8
|
$driver = nil
|
@@ -25,4 +25,4 @@ def self.method_missing method, *args, &block
|
|
25
25
|
end
|
26
26
|
|
27
27
|
require_relative 'appium_lib/logger'
|
28
|
-
require_relative 'appium_lib/driver'
|
28
|
+
require_relative 'appium_lib/driver'
|
@@ -11,24 +11,12 @@ module Appium
|
|
11
11
|
button_index = opts.fetch :button_index, false
|
12
12
|
image_button_index = opts.fetch :image_button_index, false
|
13
13
|
|
14
|
-
# complex_find(...)
|
15
|
-
# 4 = className(String className)
|
16
|
-
# 9 = instance(final int instance)
|
17
|
-
|
18
14
|
if button_index && image_button_index
|
19
|
-
|
20
|
-
|
21
|
-
[[4, Button], [9, button_index]],
|
22
|
-
# className().instance()
|
23
|
-
[[4, ImageButton], [9, image_button_index]]
|
24
|
-
]
|
15
|
+
"new UiSelector().className(#{Button}).instance(#{button_index});" +
|
16
|
+
"new UiSelector().className(#{ImageButton}).instance(#{image_button_index});"
|
25
17
|
else
|
26
|
-
|
27
|
-
|
28
|
-
[[4, Button]],
|
29
|
-
# className()
|
30
|
-
[[4, ImageButton]]
|
31
|
-
]
|
18
|
+
"new UiSelector().className(#{Button});" +
|
19
|
+
"new UiSelector().className(#{ImageButton});"
|
32
20
|
end
|
33
21
|
end
|
34
22
|
|
@@ -59,10 +47,10 @@ module Appium
|
|
59
47
|
index = value
|
60
48
|
raise "#{index} is not a valid index. Must be >= 1" if index <= 0
|
61
49
|
|
62
|
-
return
|
50
|
+
return find_element :uiautomator, _button_visible_selectors(index: index)
|
63
51
|
end
|
64
52
|
|
65
|
-
|
53
|
+
find_element :uiautomator, _button_contains_string(value)
|
66
54
|
end
|
67
55
|
|
68
56
|
# Find all buttons containing value.
|
@@ -70,14 +58,14 @@ module Appium
|
|
70
58
|
# @param value [String] the value to search for
|
71
59
|
# @return [Array<Button>]
|
72
60
|
def buttons value=false
|
73
|
-
return
|
74
|
-
|
61
|
+
return find_elements :uiautomator, _button_visible_selectors unless value
|
62
|
+
find_elements :uiautomator, _button_contains_string(value)
|
75
63
|
end
|
76
64
|
|
77
65
|
# Find the first button.
|
78
66
|
# @return [Button]
|
79
67
|
def first_button
|
80
|
-
|
68
|
+
find_element :uiautomator, _button_visible_selectors(button_index: 0, image_button_index: 0)
|
81
69
|
end
|
82
70
|
|
83
71
|
# Find the last button.
|
@@ -86,25 +74,27 @@ module Appium
|
|
86
74
|
# uiautomator index doesn't support last
|
87
75
|
# and it's 0 indexed
|
88
76
|
button_index = tags(Button).length
|
89
|
-
button_index -= 1 if button_index
|
77
|
+
button_index -= 1 if button_index > 0
|
90
78
|
image_button_index = tags(ImageButton).length
|
91
|
-
image_button_index -= 1 if image_button_index
|
79
|
+
image_button_index -= 1 if image_button_index > 0
|
92
80
|
|
93
|
-
|
81
|
+
find_element :uiautomator,
|
82
|
+
_button_visible_selectors(button_index: button_index,
|
83
|
+
image_button_index: image_button_index)
|
94
84
|
end
|
95
85
|
|
96
86
|
# Find the first button that exactly matches value.
|
97
87
|
# @param value [String] the value to match exactly
|
98
88
|
# @return [Button]
|
99
89
|
def button_exact value
|
100
|
-
|
90
|
+
find_element :uiautomator, _button_exact_string(value)
|
101
91
|
end
|
102
92
|
|
103
93
|
# Find all buttons that exactly match value.
|
104
94
|
# @param value [String] the value to match exactly
|
105
95
|
# @return [Array<Button>]
|
106
96
|
def buttons_exact value
|
107
|
-
|
97
|
+
find_elements :uiautomator, _button_exact_string(value)
|
108
98
|
end
|
109
99
|
end # module Android
|
110
100
|
end # module Appium
|
@@ -29,30 +29,33 @@ module Appium
|
|
29
29
|
complex_finds_exact '*', value
|
30
30
|
end
|
31
31
|
|
32
|
+
# @private
|
33
|
+
def scroll_uiselector content
|
34
|
+
"new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(#{content}.instance(0));"
|
35
|
+
end
|
36
|
+
|
32
37
|
# Scroll to the first element containing target text or description.
|
33
38
|
# @param text [String] the text to search for in the text value and content description
|
34
39
|
# @return [Element] the element scrolled to
|
35
40
|
def scroll_to text
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
[[7, text]]
|
41
|
+
text = %Q("#{text}")
|
42
|
+
|
43
|
+
args = scroll_uiselector("new UiSelector().textContains(#{text})") +
|
44
|
+
scroll_uiselector("new UiSelector().descriptionContains(#{text})")
|
41
45
|
|
42
|
-
|
46
|
+
find_element :uiautomator, args
|
43
47
|
end
|
44
48
|
|
45
49
|
# Scroll to the first element with the exact target text or description.
|
46
50
|
# @param text [String] the text to search for in the text value and content description
|
47
51
|
# @return [Element] the element scrolled to
|
48
52
|
def scroll_to_exact text
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
[[5, text]]
|
53
|
+
text = %Q("#{text}")
|
54
|
+
|
55
|
+
args = scroll_uiselector("new UiSelector().text(#{text})") +
|
56
|
+
scroll_uiselector("new UiSelector().description(#{text})")
|
54
57
|
|
55
|
-
|
58
|
+
find_element :uiautomator, args
|
56
59
|
end
|
57
60
|
end # module Android
|
58
61
|
end # module Appium
|
@@ -3,8 +3,7 @@ module Appium
|
|
3
3
|
# @private
|
4
4
|
# http://nokogiri.org/Nokogiri/XML/SAX.html
|
5
5
|
class AndroidElements < Nokogiri::XML::SAX::Document
|
6
|
-
|
7
|
-
attr_reader :result, :keys
|
6
|
+
attr_reader :result, :keys, :instance
|
8
7
|
|
9
8
|
def filter
|
10
9
|
@filter
|
@@ -20,17 +19,22 @@ module Appium
|
|
20
19
|
def initialize
|
21
20
|
reset
|
22
21
|
@filter = false
|
22
|
+
@instance = Hash.new -1
|
23
23
|
end
|
24
24
|
|
25
25
|
def reset
|
26
26
|
@result = ''
|
27
27
|
@keys = %w[text resource-id content-desc]
|
28
|
+
@instance = Hash.new -1
|
28
29
|
end
|
29
30
|
|
30
31
|
# http://nokogiri.org/Nokogiri/XML/SAX/Document.html
|
31
32
|
def start_element name, attrs = []
|
32
33
|
return if filter && !name.downcase.include?(filter)
|
33
34
|
|
35
|
+
# instance numbers start at 0.
|
36
|
+
number = instance[name] += 1
|
37
|
+
|
34
38
|
attributes = {}
|
35
39
|
|
36
40
|
attrs.each do |key, value|
|
@@ -75,7 +79,7 @@ module Appium
|
|
75
79
|
string += " id: #{id}\n" unless id.nil?
|
76
80
|
string += " strings.xml: #{string_ids}" unless string_ids.nil?
|
77
81
|
|
78
|
-
@result += "\n#{name}\n#{string}" unless attributes.empty?
|
82
|
+
@result += "\n#{name} (#{number})\n#{string}" unless attributes.empty?
|
79
83
|
end
|
80
84
|
end # class AndroidElements
|
81
85
|
|
@@ -92,10 +96,12 @@ module Appium
|
|
92
96
|
else
|
93
97
|
parser = @android_webview_parser ||= Nokogiri::XML::SAX::Parser.new(AndroidElements.new)
|
94
98
|
end
|
95
|
-
parser.document.reset
|
99
|
+
parser.document.reset # ensure document is reset before parsing
|
96
100
|
parser.document.filter = class_name
|
97
101
|
parser.parse source
|
98
|
-
parser.document.result
|
102
|
+
result = parser.document.result
|
103
|
+
parser.document.reset # clean up any created objects after parsing
|
104
|
+
result
|
99
105
|
end
|
100
106
|
|
101
107
|
# Intended for use with console.
|
@@ -157,14 +163,18 @@ module Appium
|
|
157
163
|
# @param index [Integer] the index
|
158
164
|
# @return [Element] the found element of type class_name
|
159
165
|
def ele_index class_name, index
|
166
|
+
results = tags(class_name)
|
160
167
|
if index == 'last()'
|
161
|
-
index =
|
168
|
+
index = results.length
|
162
169
|
index -= 1 if index >= 0
|
163
170
|
else
|
164
171
|
raise 'Index must be >= 1' unless index >= 1
|
165
172
|
index -= 1 if index >= 1
|
166
173
|
end
|
167
|
-
|
174
|
+
|
175
|
+
# uiautomator has issues with index/instance so calculate the index
|
176
|
+
# client side.
|
177
|
+
results[index]
|
168
178
|
end
|
169
179
|
|
170
180
|
# Find the first element that matches class_name
|
@@ -206,32 +216,19 @@ module Appium
|
|
206
216
|
# @param value [String] the value to search for
|
207
217
|
# @return [String]
|
208
218
|
def string_visible_contains class_name, value
|
209
|
-
|
210
|
-
# 29 = resourceId(String id
|
211
|
-
# 7 = descriptionContains(String desc)
|
212
|
-
# 3 = textContains(String text)
|
213
|
-
# todo: textContains isn't case insensitive
|
214
|
-
# descriptionContains is case insensitive
|
219
|
+
value = %Q("#{value}")
|
215
220
|
|
216
221
|
if class_name == '*'
|
217
|
-
return
|
218
|
-
|
219
|
-
|
220
|
-
# descriptionContains()
|
221
|
-
[[7, value]],
|
222
|
-
# textContains()
|
223
|
-
[[3, value]]
|
224
|
-
]
|
222
|
+
return "new UiSelector().resourceId(#{value});" +
|
223
|
+
"new UiSelector().descriptionContains(#{value});" +
|
224
|
+
"new UiSelector().textContains(#{value});"
|
225
225
|
end
|
226
226
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
# className().textContains()
|
233
|
-
[[4, class_name], [3, value]]
|
234
|
-
]
|
227
|
+
class_name = %Q("#{class_name}")
|
228
|
+
|
229
|
+
"new UiSelector().className(#{class_name}).resourceId(#{value});" +
|
230
|
+
"new UiSelector().className(#{class_name}).descriptionContains(#{value});" +
|
231
|
+
"new UiSelector().className(#{class_name}).textContains(#{value});"
|
235
232
|
end
|
236
233
|
|
237
234
|
# Find the first element that contains value
|
@@ -239,7 +236,7 @@ module Appium
|
|
239
236
|
# @param value [String] the value to search for
|
240
237
|
# @return [Element]
|
241
238
|
def complex_find_contains element, value
|
242
|
-
|
239
|
+
find_element :uiautomator, string_visible_contains(element, value)
|
243
240
|
end
|
244
241
|
|
245
242
|
# Find all elements containing value
|
@@ -247,7 +244,7 @@ module Appium
|
|
247
244
|
# @param value [String] the value to search for
|
248
245
|
# @return [Array<Element>]
|
249
246
|
def complex_finds_contains element, value
|
250
|
-
|
247
|
+
find_elements :uiautomator, string_visible_contains(element, value)
|
251
248
|
end
|
252
249
|
|
253
250
|
# @private
|
@@ -256,30 +253,19 @@ module Appium
|
|
256
253
|
# @param value [String] the value to search for
|
257
254
|
# @return [String]
|
258
255
|
def string_visible_exact class_name, value
|
259
|
-
|
260
|
-
# 29 = resourceId(String id
|
261
|
-
# 5 = description(String desc)
|
262
|
-
# 1 = text(String text)
|
256
|
+
value = %Q("#{value}")
|
263
257
|
|
264
258
|
if class_name == '*'
|
265
|
-
return
|
266
|
-
|
267
|
-
|
268
|
-
# description()
|
269
|
-
[[5, value]],
|
270
|
-
# text()
|
271
|
-
[[1, value]]
|
272
|
-
]
|
259
|
+
return "new UiSelector().resourceId(#{value});" +
|
260
|
+
"new UiSelector().description(#{value});" +
|
261
|
+
"new UiSelector().text(#{value});"
|
273
262
|
end
|
274
263
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
# className().text()
|
281
|
-
[[4, class_name], [1, value]]
|
282
|
-
]
|
264
|
+
class_name = %Q("#{class_name}")
|
265
|
+
|
266
|
+
"new UiSelector().className(#{class_name}).resourceId(#{value});" +
|
267
|
+
"new UiSelector().className(#{class_name}).description(#{value});" +
|
268
|
+
"new UiSelector().className(#{class_name}).text(#{value});"
|
283
269
|
end
|
284
270
|
|
285
271
|
# Find the first element exactly matching value
|
@@ -287,7 +273,7 @@ module Appium
|
|
287
273
|
# @param value [String] the value to search for
|
288
274
|
# @return [Element]
|
289
275
|
def complex_find_exact class_name, value
|
290
|
-
|
276
|
+
find_element :uiautomator, string_visible_exact(class_name, value)
|
291
277
|
end
|
292
278
|
|
293
279
|
# Find all elements exactly matching value
|
@@ -295,7 +281,7 @@ module Appium
|
|
295
281
|
# @param value [String] the value to search for
|
296
282
|
# @return [Element]
|
297
283
|
def complex_finds_exact class_name, value
|
298
|
-
|
284
|
+
find_elements :uiautomator, string_visible_exact(class_name, value)
|
299
285
|
end
|
300
286
|
end # module Android
|
301
287
|
end # module Appium
|