appium_lib 9.5.0 → 9.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/docs/android_docs.md +512 -287
- data/docs/ios_docs.md +906 -315
- data/docs/ios_xcuitest.md +4 -0
- data/lib/appium_lib/android/device.rb +39 -0
- data/lib/appium_lib/android/element/button.rb +36 -65
- data/lib/appium_lib/android/element/generic.rb +20 -12
- data/lib/appium_lib/android/helper.rb +4 -16
- data/lib/appium_lib/android/uiautomator2/element/button.rb +110 -0
- data/lib/appium_lib/android/uiautomator2/helper.rb +85 -0
- data/lib/appium_lib/common/command.rb +9 -1
- data/lib/appium_lib/common/helper.rb +5 -4
- data/lib/appium_lib/common/patch.rb +21 -5
- data/lib/appium_lib/common/version.rb +2 -2
- data/lib/appium_lib/common/wait.rb +1 -0
- data/lib/appium_lib/device/device.rb +13 -23
- data/lib/appium_lib/device/multi_touch.rb +60 -20
- data/lib/appium_lib/device/touch_actions.rb +17 -8
- data/lib/appium_lib/driver.rb +79 -19
- data/lib/appium_lib/ios/element/button.rb +5 -25
- data/lib/appium_lib/ios/element/generic.rb +4 -22
- data/lib/appium_lib/ios/element/text.rb +5 -25
- data/lib/appium_lib/ios/element/textfield.rb +31 -78
- data/lib/appium_lib/ios/helper.rb +11 -74
- data/lib/appium_lib/ios/mobile_methods.rb +0 -20
- data/lib/appium_lib/ios/patch.rb +2 -6
- data/lib/appium_lib/ios/xcuitest/device.rb +59 -0
- data/lib/appium_lib/ios/xcuitest/element.rb +24 -0
- data/lib/appium_lib/ios/xcuitest/element/button.rb +64 -0
- data/lib/appium_lib/ios/xcuitest/element/generic.rb +50 -0
- data/lib/appium_lib/ios/xcuitest/element/text.rb +61 -0
- data/lib/appium_lib/ios/xcuitest/element/textfield.rb +94 -0
- data/lib/appium_lib/ios/{xcuitest_gestures.rb → xcuitest/gestures.rb} +10 -23
- data/lib/appium_lib/ios/xcuitest/helper.rb +103 -0
- data/lib/appium_lib/ios/xcuitest/mobile_methods.rb +23 -0
- data/release_notes.md +6 -0
- metadata +14 -3
@@ -52,11 +52,19 @@ module Appium
|
|
52
52
|
end_coverage: [:post, 'session/:session_id/appium/app/end_test_coverage'.freeze],
|
53
53
|
set_network_connection: [:post, 'session/:session_id/network_connection'.freeze],
|
54
54
|
get_performance_data: [:post, 'session/:session_id/appium/getPerformanceData'.freeze],
|
55
|
+
get_ime_available_engines: [:get, 'session/:session_id/ime/available_engines'.freeze],
|
56
|
+
get_ime_active_engine: [:get, 'session/:session_id/ime/active_engine'.freeze],
|
57
|
+
get_ime_activated: [:get, 'session/:session_id/ime/activated'.freeze],
|
58
|
+
ime_deactivate: [:post, 'session/:session_id/ime/deactivate'.freeze],
|
59
|
+
ime_activate: [:post, 'session/:session_id/ime/activate'.freeze],
|
55
60
|
|
56
61
|
# iOS
|
57
62
|
touch_id: [:post, 'session/:session_id/appium/simulator/touch_id'.freeze],
|
58
63
|
toggle_touch_id_enrollment: [:post, 'session/:session_id/appium/simulator/toggle_touch_id_enrollment'.freeze]
|
59
|
-
}.merge(COMMAND_NO_ARG).
|
64
|
+
}.merge(COMMAND_NO_ARG).freeze
|
65
|
+
|
66
|
+
COMMANDS_EXTEND_OSS = COMMAND.merge(::Selenium::WebDriver::Remote::OSS::Bridge::COMMANDS).freeze
|
67
|
+
COMMANDS_EXTEND_W3C = COMMAND.merge(::Selenium::WebDriver::Remote::W3C::Bridge::COMMANDS).freeze
|
60
68
|
end
|
61
69
|
end
|
62
70
|
end
|
@@ -77,9 +77,9 @@ module Appium
|
|
77
77
|
end
|
78
78
|
|
79
79
|
# http://nokogiri.org/Nokogiri/XML/SAX/Document.html
|
80
|
-
def start_element(name, attrs = [])
|
80
|
+
def start_element(name, attrs = [], driver = $driver)
|
81
81
|
# Count only visible elements. Android is always visible
|
82
|
-
element_visible =
|
82
|
+
element_visible = driver.device_is_android? ? true : Hash[attrs]['visible'] == 'true'
|
83
83
|
@result[name] += 1 if element_visible
|
84
84
|
end
|
85
85
|
|
@@ -115,8 +115,8 @@ module Appium
|
|
115
115
|
# ```ruby
|
116
116
|
# px_to_window_rel x: 50, y: 150
|
117
117
|
# ```
|
118
|
-
def px_to_window_rel(opts = {})
|
119
|
-
w =
|
118
|
+
def px_to_window_rel(opts = {}, driver = $driver)
|
119
|
+
w = driver.window_size
|
120
120
|
x = opts.fetch :x, 0
|
121
121
|
y = opts.fetch :y, 0
|
122
122
|
|
@@ -214,6 +214,7 @@ module Appium
|
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
217
|
+
# @private
|
217
218
|
def _no_such_element
|
218
219
|
error_message = 'An element could not be located on the page using the given search parameters.'
|
219
220
|
raise Selenium::WebDriver::Error::NoSuchElementError, error_message
|
@@ -27,7 +27,7 @@ module Appium
|
|
27
27
|
# ```
|
28
28
|
#
|
29
29
|
# @return [OpenStruct] the relative x, y in a struct. ex: { x: 0.50, y: 0.20 }
|
30
|
-
def location_rel
|
30
|
+
def location_rel(driver = $driver)
|
31
31
|
# TODO: Remove with 'refine Appium ruby binding'
|
32
32
|
# https://github.com/appium/ruby_lib/issues/602
|
33
33
|
if ::Appium.selenium_webdriver_version_more?('3.4.0')
|
@@ -50,7 +50,7 @@ module Appium
|
|
50
50
|
center_x = location_x + (size_width / 2.0)
|
51
51
|
center_y = location_y + (size_height / 2.0)
|
52
52
|
|
53
|
-
w =
|
53
|
+
w = driver.window_size
|
54
54
|
OpenStruct.new(x: "#{center_x} / #{w.width.to_f}",
|
55
55
|
y: "#{center_y} / #{w.height.to_f}")
|
56
56
|
end
|
@@ -129,8 +129,13 @@ def patch_webdriver_bridge
|
|
129
129
|
# for example invalid JSON will not be a Hash
|
130
130
|
Appium::Logger.ap_info command_hash
|
131
131
|
end
|
132
|
-
|
133
|
-
|
132
|
+
|
133
|
+
if !$driver.nil? && $driver.global_webdriver_http_sleep
|
134
|
+
warn '[DEPRECATION] global_webdriver_http_sleep will be removed. Please arrange with timeout.'
|
135
|
+
|
136
|
+
delay = $driver.global_webdriver_http_sleep
|
137
|
+
sleep delay if delay > 0
|
138
|
+
end
|
134
139
|
# Appium::Logger.info "verb: #{verb}, path #{path}, command_hash #{command_hash.to_json}"
|
135
140
|
http.call(verb, path, command_hash)
|
136
141
|
end # def
|
@@ -168,7 +173,18 @@ end
|
|
168
173
|
def patch_remote_driver_commands
|
169
174
|
Selenium::WebDriver::Remote::OSS::Bridge.class_eval do
|
170
175
|
def commands(command)
|
171
|
-
::Appium::Driver::Commands::
|
176
|
+
::Appium::Driver::Commands::COMMANDS_EXTEND_OSS[command]
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
Selenium::WebDriver::Remote::W3C::Bridge.class_eval do
|
181
|
+
def commands(command)
|
182
|
+
case command
|
183
|
+
when :status, :is_element_displayed
|
184
|
+
::Appium::Driver::Commands::COMMANDS_EXTEND_OSS[command]
|
185
|
+
else
|
186
|
+
::Appium::Driver::Commands::COMMANDS_EXTEND_W3C[command]
|
187
|
+
end
|
172
188
|
end
|
173
189
|
end
|
174
190
|
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 = '2017-08-
|
3
|
+
VERSION = '9.6.0'.freeze unless defined? ::Appium::VERSION
|
4
|
+
DATE = '2017-08-19'.freeze unless defined? ::Appium::DATE
|
5
5
|
end
|
@@ -254,14 +254,7 @@ module Appium
|
|
254
254
|
|
255
255
|
add_endpoint_method(:background_app) do
|
256
256
|
def background_app(duration = 0)
|
257
|
-
|
258
|
-
# `execute :background_app, {}, seconds: { timeout: duration_milli_sec }` works over Appium 1.6.4
|
259
|
-
if $driver.automation_name_is_xcuitest?
|
260
|
-
duration_milli_sec = duration.nil? ? nil : duration * 1000
|
261
|
-
execute :background_app, {}, seconds: { timeout: duration_milli_sec }
|
262
|
-
else
|
263
|
-
execute :background_app, {}, seconds: duration
|
264
|
-
end
|
257
|
+
execute :background_app, {}, seconds: duration
|
265
258
|
end
|
266
259
|
end
|
267
260
|
|
@@ -295,16 +288,9 @@ module Appium
|
|
295
288
|
def hide_keyboard(close_key = nil, strategy = nil)
|
296
289
|
option = {}
|
297
290
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
elsif $driver.automation_name_is_xcuitest?
|
302
|
-
option[:key] = close_key if close_key
|
303
|
-
option[:strategy] = strategy if strategy
|
304
|
-
else
|
305
|
-
option[:key] = close_key || 'Done' # default to Done key.
|
306
|
-
option[:strategy] = strategy || :pressKey # default to pressKey
|
307
|
-
end
|
291
|
+
option[:key] = close_key || 'Done' # default to Done key.
|
292
|
+
option[:strategy] = strategy || :pressKey # default to pressKey
|
293
|
+
|
308
294
|
execute :hide_keyboard, {}, option
|
309
295
|
end
|
310
296
|
end
|
@@ -440,6 +426,10 @@ module Appium
|
|
440
426
|
Selenium::WebDriver::Remote::OSS::Bridge.class_eval do
|
441
427
|
block_given? ? class_eval(&Proc.new) : define_method(method) { execute method }
|
442
428
|
end
|
429
|
+
|
430
|
+
Selenium::WebDriver::Remote::W3C::Bridge.class_eval do
|
431
|
+
block_given? ? class_eval(&Proc.new) : define_method(method) { execute method }
|
432
|
+
end
|
443
433
|
end
|
444
434
|
|
445
435
|
# @!method find_element_with_appium
|
@@ -520,7 +510,7 @@ module Appium
|
|
520
510
|
# ```
|
521
511
|
add_endpoint_method(:ime_activate) do
|
522
512
|
def ime_activate(ime_name)
|
523
|
-
execute :
|
513
|
+
execute :ime_activate, {}, engine: ime_name
|
524
514
|
end
|
525
515
|
end
|
526
516
|
|
@@ -533,7 +523,7 @@ module Appium
|
|
533
523
|
# ```
|
534
524
|
add_endpoint_method(:ime_available_engines) do
|
535
525
|
def ime_available_engines
|
536
|
-
execute :
|
526
|
+
execute :get_ime_available_engines
|
537
527
|
end
|
538
528
|
end
|
539
529
|
|
@@ -546,7 +536,7 @@ module Appium
|
|
546
536
|
# ```
|
547
537
|
add_endpoint_method(:ime_active_engine) do
|
548
538
|
def ime_active_engine
|
549
|
-
execute :
|
539
|
+
execute :get_ime_active_engine
|
550
540
|
end
|
551
541
|
end
|
552
542
|
|
@@ -559,7 +549,7 @@ module Appium
|
|
559
549
|
# ```
|
560
550
|
add_endpoint_method(:ime_activated) do
|
561
551
|
def ime_activated
|
562
|
-
execute :
|
552
|
+
execute :get_ime_activated
|
563
553
|
end
|
564
554
|
end
|
565
555
|
|
@@ -573,7 +563,7 @@ module Appium
|
|
573
563
|
# ```
|
574
564
|
add_endpoint_method(:ime_deactivate) do
|
575
565
|
def ime_deactivate
|
576
|
-
execute :
|
566
|
+
execute :ime_deactivate, {}
|
577
567
|
end
|
578
568
|
end
|
579
569
|
end
|
@@ -14,31 +14,56 @@ module Appium
|
|
14
14
|
# multi_touch_action.add action_1
|
15
15
|
# multi_touch_action.add action_2
|
16
16
|
# multi_touch_action.perform
|
17
|
+
# ```
|
18
|
+
#
|
19
|
+
# ```
|
20
|
+
# # with an arbitrary driver
|
21
|
+
# driver = Appium::Driver.new(opts, false).start_driver
|
22
|
+
# multi_touch_action = MultiTouch.new(driver)
|
23
|
+
# multi_touch_action.add action_1
|
24
|
+
# multi_touch_action.add action_2
|
25
|
+
# multi_touch_action.perform
|
26
|
+
# ```
|
27
|
+
|
17
28
|
class MultiTouch
|
18
29
|
class << self
|
19
30
|
# Convenience method for pinching the screen.
|
20
31
|
# Places two fingers at the edges of the screen and brings them together.
|
21
32
|
# @param percentage (int) The percent size by which to shrink the screen when pinched.
|
22
33
|
# @param auto_perform (boolean) Whether to perform the action immediately (default true)
|
34
|
+
# @param driver (Driver) Set a driver to conduct the action. DEfault is global driver($driver)
|
23
35
|
#
|
24
36
|
# ```ruby
|
25
|
-
#
|
37
|
+
# pinch 75 #=> Pinch the screen from the top right and bottom left corners
|
38
|
+
# ```
|
39
|
+
#
|
40
|
+
# Without auto_perform
|
41
|
+
#
|
42
|
+
# ```ruby
|
43
|
+
# action = pinch 75, false #=> Pinch the screen from the top right and bottom left corners
|
26
44
|
# action.perform #=> to 25% of its size.
|
27
45
|
# ```
|
28
|
-
|
46
|
+
#
|
47
|
+
# With driver
|
48
|
+
#
|
49
|
+
# ```ruby
|
50
|
+
# driver = Appium::Driver.new(opts, false).start_driver
|
51
|
+
# pinch 75, true, driver #=> Pinch the screen from the top right and bottom left corners
|
52
|
+
# ```
|
53
|
+
def pinch(percentage = 25, auto_perform = true, driver = $driver)
|
29
54
|
raise ArgumentError("Can't pinch to greater than screen size.") if percentage > 100
|
30
55
|
|
31
56
|
rate = Float(percentage) / 100
|
57
|
+
pinch = MultiTouch.new(driver)
|
32
58
|
|
33
|
-
if
|
34
|
-
top, bottom = pinch_for_xcuitest(rate)
|
35
|
-
elsif
|
59
|
+
if pinch.driver.automation_name_is_xcuitest?
|
60
|
+
top, bottom = pinch_for_xcuitest(rate, pinch.driver)
|
61
|
+
elsif pinch.driver.device_is_android?
|
36
62
|
top, bottom = pinch_android(rate)
|
37
63
|
else
|
38
64
|
top, bottom = pinch_ios(rate)
|
39
65
|
end
|
40
66
|
|
41
|
-
pinch = MultiTouch.new
|
42
67
|
pinch.add top
|
43
68
|
pinch.add bottom
|
44
69
|
return pinch unless auto_perform
|
@@ -49,25 +74,39 @@ module Appium
|
|
49
74
|
# Places two fingers at the edges of the screen and brings them together.
|
50
75
|
# @param percentage (int) The percent size by which to shrink the screen when pinched.
|
51
76
|
# @param auto_perform (boolean) Whether to perform the action immediately (default true)
|
77
|
+
# @param driver (Driver) Set a driver to conduct the action. DEfault is global driver($driver)
|
52
78
|
#
|
53
79
|
# ```ruby
|
54
80
|
# action = zoom 200 #=> Zoom in the screen from the center until it doubles in size.
|
55
|
-
# action.perform
|
56
81
|
# ```
|
57
|
-
|
82
|
+
#
|
83
|
+
# Without auto_perform
|
84
|
+
#
|
85
|
+
# ```ruby
|
86
|
+
# action = zoom 200, false #=> Zoom in the screen from the center until it doubles in size.
|
87
|
+
# action.perform #=> to 25% of its size.
|
88
|
+
# ```
|
89
|
+
#
|
90
|
+
# With driver
|
91
|
+
#
|
92
|
+
# ```ruby
|
93
|
+
# driver = Appium::Driver.new(opts, false).start_driver
|
94
|
+
# pinch 200, true, driver #=> Zoom in the screen from the center until it doubles in size.
|
95
|
+
# ```
|
96
|
+
def zoom(percentage = 200, auto_perform = true, driver = $driver)
|
58
97
|
raise ArgumentError("Can't zoom to smaller then screen size.") if percentage < 100
|
59
98
|
|
60
99
|
rate = 100 / Float(percentage)
|
100
|
+
zoom = MultiTouch.new(driver)
|
61
101
|
|
62
|
-
if
|
63
|
-
top, bottom = zoom_for_xcuitest(rate)
|
64
|
-
elsif
|
102
|
+
if zoom.driver.automation_name_is_xcuitest?
|
103
|
+
top, bottom = zoom_for_xcuitest(rate, zoom.driver)
|
104
|
+
elsif zoom.driver.device_is_android?
|
65
105
|
top, bottom = zoom_android(rate)
|
66
106
|
else
|
67
107
|
top, bottom = zoom_ios(rate)
|
68
108
|
end
|
69
109
|
|
70
|
-
zoom = MultiTouch.new
|
71
110
|
zoom.add top
|
72
111
|
zoom.add bottom
|
73
112
|
return zoom unless auto_perform
|
@@ -76,10 +115,10 @@ module Appium
|
|
76
115
|
|
77
116
|
private
|
78
117
|
|
79
|
-
def pinch_for_xcuitest(rate)
|
118
|
+
def pinch_for_xcuitest(rate, driver)
|
80
119
|
height = 100
|
81
120
|
|
82
|
-
ele =
|
121
|
+
ele = driver.find_element :class, 'XCUIElementTypeApplication'
|
83
122
|
top = TouchAction.new
|
84
123
|
top.swipe({ start_x: 0.5, start_y: 0.0,
|
85
124
|
offset_x: 0.0, offset_y: (1 - rate) * height }, ele)
|
@@ -119,10 +158,10 @@ module Appium
|
|
119
158
|
[top, bottom]
|
120
159
|
end
|
121
160
|
|
122
|
-
def zoom_for_xcuitest(rate)
|
161
|
+
def zoom_for_xcuitest(rate, driver)
|
123
162
|
height = 100
|
124
163
|
|
125
|
-
ele =
|
164
|
+
ele = driver.find_element :class, 'XCUIElementTypeApplication'
|
126
165
|
top = TouchAction.new
|
127
166
|
top.swipe({ start_x: 0.5, start_y: (1 - rate) * height,
|
128
167
|
offset_x: 0.0, offset_y: - (1 - rate) * height }, ele)
|
@@ -163,11 +202,12 @@ module Appium
|
|
163
202
|
end
|
164
203
|
end # self
|
165
204
|
|
166
|
-
attr_reader :actions
|
205
|
+
attr_reader :actions, :driver
|
167
206
|
|
168
|
-
# Create a new multi-action
|
169
|
-
def initialize
|
207
|
+
# Create a new multi-action with Driver
|
208
|
+
def initialize(driver = $driver)
|
170
209
|
@actions = []
|
210
|
+
@driver = driver
|
171
211
|
end
|
172
212
|
|
173
213
|
# Add a touch_action to be performed
|
@@ -178,7 +218,7 @@ module Appium
|
|
178
218
|
|
179
219
|
# Ask Appium to perform the actions
|
180
220
|
def perform
|
181
|
-
|
221
|
+
@driver.multi_touch @actions
|
182
222
|
@actions.clear
|
183
223
|
end
|
184
224
|
end # class MultiTouch
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Appium
|
2
2
|
# Perform a series of gestures, one after another. Gestures are chained
|
3
|
-
# together and only performed when `perform()` is called.
|
3
|
+
# together and only performed when `perform()` is called. Default is conducted by global driver.
|
4
4
|
#
|
5
5
|
# Each method returns the object itself, so calls can be chained.
|
6
6
|
#
|
@@ -17,7 +17,15 @@ module Appium
|
|
17
17
|
# # called `swipe(...).perform` in this method.
|
18
18
|
# swipe(start_x: 75, start_y: 500, offset_x: 75, offset_y: 20, duration: 500)
|
19
19
|
# ```
|
20
|
-
|
20
|
+
#
|
21
|
+
# If you'd like to perform the chain with an arbitrary driver:
|
22
|
+
# ```ruby
|
23
|
+
# driver = Appium::Driver.new(opts, false).start_driver
|
24
|
+
# action = TouchAction.new.press(x: 45, y: 100).wait(5).release
|
25
|
+
# action.perform(@driver)
|
26
|
+
# action = TouchAction.new.swipe(....)
|
27
|
+
# action.perform(@driver)
|
28
|
+
# ```
|
21
29
|
class TouchAction
|
22
30
|
ACTIONS = [:move_to, :long_press, :double_tap, :two_finger_tap, :press, :release, :tap, :wait, :perform].freeze
|
23
31
|
COMPLEX_ACTIONS = [:swipe].freeze
|
@@ -176,21 +184,22 @@ module Appium
|
|
176
184
|
end
|
177
185
|
|
178
186
|
# Ask the driver to perform all actions in this action chain.
|
179
|
-
def perform
|
180
|
-
|
187
|
+
def perform(driver = $driver)
|
188
|
+
driver.touch_actions @actions
|
181
189
|
@actions.clear
|
182
190
|
self
|
183
191
|
end
|
184
192
|
|
185
193
|
# Does nothing, currently.
|
186
|
-
def cancel
|
194
|
+
def cancel(driver = $driver)
|
187
195
|
@actions << { action: cancel }
|
188
|
-
|
196
|
+
driver.touch_actions @actions
|
189
197
|
self
|
190
198
|
end
|
191
199
|
|
192
|
-
|
193
|
-
|
200
|
+
# Visible for testing
|
201
|
+
def swipe_coordinates(end_x: nil, end_y: nil, offset_x: nil, offset_y: nil, driver: $driver)
|
202
|
+
if driver.device_is_android?
|
194
203
|
puts 'end_x and end_y are used for Android. Not offset_x and offset_y.' if end_x.nil? || end_y.nil?
|
195
204
|
end_x ||= 0
|
196
205
|
end_y ||= 0
|
data/lib/appium_lib/driver.rb
CHANGED
@@ -24,7 +24,17 @@ require_relative 'ios/element/generic'
|
|
24
24
|
require_relative 'ios/element/textfield'
|
25
25
|
require_relative 'ios/element/text'
|
26
26
|
require_relative 'ios/mobile_methods'
|
27
|
-
|
27
|
+
|
28
|
+
# ios - xcuitest
|
29
|
+
require_relative 'ios/xcuitest/element'
|
30
|
+
require_relative 'ios/xcuitest/gestures'
|
31
|
+
require_relative 'ios/xcuitest/mobile_methods'
|
32
|
+
require_relative 'ios/xcuitest/device'
|
33
|
+
require_relative 'ios/xcuitest/helper'
|
34
|
+
require_relative 'ios/xcuitest/element/text'
|
35
|
+
require_relative 'ios/xcuitest/element/textfield'
|
36
|
+
require_relative 'ios/xcuitest/element/generic'
|
37
|
+
require_relative 'ios/xcuitest/element/button'
|
28
38
|
|
29
39
|
# android
|
30
40
|
require_relative 'android/helper'
|
@@ -37,6 +47,11 @@ require_relative 'android/element/textfield'
|
|
37
47
|
require_relative 'android/element/text'
|
38
48
|
require_relative 'android/mobile_methods'
|
39
49
|
|
50
|
+
require_relative 'android/device'
|
51
|
+
|
52
|
+
# android - uiautomator2
|
53
|
+
require_relative 'android/uiautomator2/helper.rb'
|
54
|
+
|
40
55
|
# device methods
|
41
56
|
require_relative 'device/device'
|
42
57
|
require_relative 'device/touch_actions'
|
@@ -168,8 +183,8 @@ module Appium
|
|
168
183
|
# if modules is a module instead of an array, then the constants of
|
169
184
|
# that module are promoted on.
|
170
185
|
# otherwise, the array of modules will be used as the promotion target.
|
171
|
-
def self.promote_singleton_appium_methods(modules)
|
172
|
-
raise '
|
186
|
+
def self.promote_singleton_appium_methods(modules, driver = $driver)
|
187
|
+
raise 'Global $driver is nil' if driver.nil?
|
173
188
|
|
174
189
|
target_modules = []
|
175
190
|
|
@@ -185,15 +200,15 @@ module Appium
|
|
185
200
|
target_modules.each do |const|
|
186
201
|
# noinspection RubyResolve
|
187
202
|
# rubocop:disable Style/MultilineIfModifier
|
188
|
-
|
203
|
+
driver.public_methods(false).each do |m|
|
189
204
|
const.send(:define_singleton_method, m) do |*args, &block|
|
190
205
|
begin
|
191
206
|
super(*args, &block) # promote.rb
|
192
207
|
rescue NoMethodError, ArgumentError
|
193
|
-
|
208
|
+
driver.send m, *args, &block if driver.respond_to?(m)
|
194
209
|
end
|
195
210
|
# override unless there's an existing method with matching arity
|
196
|
-
end unless const.respond_to?(m) && const.method(m).arity ==
|
211
|
+
end unless const.respond_to?(m) && const.method(m).arity == driver.method(m).arity
|
197
212
|
end
|
198
213
|
# rubocop:enable Style/MultilineIfModifier
|
199
214
|
end
|
@@ -221,13 +236,13 @@ module Appium
|
|
221
236
|
# # promote on minispec
|
222
237
|
# Appium.promote_appium_methods Minitest::Spec
|
223
238
|
# ```
|
224
|
-
def self.promote_appium_methods(class_array)
|
225
|
-
raise 'Driver is nil' if
|
239
|
+
def self.promote_appium_methods(class_array, driver = $driver)
|
240
|
+
raise 'Driver is nil' if driver.nil?
|
226
241
|
# Wrap single class into an array
|
227
242
|
class_array = [class_array] unless class_array.class == Array
|
228
243
|
# Promote Appium driver methods to class instance methods.
|
229
244
|
class_array.each do |klass|
|
230
|
-
|
245
|
+
driver.public_methods(false).each do |m|
|
231
246
|
klass.class_eval do
|
232
247
|
define_method m do |*args, &block|
|
233
248
|
begin
|
@@ -239,7 +254,7 @@ module Appium
|
|
239
254
|
# so rescue argument error
|
240
255
|
# and call the name method on $driver
|
241
256
|
rescue NoMethodError, ArgumentError
|
242
|
-
|
257
|
+
driver.send m, *args, &block if driver.respond_to?(m)
|
243
258
|
end
|
244
259
|
end
|
245
260
|
end
|
@@ -320,7 +335,8 @@ module Appium
|
|
320
335
|
# @return [Integer]
|
321
336
|
attr_reader :appium_wait_interval
|
322
337
|
|
323
|
-
# Creates a new driver
|
338
|
+
# Creates a new driver. The driver is defined as global scope by default.
|
339
|
+
# We can avoid defining global driver.
|
324
340
|
#
|
325
341
|
# @example
|
326
342
|
#
|
@@ -330,7 +346,7 @@ module Appium
|
|
330
346
|
#
|
331
347
|
# # platformName takes a string or a symbol.
|
332
348
|
#
|
333
|
-
# # Start iOS driver
|
349
|
+
# # Start iOS driver with global scope
|
334
350
|
# opts = {
|
335
351
|
# caps: {
|
336
352
|
# platformName: :ios,
|
@@ -342,7 +358,7 @@ module Appium
|
|
342
358
|
# }
|
343
359
|
# Appium::Driver.new(opts).start_driver
|
344
360
|
#
|
345
|
-
# # Start Android driver
|
361
|
+
# # Start Android driver with global scope
|
346
362
|
# opts = {
|
347
363
|
# caps: {
|
348
364
|
# platformName: :android,
|
@@ -354,13 +370,30 @@ module Appium
|
|
354
370
|
# }
|
355
371
|
# }
|
356
372
|
# Appium::Driver.new(opts).start_driver
|
373
|
+
#
|
374
|
+
# # Start iOS driver without global scope
|
375
|
+
# opts = {
|
376
|
+
# caps: {
|
377
|
+
# platformName: :ios,
|
378
|
+
# app: '/path/to/MyiOS.app'
|
379
|
+
# },
|
380
|
+
# appium_lib: {
|
381
|
+
# wait_timeout: 30
|
382
|
+
# }
|
383
|
+
# }
|
384
|
+
# Appium::Driver.new(opts, false).start_driver
|
357
385
|
# ```
|
358
386
|
#
|
359
387
|
# @param opts [Object] A hash containing various options.
|
388
|
+
# @param global_driver [Bool] A bool require global driver before initialize.
|
360
389
|
# @return [Driver]
|
361
|
-
def initialize(opts = {})
|
362
|
-
|
363
|
-
|
390
|
+
def initialize(opts = {}, global_driver = true)
|
391
|
+
if global_driver
|
392
|
+
warn '[DEPRECATION] Appium::Driver.new(opts) will not generate global driver by default.' \
|
393
|
+
'If you would like to generate the global driver dy default, ' \
|
394
|
+
'please initialise driver with Appium::Driver.new(opts, true)'
|
395
|
+
$driver.driver_quit if $driver
|
396
|
+
end
|
364
397
|
raise 'opts must be a hash' unless opts.is_a? Hash
|
365
398
|
|
366
399
|
opts = Appium.symbolize_keys opts
|
@@ -391,11 +424,19 @@ module Appium
|
|
391
424
|
|
392
425
|
if device_is_android?
|
393
426
|
extend Appium::Android
|
427
|
+
extend Appium::Android::Device
|
428
|
+
if automation_name_is_uiautomator2?
|
429
|
+
extend Appium::Android::Uiautomator2::Helper
|
430
|
+
end
|
394
431
|
else
|
395
432
|
extend Appium::Ios
|
396
|
-
if automation_name_is_xcuitest?
|
433
|
+
if automation_name_is_xcuitest?
|
434
|
+
# Override touch actions and patch_webdriver_element
|
397
435
|
extend Appium::Ios::Xcuitest
|
436
|
+
extend Appium::Ios::Xcuitest::Helper
|
398
437
|
extend Appium::Ios::Xcuitest::Gesture
|
438
|
+
extend Appium::Ios::Xcuitest::Device
|
439
|
+
extend Appium::Ios::Xcuitest::Element
|
399
440
|
end
|
400
441
|
end
|
401
442
|
|
@@ -417,7 +458,7 @@ module Appium
|
|
417
458
|
end
|
418
459
|
|
419
460
|
# Save global reference to last created Appium driver for top level methods.
|
420
|
-
$driver = self
|
461
|
+
$driver = self if global_driver
|
421
462
|
|
422
463
|
self # return newly created driver
|
423
464
|
end
|
@@ -485,6 +526,12 @@ module Appium
|
|
485
526
|
!@automation_name.nil? && @automation_name == :uiautomator2
|
486
527
|
end
|
487
528
|
|
529
|
+
# Return true if automationName is 'Espresso'
|
530
|
+
# @return [Boolean]
|
531
|
+
def automation_name_is_espresso?
|
532
|
+
!@automation_name.nil? && @automation_name == :espresso
|
533
|
+
end
|
534
|
+
|
488
535
|
# Return true if the target Appium server is over REQUIRED_VERSION_XCUITEST.
|
489
536
|
# If the Appium server is under REQUIRED_VERSION_XCUITEST, then error is raised.
|
490
537
|
# @return [Boolean]
|
@@ -617,6 +664,9 @@ module Appium
|
|
617
664
|
nil
|
618
665
|
end
|
619
666
|
|
667
|
+
# Alias for driver_quit
|
668
|
+
alias_method :quit_driver, :driver_quit
|
669
|
+
|
620
670
|
# Creates a new global driver and quits the old one if it exists.
|
621
671
|
# You can customise http_client as the following
|
622
672
|
#
|
@@ -677,11 +727,21 @@ module Appium
|
|
677
727
|
check_server_version_xcuitest
|
678
728
|
set_automation_name_if_nil
|
679
729
|
|
680
|
-
@
|
730
|
+
set_implicit_wait(@default_wait)
|
681
731
|
|
682
732
|
@driver
|
683
733
|
end
|
684
734
|
|
735
|
+
# To ignore error for Espresso Driver
|
736
|
+
def set_implicit_wait(wait)
|
737
|
+
@driver.manage.timeouts.implicit_wait = wait
|
738
|
+
rescue Selenium::WebDriver::Error::UnknownError => e
|
739
|
+
unless e.message.include?('The operation requested is not yet implemented by Espresso driver')
|
740
|
+
raise ::Appium::Error::ServerError
|
741
|
+
end
|
742
|
+
{}
|
743
|
+
end
|
744
|
+
|
685
745
|
# Set implicit wait to zero.
|
686
746
|
def no_wait
|
687
747
|
@driver.manage.timeouts.implicit_wait = 0
|