appium_lib 9.0.0 → 9.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +21 -0
- data/android_tests/lib/android/specs/android/helper.rb +3 -5
- data/android_tests/lib/android/specs/common/command.rb +47 -0
- data/android_tests/lib/android/specs/common/helper.rb +8 -8
- data/android_tests/lib/android/specs/common/web_context.rb +1 -1
- data/android_tests/lib/android/specs/driver.rb +19 -11
- data/android_tests/lib/format.rb +3 -3
- data/android_tests/lib/run.rb +7 -5
- data/android_tests/readme.md +1 -1
- data/appium_lib.gemspec +6 -7
- data/contributing.md +10 -0
- data/docs/android_docs.md +252 -217
- data/docs/ios_docs.md +257 -222
- data/docs/ios_xcuitest.md +32 -4
- data/ios_tests/lib/common.rb +11 -55
- data/ios_tests/lib/ios/specs/common/command.rb +44 -0
- data/ios_tests/lib/ios/specs/common/helper.rb +8 -8
- data/ios_tests/lib/ios/specs/device/device.rb +5 -5
- data/ios_tests/lib/ios/specs/driver.rb +34 -15
- data/ios_tests/lib/ios/specs/ios/element/textfield.rb +1 -1
- data/ios_tests/readme.md +1 -1
- data/ios_tests/upload/sauce_storage.rb +10 -8
- data/lib/appium_lib/android/element/button.rb +3 -3
- data/lib/appium_lib/android/element/text.rb +1 -1
- data/lib/appium_lib/android/element/textfield.rb +1 -1
- data/lib/appium_lib/android/helper.rb +12 -12
- data/lib/appium_lib/android/mobile_methods.rb +1 -3
- data/lib/appium_lib/common/command.rb +55 -0
- data/lib/appium_lib/common/helper.rb +7 -7
- data/lib/appium_lib/common/patch.rb +21 -8
- data/lib/appium_lib/common/search_context.rb +10 -0
- data/lib/appium_lib/common/version.rb +2 -2
- data/lib/appium_lib/common/wait.rb +8 -14
- data/lib/appium_lib/device/device.rb +65 -83
- data/lib/appium_lib/device/multi_touch.rb +2 -2
- data/lib/appium_lib/device/touch_actions.rb +4 -7
- data/lib/appium_lib/driver.rb +66 -38
- data/lib/appium_lib/ios/element/alert.rb +4 -4
- data/lib/appium_lib/ios/element/textfield.rb +3 -3
- data/lib/appium_lib/ios/errors.rb +6 -0
- data/lib/appium_lib/ios/helper.rb +25 -25
- data/lib/appium_lib/ios/mobile_methods.rb +2 -4
- data/readme.md +3 -1
- data/release_notes.md +13 -0
- metadata +23 -12
@@ -50,8 +50,8 @@ module Appium
|
|
50
50
|
|
51
51
|
string_ids = nil
|
52
52
|
|
53
|
-
if id_matches && id_matches.
|
54
|
-
space_suffix = ' ' * ' strings.xml: '.length
|
53
|
+
if id_matches && !id_matches.empty?
|
54
|
+
space_suffix = ' ' * 15 # 15 is ' strings.xml: '.length
|
55
55
|
string_ids = ''
|
56
56
|
|
57
57
|
# add first
|
@@ -130,11 +130,11 @@ module Appium
|
|
130
130
|
source_header = source[0..doctype_string.length].downcase
|
131
131
|
source_is_html = source_header.start_with?(doctype_string, '<html')
|
132
132
|
|
133
|
-
if source_is_html # parse html from webview
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
133
|
+
parser = if source_is_html # parse html from webview
|
134
|
+
@android_html_parser ||= Nokogiri::HTML::SAX::Parser.new(Common::HTMLElements.new)
|
135
|
+
else
|
136
|
+
@android_native_parser ||= Nokogiri::XML::SAX::Parser.new(AndroidElements.new)
|
137
|
+
end
|
138
138
|
parser.document.reset # ensure document is reset before parsing
|
139
139
|
parser.document.filter = class_name
|
140
140
|
parser.parse source
|
@@ -208,7 +208,7 @@ module Appium
|
|
208
208
|
index = results.length
|
209
209
|
index -= 1 if index >= 0
|
210
210
|
else
|
211
|
-
|
211
|
+
raise 'Index must be >= 1' unless index >= 1
|
212
212
|
index -= 1 if index >= 1
|
213
213
|
end
|
214
214
|
|
@@ -289,9 +289,9 @@ module Appium
|
|
289
289
|
value = %("#{value}")
|
290
290
|
|
291
291
|
if class_name == '*'
|
292
|
-
return _resource_id(value, "new UiSelector().resourceId(#{value});") +
|
292
|
+
return (_resource_id(value, "new UiSelector().resourceId(#{value});") +
|
293
293
|
"new UiSelector().descriptionContains(#{value});" \
|
294
|
-
"new UiSelector().textContains(#{value});"
|
294
|
+
"new UiSelector().textContains(#{value});")
|
295
295
|
end
|
296
296
|
|
297
297
|
class_name = %("#{class_name}")
|
@@ -326,9 +326,9 @@ module Appium
|
|
326
326
|
value = %("#{value}")
|
327
327
|
|
328
328
|
if class_name == '*'
|
329
|
-
return _resource_id(value, "new UiSelector().resourceId(#{value});") +
|
329
|
+
return (_resource_id(value, "new UiSelector().resourceId(#{value});") +
|
330
330
|
"new UiSelector().description(#{value});" \
|
331
|
-
"new UiSelector().text(#{value});"
|
331
|
+
"new UiSelector().text(#{value});")
|
332
332
|
end
|
333
333
|
|
334
334
|
class_name = %("#{class_name}")
|
@@ -8,9 +8,7 @@ module Appium
|
|
8
8
|
# find_elements :uiautomator, 'new UiSelector().clickable(true)'
|
9
9
|
# ```
|
10
10
|
def extended(_mod)
|
11
|
-
|
12
|
-
Selenium::WebDriver::SearchContext::FINDERS[:uiautomator] = '-android uiautomator'
|
13
|
-
end
|
11
|
+
::Appium::Driver::SearchContext::FINDERS[:uiautomator] = '-android uiautomator'
|
14
12
|
end
|
15
13
|
end # class << self
|
16
14
|
end # module Android
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Appium
|
2
|
+
class Driver
|
3
|
+
module Commands
|
4
|
+
COMMAND_NO_ARG = {
|
5
|
+
# common
|
6
|
+
shake: [:post, 'session/:session_id/appium/device/shake'.freeze],
|
7
|
+
launch_app: [:post, 'session/:session_id/appium/app/launch'.freeze],
|
8
|
+
close_app: [:post, 'session/:session_id/appium/app/close'.freeze],
|
9
|
+
reset: [:post, 'session/:session_id/appium/app/reset'.freeze],
|
10
|
+
device_locked?: [:post, 'session/:session_id/appium/device/is_locked'.freeze],
|
11
|
+
|
12
|
+
# Android
|
13
|
+
open_notifications: [:post, 'session/:session_id/appium/device/open_notifications'.freeze],
|
14
|
+
toggle_airplane_mode: [:post, 'session/:session_id/appium/device/toggle_airplane_mode'.freeze],
|
15
|
+
current_activity: [:get, 'session/:session_id/appium/device/current_activity'.freeze],
|
16
|
+
get_network_connection: [:get, 'session/:session_id/network_connection'.freeze],
|
17
|
+
|
18
|
+
# iOS
|
19
|
+
device_time: [:get, 'session/:session_id/appium/device/system_time'.freeze],
|
20
|
+
current_context: [:get, 'session/:session_id/context'.freeze]
|
21
|
+
}.freeze
|
22
|
+
|
23
|
+
COMMAND = {
|
24
|
+
# common
|
25
|
+
available_contexts: [:get, 'session/:session_id/contexts'.freeze],
|
26
|
+
set_context: [:post, 'session/:session_id/context'.freeze],
|
27
|
+
app_strings: [:post, 'session/:session_id/appium/app/strings'.freeze],
|
28
|
+
lock: [:post, 'session/:session_id/appium/device/lock'.freeze],
|
29
|
+
install_app: [:post, 'session/:session_id/appium/device/install_app'.freeze],
|
30
|
+
remove_app: [:post, 'session/:session_id/appium/device/remove_app'.freeze],
|
31
|
+
app_installed?: [:post, 'session/:session_id/appium/device/app_installed'.freeze],
|
32
|
+
background_app: [:post, 'session/:session_id/appium/app/background'.freeze],
|
33
|
+
hide_keyboard: [:post, 'session/:session_id/appium/device/hide_keyboard'.freeze],
|
34
|
+
press_keycode: [:post, 'session/:session_id/appium/device/press_keycode'.freeze],
|
35
|
+
long_press_keycode: [:post, 'session/:session_id/appium/device/long_press_keycode'.freeze],
|
36
|
+
set_immediate_value: [:post, 'session/:session_id/appium/element/:id/value'.freeze],
|
37
|
+
push_file: [:post, 'session/:session_id/appium/device/push_file'.freeze],
|
38
|
+
pull_file: [:post, 'session/:session_id/appium/device/pull_file'.freeze],
|
39
|
+
pull_folder: [:post, 'session/:session_id/appium/device/pull_folder'.freeze],
|
40
|
+
get_settings: [:get, 'session/:session_id/appium/settings'.freeze],
|
41
|
+
update_settings: [:post, 'session/:session_id/appium/settings'.freeze],
|
42
|
+
touch_actions: [:post, 'session/:session_id/touch/perform'.freeze],
|
43
|
+
multi_touch: [:post, 'session/:session_id/touch/multi/perform'.freeze],
|
44
|
+
|
45
|
+
# Android
|
46
|
+
start_activity: [:post, 'session/:session_id/appium/device/start_activity'.freeze],
|
47
|
+
end_coverage: [:post, 'session/:session_id/appium/app/end_test_coverage'.freeze],
|
48
|
+
set_network_connection: [:post, 'session/:session_id/network_connection'.freeze],
|
49
|
+
|
50
|
+
# iOS
|
51
|
+
touch_id: [:post, 'session/:session_id/appium/simulator/touch_id'.freeze]
|
52
|
+
}.merge(COMMAND_NO_ARG).merge(::Selenium::WebDriver::Remote::Bridge::COMMANDS).freeze
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -55,11 +55,11 @@ module Appium
|
|
55
55
|
|
56
56
|
def _print_source(source)
|
57
57
|
opts = Nokogiri::XML::ParseOptions::NOBLANKS | Nokogiri::XML::ParseOptions::NONET
|
58
|
-
if source.start_with? '<html'
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
58
|
+
doc = if source.start_with? '<html'
|
59
|
+
Nokogiri::HTML(source) { |cfg| cfg.options = opts }
|
60
|
+
else
|
61
|
+
Nokogiri::XML(source) { |cfg| cfg.options = opts }
|
62
|
+
end
|
63
63
|
puts doc.to_xml indent: 2
|
64
64
|
end
|
65
65
|
|
@@ -215,8 +215,8 @@ module Appium
|
|
215
215
|
end
|
216
216
|
|
217
217
|
def _no_such_element
|
218
|
-
|
219
|
-
|
218
|
+
error_message = 'An element could not be located on the page using the given search parameters.'
|
219
|
+
raise Selenium::WebDriver::Error::NoSuchElementError, error_message
|
220
220
|
end
|
221
221
|
end # module Common
|
222
222
|
end # module Appium
|
@@ -52,10 +52,13 @@ end # module Appium
|
|
52
52
|
#
|
53
53
|
# Requires from lib/selenium/webdriver/remote.rb
|
54
54
|
require 'selenium/webdriver/remote/capabilities'
|
55
|
+
require 'selenium/webdriver/remote/w3c_capabilities'
|
55
56
|
require 'selenium/webdriver/remote/bridge'
|
57
|
+
require 'selenium/webdriver/remote/w3c_bridge'
|
56
58
|
require 'selenium/webdriver/remote/server_error'
|
57
59
|
require 'selenium/webdriver/remote/response'
|
58
60
|
require 'selenium/webdriver/remote/commands'
|
61
|
+
require 'selenium/webdriver/remote/w3c_commands'
|
59
62
|
require 'selenium/webdriver/remote/http/common'
|
60
63
|
require 'selenium/webdriver/remote/http/default'
|
61
64
|
|
@@ -67,14 +70,15 @@ def patch_webdriver_bridge
|
|
67
70
|
Selenium::WebDriver::Remote::Bridge.class_eval do
|
68
71
|
# Code from lib/selenium/webdriver/remote/bridge.rb
|
69
72
|
def raw_execute(command, opts = {}, command_hash = nil)
|
70
|
-
verb, path =
|
71
|
-
|
72
|
-
path = path.dup
|
73
|
+
verb, path = commands(command) || raise(ArgumentError, "unknown command: #{command.inspect}")
|
74
|
+
path = path.dup
|
73
75
|
|
74
76
|
path[':session_id'] = @session_id if path.include?(':session_id')
|
75
77
|
|
76
78
|
begin
|
77
|
-
opts.each
|
79
|
+
opts.each do |key, value|
|
80
|
+
path[key.inspect] = escaper.escape(value.to_s)
|
81
|
+
end
|
78
82
|
rescue IndexError
|
79
83
|
raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
|
80
84
|
end
|
@@ -107,10 +111,11 @@ def patch_webdriver_bridge
|
|
107
111
|
else
|
108
112
|
Appium::Logger.ap_info print_command
|
109
113
|
end
|
110
|
-
|
114
|
+
elsif command_hash
|
115
|
+
# non-standard command hash
|
111
116
|
# It's important to output this for debugging problems.
|
112
117
|
# for example invalid JSON will not be a Hash
|
113
|
-
Appium::Logger.ap_info command_hash
|
118
|
+
Appium::Logger.ap_info command_hash
|
114
119
|
end
|
115
120
|
delay = $driver.global_webdriver_http_sleep
|
116
121
|
sleep delay if !delay.nil? && delay > 0
|
@@ -131,7 +136,7 @@ class Selenium::WebDriver::Remote::Response
|
|
131
136
|
case val
|
132
137
|
when Hash
|
133
138
|
msg = val['origValue'] || val['message'] or return 'unknown error'
|
134
|
-
msg << " (#{
|
139
|
+
msg << " (#{val['class']})" if val['class']
|
135
140
|
when String
|
136
141
|
msg = val
|
137
142
|
else
|
@@ -144,5 +149,13 @@ end
|
|
144
149
|
|
145
150
|
class Selenium::WebDriver::Remote::Http::Common # rubocop:disable Style/ClassAndModuleChildren
|
146
151
|
remove_const :DEFAULT_HEADERS if defined? DEFAULT_HEADERS
|
147
|
-
DEFAULT_HEADERS = { 'Accept' => CONTENT_TYPE, 'User-Agent' => "appium/ruby_lib/#{::Appium::VERSION}" }
|
152
|
+
DEFAULT_HEADERS = { 'Accept' => CONTENT_TYPE, 'User-Agent' => "appium/ruby_lib/#{::Appium::VERSION}" }.freeze
|
153
|
+
end
|
154
|
+
|
155
|
+
def patch_remote_driver_commands
|
156
|
+
Selenium::WebDriver::Remote::Bridge.class_eval do
|
157
|
+
def commands(command)
|
158
|
+
::Appium::Driver::Commands::COMMAND[command]
|
159
|
+
end
|
160
|
+
end
|
148
161
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Appium
|
2
2
|
# Version and Date are defined on the 'Appium' module, not 'Appium::Common'
|
3
|
-
VERSION = '9.
|
4
|
-
DATE = '2016-12-
|
3
|
+
VERSION = '9.1.0'.freeze unless defined? ::Appium::VERSION
|
4
|
+
DATE = '2016-12-18'.freeze unless defined? ::Appium::DATE
|
5
5
|
end
|
@@ -11,7 +11,7 @@ module Appium
|
|
11
11
|
invalid_keys = []
|
12
12
|
opts.keys.each { |key| invalid_keys << key unless valid_keys.include?(key) }
|
13
13
|
# [:one, :two] => :one, :two
|
14
|
-
|
14
|
+
raise "Invalid keys #{invalid_keys.to_s[1..-2]}. Valid keys are #{valid_keys.to_s[1..-2]}" unless invalid_keys.empty?
|
15
15
|
|
16
16
|
timeout = opts.fetch(:timeout, 30)
|
17
17
|
interval = opts.fetch(:interval, 0.5)
|
@@ -24,12 +24,10 @@ module Appium
|
|
24
24
|
|
25
25
|
until Time.now > end_time
|
26
26
|
begin
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
return block.call
|
32
|
-
end
|
27
|
+
return block.call unless return_if_true
|
28
|
+
|
29
|
+
result = block.call
|
30
|
+
return result if result
|
33
31
|
rescue ::Errno::ECONNREFUSED => e
|
34
32
|
raise e
|
35
33
|
rescue *ignored => last_error # rubocop:disable Lint/HandleExceptions
|
@@ -39,21 +37,17 @@ module Appium
|
|
39
37
|
sleep interval
|
40
38
|
end
|
41
39
|
|
42
|
-
|
43
|
-
msg = message.dup
|
44
|
-
else
|
45
|
-
msg = "timed out after #{timeout} seconds"
|
46
|
-
end
|
40
|
+
msg = message ? message.dup : "timed out after #{timeout} seconds"
|
47
41
|
|
48
42
|
msg << " (#{last_error.message})" if last_error
|
49
43
|
|
50
|
-
|
44
|
+
raise Selenium::WebDriver::Error::TimeOutError, msg
|
51
45
|
end
|
52
46
|
|
53
47
|
# process opts before calling _generic_wait
|
54
48
|
def _process_wait_opts(opts)
|
55
49
|
opts = { timeout: opts } if opts.is_a?(Numeric)
|
56
|
-
|
50
|
+
raise 'opts must be a hash' unless opts.is_a? Hash
|
57
51
|
opts
|
58
52
|
end
|
59
53
|
|
@@ -4,24 +4,6 @@ module Appium
|
|
4
4
|
module Device
|
5
5
|
extend Forwardable
|
6
6
|
|
7
|
-
NoArgMethods = {
|
8
|
-
post: {
|
9
|
-
open_notifications: 'session/:session_id/appium/device/open_notifications',
|
10
|
-
shake: 'session/:session_id/appium/device/shake',
|
11
|
-
launch_app: 'session/:session_id/appium/app/launch',
|
12
|
-
close_app: 'session/:session_id/appium/app/close',
|
13
|
-
reset: 'session/:session_id/appium/app/reset',
|
14
|
-
toggle_airplane_mode: 'session/:session_id/appium/device/toggle_airplane_mode',
|
15
|
-
device_locked?: 'session/:session_id/appium/device/is_locked'
|
16
|
-
},
|
17
|
-
get: {
|
18
|
-
device_time: 'session/:session_id/appium/device/system_time',
|
19
|
-
current_activity: 'session/:session_id/appium/device/current_activity',
|
20
|
-
current_context: 'session/:session_id/context',
|
21
|
-
get_network_connection: 'session/:session_id/network_connection'
|
22
|
-
}
|
23
|
-
}
|
24
|
-
|
25
7
|
# @!method app_strings
|
26
8
|
# Return the hash of all localization strings.
|
27
9
|
# ```ruby
|
@@ -117,49 +99,49 @@ module Appium
|
|
117
99
|
def extended(_mod)
|
118
100
|
extend_webdriver_with_forwardable
|
119
101
|
|
120
|
-
|
121
|
-
|
102
|
+
::Appium::Driver::Commands::COMMAND_NO_ARG.each_key do |method|
|
103
|
+
add_endpoint_method method
|
122
104
|
end
|
123
105
|
|
124
|
-
add_endpoint_method(:available_contexts
|
106
|
+
add_endpoint_method(:available_contexts) do
|
125
107
|
def available_contexts
|
126
108
|
# return empty array instead of nil on failure
|
127
109
|
execute(:available_contexts, {}) || []
|
128
110
|
end
|
129
111
|
end
|
130
112
|
|
131
|
-
add_endpoint_method(:app_strings
|
113
|
+
add_endpoint_method(:app_strings) do
|
132
114
|
def app_strings(language = nil)
|
133
115
|
opts = language ? { language: language } : {}
|
134
116
|
execute :app_strings, {}, opts
|
135
117
|
end
|
136
118
|
end
|
137
119
|
|
138
|
-
add_endpoint_method(:lock
|
120
|
+
add_endpoint_method(:lock) do
|
139
121
|
def lock(duration)
|
140
122
|
execute :lock, {}, seconds: duration
|
141
123
|
end
|
142
124
|
end
|
143
125
|
|
144
|
-
add_endpoint_method(:install_app
|
126
|
+
add_endpoint_method(:install_app) do
|
145
127
|
def install_app(path)
|
146
128
|
execute :install_app, {}, appPath: path
|
147
129
|
end
|
148
130
|
end
|
149
131
|
|
150
|
-
add_endpoint_method(:remove_app
|
132
|
+
add_endpoint_method(:remove_app) do
|
151
133
|
def remove_app(id)
|
152
134
|
execute :remove_app, {}, appId: id
|
153
135
|
end
|
154
136
|
end
|
155
137
|
|
156
|
-
add_endpoint_method(:app_installed
|
138
|
+
add_endpoint_method(:app_installed?) do
|
157
139
|
def app_installed?(app_id)
|
158
140
|
execute :app_installed?, {}, bundleId: app_id
|
159
141
|
end
|
160
142
|
end
|
161
143
|
|
162
|
-
add_endpoint_method(:background_app
|
144
|
+
add_endpoint_method(:background_app) do
|
163
145
|
def background_app(duration)
|
164
146
|
execute :background_app, {}, seconds: duration
|
165
147
|
end
|
@@ -178,18 +160,18 @@ module Appium
|
|
178
160
|
# start_activity app_package: 'io.appium.android.apis',
|
179
161
|
# app_activity: '.accessibility.AccessibilityNodeProviderActivity'
|
180
162
|
# ```
|
181
|
-
add_endpoint_method(:start_activity
|
163
|
+
add_endpoint_method(:start_activity) do
|
182
164
|
def start_activity(opts)
|
183
|
-
|
165
|
+
raise 'opts must be a hash' unless opts.is_a? Hash
|
184
166
|
app_package = opts[:app_package]
|
185
|
-
|
167
|
+
raise 'app_package is required' unless app_package
|
186
168
|
app_activity = opts[:app_activity]
|
187
|
-
|
169
|
+
raise 'app_activity is required' unless opts[:app_activity]
|
188
170
|
app_wait_package = opts.fetch(:app_wait_package, '')
|
189
171
|
app_wait_activity = opts.fetch(:app_wait_activity, '')
|
190
172
|
|
191
173
|
unknown_opts = opts.keys - [:app_package, :app_activity, :app_wait_package, :app_wait_activity]
|
192
|
-
|
174
|
+
raise "Unknown options #{unknown_opts}" unless unknown_opts.empty?
|
193
175
|
|
194
176
|
execute :start_activity, {}, appPackage: app_package,
|
195
177
|
appActivity: app_activity,
|
@@ -198,13 +180,13 @@ module Appium
|
|
198
180
|
end
|
199
181
|
end
|
200
182
|
|
201
|
-
add_endpoint_method(:set_context
|
183
|
+
add_endpoint_method(:set_context) do
|
202
184
|
def set_context(context = null)
|
203
185
|
execute :set_context, {}, name: context
|
204
186
|
end
|
205
187
|
end
|
206
188
|
|
207
|
-
add_endpoint_method(:hide_keyboard
|
189
|
+
add_endpoint_method(:hide_keyboard) do
|
208
190
|
def hide_keyboard(close_key = nil)
|
209
191
|
# Android can only tapOutside.
|
210
192
|
if $driver.device_is_android?
|
@@ -222,7 +204,7 @@ module Appium
|
|
222
204
|
end
|
223
205
|
end
|
224
206
|
|
225
|
-
add_endpoint_method(:press_keycode
|
207
|
+
add_endpoint_method(:press_keycode) do
|
226
208
|
def press_keycode(key, metastate = nil)
|
227
209
|
args = { keycode: key }
|
228
210
|
args[:metastate] = metastate if metastate
|
@@ -230,7 +212,7 @@ module Appium
|
|
230
212
|
end
|
231
213
|
end
|
232
214
|
|
233
|
-
add_endpoint_method(:long_press_keycode
|
215
|
+
add_endpoint_method(:long_press_keycode) do
|
234
216
|
def long_press_keycode(key, metastate = nil)
|
235
217
|
args = { keycode: key }
|
236
218
|
args[:metastate] = metastate if metastate
|
@@ -239,20 +221,20 @@ module Appium
|
|
239
221
|
end
|
240
222
|
|
241
223
|
# TODO: TEST ME
|
242
|
-
add_endpoint_method(:set_immediate_value
|
224
|
+
add_endpoint_method(:set_immediate_value) do
|
243
225
|
def set_immediate_value(element, value)
|
244
226
|
execute :set_immediate_value, { id: element.ref }, value: value
|
245
227
|
end
|
246
228
|
end
|
247
229
|
|
248
|
-
add_endpoint_method(:push_file
|
230
|
+
add_endpoint_method(:push_file) do
|
249
231
|
def push_file(path, filedata)
|
250
232
|
encoded_data = Base64.encode64 filedata
|
251
233
|
execute :push_file, {}, path: path, data: encoded_data
|
252
234
|
end
|
253
235
|
end
|
254
236
|
|
255
|
-
add_endpoint_method(:pull_file
|
237
|
+
add_endpoint_method(:pull_file) do
|
256
238
|
def pull_file(path)
|
257
239
|
data = execute :pull_file, {}, path: path
|
258
240
|
Base64.decode64 data
|
@@ -260,7 +242,7 @@ module Appium
|
|
260
242
|
end
|
261
243
|
|
262
244
|
# TODO: TEST ME
|
263
|
-
add_endpoint_method(:pull_folder
|
245
|
+
add_endpoint_method(:pull_folder) do
|
264
246
|
def pull_folder(path)
|
265
247
|
data = execute :pull_folder, {}, path: path
|
266
248
|
Base64.decode64 data
|
@@ -268,26 +250,26 @@ module Appium
|
|
268
250
|
end
|
269
251
|
|
270
252
|
# TODO: TEST ME
|
271
|
-
add_endpoint_method(:touch_id
|
253
|
+
add_endpoint_method(:touch_id) do
|
272
254
|
def touch_id(match = true)
|
273
255
|
execute :touch_id, {}, match: match
|
274
256
|
end
|
275
257
|
end
|
276
258
|
|
277
259
|
# TODO: TEST ME
|
278
|
-
add_endpoint_method(:end_coverage
|
260
|
+
add_endpoint_method(:end_coverage) do
|
279
261
|
def end_coverage(path, intent)
|
280
262
|
execute :end_coverage, {}, path: path, intent: intent
|
281
263
|
end
|
282
264
|
end
|
283
265
|
|
284
|
-
add_endpoint_method(:get_settings
|
266
|
+
add_endpoint_method(:get_settings) do
|
285
267
|
def get_settings
|
286
268
|
execute :get_settings, {}
|
287
269
|
end
|
288
270
|
end
|
289
271
|
|
290
|
-
add_endpoint_method(:update_settings
|
272
|
+
add_endpoint_method(:update_settings) do
|
291
273
|
def update_settings(settings)
|
292
274
|
execute :update_settings, {}, settings: settings
|
293
275
|
end
|
@@ -308,7 +290,7 @@ module Appium
|
|
308
290
|
# 2 (Wifi only) | 0 | 1 | 0
|
309
291
|
# 0 (None) | 0 | 0 | 0
|
310
292
|
#
|
311
|
-
add_endpoint_method(:set_network_connection
|
293
|
+
add_endpoint_method(:set_network_connection) do
|
312
294
|
def set_network_connection(mode)
|
313
295
|
execute :set_network_connection, {}, type: mode
|
314
296
|
end
|
@@ -322,13 +304,11 @@ module Appium
|
|
322
304
|
# def extended
|
323
305
|
|
324
306
|
# @private
|
325
|
-
def add_endpoint_method(method
|
307
|
+
def add_endpoint_method(method)
|
326
308
|
if block_given?
|
327
|
-
|
328
|
-
# Because creating Procs from blocks is slow
|
329
|
-
create_bridge_command method, verb, path, &Proc.new
|
309
|
+
create_bridge_command method, &Proc.new
|
330
310
|
else
|
331
|
-
create_bridge_command method
|
311
|
+
create_bridge_command method
|
332
312
|
end
|
333
313
|
|
334
314
|
delegate_driver_method method
|
@@ -355,31 +335,7 @@ module Appium
|
|
355
335
|
end
|
356
336
|
|
357
337
|
# @private
|
358
|
-
def create_bridge_command(method
|
359
|
-
Selenium::WebDriver::Remote::Bridge.class_eval do
|
360
|
-
command method, verb, path
|
361
|
-
if block_given?
|
362
|
-
class_eval(&Proc.new)
|
363
|
-
else
|
364
|
-
define_method(method) { execute method }
|
365
|
-
end
|
366
|
-
end
|
367
|
-
end
|
368
|
-
|
369
|
-
# @private
|
370
|
-
def add_bridge_method(method)
|
371
|
-
if block_given?
|
372
|
-
create_bridge method, &Proc.new
|
373
|
-
else
|
374
|
-
create_bridge method
|
375
|
-
end
|
376
|
-
|
377
|
-
delegate_driver_method method
|
378
|
-
delegate_from_appium_driver method
|
379
|
-
end
|
380
|
-
|
381
|
-
# @private
|
382
|
-
def create_bridge(method)
|
338
|
+
def create_bridge_command(method)
|
383
339
|
Selenium::WebDriver::Remote::Bridge.class_eval do
|
384
340
|
if block_given?
|
385
341
|
class_eval(&Proc.new)
|
@@ -399,19 +355,45 @@ module Appium
|
|
399
355
|
# ```
|
400
356
|
def extend_search_contexts
|
401
357
|
Selenium::WebDriver::SearchContext.class_eval do
|
402
|
-
|
358
|
+
def find_element_with_appium(*args)
|
359
|
+
how, what = extract_args(args)
|
360
|
+
|
361
|
+
finders = ::Selenium::WebDriver::SearchContext::FINDERS.merge ::Appium::Driver::SearchContext::FINDERS
|
362
|
+
by = finders[how.to_sym]
|
363
|
+
raise ArgumentError, "cannot find element by #{how.inspect}" unless by
|
364
|
+
|
365
|
+
begin
|
366
|
+
bridge.find_element_by by, what.to_s, ref
|
367
|
+
rescue Selenium::WebDriver::Error::TimeOutError
|
368
|
+
raise Selenium::WebDriver::Error::NoSuchElementError
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
def find_elements_with_appium(*args)
|
373
|
+
how, what = extract_args(args)
|
374
|
+
|
375
|
+
finders = ::Selenium::WebDriver::SearchContext::FINDERS.merge ::Appium::Driver::SearchContext::FINDERS
|
376
|
+
by = finders[how.to_sym]
|
377
|
+
raise ArgumentError, "cannot find element by #{how.inspect}" unless by
|
378
|
+
|
379
|
+
begin
|
380
|
+
bridge.find_elements_by by, what.to_s, ref
|
381
|
+
rescue Selenium::WebDriver::Error::TimeOutError
|
382
|
+
raise Selenium::WebDriver::Error::NoSuchElementError
|
383
|
+
end
|
384
|
+
end
|
403
385
|
end
|
404
386
|
end
|
405
387
|
|
406
388
|
def add_touch_actions
|
407
|
-
add_endpoint_method(:touch_actions
|
389
|
+
add_endpoint_method(:touch_actions) do
|
408
390
|
def touch_actions(actions)
|
409
391
|
actions = { actions: [actions].flatten }
|
410
392
|
execute :touch_actions, {}, actions
|
411
393
|
end
|
412
394
|
end
|
413
395
|
|
414
|
-
add_endpoint_method(:multi_touch
|
396
|
+
add_endpoint_method(:multi_touch) do
|
415
397
|
def multi_touch(actions)
|
416
398
|
execute :multi_touch, {}, actions: actions
|
417
399
|
end
|
@@ -440,7 +422,7 @@ module Appium
|
|
440
422
|
# ```ruby
|
441
423
|
# ime_activate engine: 'com.android.inputmethod.latin/.LatinIME'
|
442
424
|
# ```
|
443
|
-
|
425
|
+
add_endpoint_method(:ime_activate) do
|
444
426
|
def ime_activate(ime_name)
|
445
427
|
execute :imeActivateEngine, {}, engine: ime_name
|
446
428
|
end
|
@@ -453,7 +435,7 @@ module Appium
|
|
453
435
|
# ```ruby
|
454
436
|
# ime_available_engines #=> Get the list of IME installed in the target device
|
455
437
|
# ```
|
456
|
-
|
438
|
+
add_endpoint_method(:ime_available_engines) do
|
457
439
|
def ime_available_engines
|
458
440
|
execute :imeGetAvailableEngines
|
459
441
|
end
|
@@ -466,7 +448,7 @@ module Appium
|
|
466
448
|
# ```ruby
|
467
449
|
# ime_active_engine #=> Get the current active IME such as 'com.android.inputmethod.latin/.LatinIME'
|
468
450
|
# ```
|
469
|
-
|
451
|
+
add_endpoint_method(:ime_active_engine) do
|
470
452
|
def ime_active_engine
|
471
453
|
execute :imeGetActiveEngine
|
472
454
|
end
|
@@ -479,7 +461,7 @@ module Appium
|
|
479
461
|
# ```ruby
|
480
462
|
# ime_activated #=> True if IME is activated
|
481
463
|
# ```
|
482
|
-
|
464
|
+
add_endpoint_method(:ime_activated) do
|
483
465
|
def ime_activated
|
484
466
|
execute :imeIsActivated
|
485
467
|
end
|
@@ -493,7 +475,7 @@ module Appium
|
|
493
475
|
# ```ruby
|
494
476
|
# ime_deactivate #=> Deactivate current IME engine
|
495
477
|
# ```
|
496
|
-
|
478
|
+
add_endpoint_method(:ime_deactivate) do
|
497
479
|
def ime_deactivate
|
498
480
|
execute :imeDeactivate, {}
|
499
481
|
end
|