appium_lib 9.5.0 → 9.6.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/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
|