appium_lib 3.0.3 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|