appium_lib 9.7.2 → 9.7.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/docs/android_docs.md +220 -168
- data/docs/docs.md +13 -37
- data/docs/ios_docs.md +278 -220
- data/docs/ios_xcuitest.md +0 -4
- data/docs/parallel.md +8 -0
- data/lib/appium_lib/android/android.rb +3 -0
- data/lib/appium_lib/android/common/helper.rb +3 -0
- data/lib/appium_lib/android/espresso.rb +9 -0
- data/lib/appium_lib/android/espresso/bridge.rb +14 -0
- data/lib/appium_lib/common/multi_touch.rb +151 -4
- data/lib/appium_lib/common/touch_actions.rb +21 -0
- data/lib/appium_lib/common/wait.rb +2 -22
- data/lib/appium_lib/core/android.rb +1 -0
- data/lib/appium_lib/core/android/espresso/bridge.rb +18 -0
- data/lib/appium_lib/core/android/touch.rb +15 -0
- data/lib/appium_lib/core/android/uiautomator1/bridge.rb +3 -1
- data/lib/appium_lib/core/android/uiautomator2/bridge.rb +3 -1
- data/lib/appium_lib/core/android_espresso.rb +5 -0
- data/lib/appium_lib/core/android_uiautomator2.rb +1 -0
- data/lib/appium_lib/core/core.rb +1 -1
- data/lib/appium_lib/core/device/touch_actions.rb +8 -23
- data/lib/appium_lib/core/driver.rb +93 -17
- data/lib/appium_lib/core/ios.rb +1 -0
- data/lib/appium_lib/core/ios/touch.rb +16 -0
- data/lib/appium_lib/core/ios/uiautomation/bridge.rb +2 -0
- data/lib/appium_lib/core/ios/xcuitest/bridge.rb +2 -0
- data/lib/appium_lib/core/ios/xcuitest/search_context.rb +23 -12
- data/lib/appium_lib/core/ios_xcuitest.rb +1 -0
- data/lib/appium_lib/driver.rb +18 -15
- data/lib/appium_lib/ios/xcuitest/bridge.rb +1 -0
- data/lib/appium_lib/ios/xcuitest/command.rb +1 -0
- data/lib/appium_lib/ios/xcuitest/command/source.rb +20 -0
- data/lib/appium_lib/version.rb +2 -2
- data/readme.md +14 -29
- data/release_notes.md +8 -0
- metadata +10 -3
- data/lib/appium_lib/core/device/multi_touch.rb +0 -213
data/docs/ios_xcuitest.md
CHANGED
@@ -8,10 +8,6 @@
|
|
8
8
|
- [ios-xctest-mobile-gestures](https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/ios-xctest-mobile-gestures.md)
|
9
9
|
- Required Appium1.6.4+
|
10
10
|
|
11
|
-
## Run tests on Multiple Simulators with Xcode 9
|
12
|
-
- https://github.com/appium/appium-xcuitest-driver/tree/master/test/functional/parallel
|
13
|
-
- https://github.com/appium/ruby_lib/tree/master/ios_tests/parallel
|
14
|
-
|
15
11
|
## find elements
|
16
12
|
- supported elements by find_element are:
|
17
13
|
- [appium-xcuitest-driver](https://github.com/appium/appium-xcuitest-driver/blob/master/lib/commands/find.js#L17)
|
data/docs/parallel.md
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
Appium 1.7.0+ supports single server and multiple sessions, and it requires Xcode 9 for iOS.
|
2
|
+
|
3
|
+
# Example
|
4
|
+
## Run tests on Multiple Simulators with Xcode 9
|
5
|
+
- https://github.com/appium/appium-xcuitest-driver/tree/master/test/functional/parallel
|
6
|
+
- https://github.com/appium/ruby_lib/tree/master/ios_tests/parallel
|
7
|
+
- Thread programming: TestParallelRunThread
|
8
|
+
- Process programming: TestParallelRunProcess
|
@@ -122,6 +122,9 @@ module Appium
|
|
122
122
|
# "mFocusedApp=AppWindowToken{b1420058 token=Token{b128add0
|
123
123
|
# ActivityRecord{b1264d10 u0 com.example.android.apis/.ApiDemos t23}}}"
|
124
124
|
def current_app
|
125
|
+
warn '[DEPRECATION] current_app will be removed since it work only local.' \
|
126
|
+
'Please use current_activity and current_app to know package and activity for current app'
|
127
|
+
|
125
128
|
line = `adb shell dumpsys window windows`.each_line.grep(/mFocusedApp/).first.strip
|
126
129
|
|
127
130
|
_parse_current_app_line line
|
@@ -23,7 +23,7 @@ module Appium
|
|
23
23
|
# multi_touch_action.add action_2
|
24
24
|
# multi_touch_action.perform
|
25
25
|
#
|
26
|
-
class MultiTouch
|
26
|
+
class MultiTouch
|
27
27
|
class << self
|
28
28
|
# Convenience method for pinching the screen.
|
29
29
|
# Places two fingers at the edges of the screen and brings them together.
|
@@ -49,7 +49,23 @@ module Appium
|
|
49
49
|
# pinch 75, true, driver #=> Pinch the screen from the top right and bottom left corners
|
50
50
|
#
|
51
51
|
def pinch(percentage = 25, auto_perform = true, driver = $driver)
|
52
|
-
|
52
|
+
raise ArgumentError("Can't pinch to greater than screen size.") if percentage > 100
|
53
|
+
|
54
|
+
rate = Float(percentage) / 100
|
55
|
+
pinch = MultiTouch.new(driver)
|
56
|
+
|
57
|
+
if driver.automation_name_is_xcuitest?
|
58
|
+
top, bottom = pinch_for_xcuitest(rate, pinch.driver)
|
59
|
+
elsif driver.device_is_android?
|
60
|
+
top, bottom = pinch_android(rate, pinch.driver)
|
61
|
+
else
|
62
|
+
top, bottom = pinch_ios(rate, pinch.driver)
|
63
|
+
end
|
64
|
+
|
65
|
+
pinch.add top
|
66
|
+
pinch.add bottom
|
67
|
+
return pinch unless auto_perform
|
68
|
+
pinch.perform
|
53
69
|
end
|
54
70
|
|
55
71
|
# Convenience method for zooming the screen.
|
@@ -77,12 +93,143 @@ module Appium
|
|
77
93
|
# pinch 200, true, driver #=> Zoom in the screen from the center until it doubles in size.
|
78
94
|
#
|
79
95
|
def zoom(percentage = 200, auto_perform = true, driver = $driver)
|
80
|
-
|
96
|
+
raise ArgumentError("Can't zoom to smaller then screen size.") if percentage < 100
|
97
|
+
|
98
|
+
rate = 100 / Float(percentage)
|
99
|
+
zoom = MultiTouch.new(driver)
|
100
|
+
|
101
|
+
if driver.automation_name_is_xcuitest?
|
102
|
+
top, bottom = zoom_for_xcuitest(rate, zoom.driver)
|
103
|
+
elsif driver.device_is_android?
|
104
|
+
top, bottom = zoom_android(rate, zoom.driver)
|
105
|
+
else
|
106
|
+
top, bottom = zoom_ios(rate, zoom.driver)
|
107
|
+
end
|
108
|
+
|
109
|
+
zoom.add top
|
110
|
+
zoom.add bottom
|
111
|
+
return zoom unless auto_perform
|
112
|
+
zoom.perform
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
# @private
|
118
|
+
def pinch_android(rate, driver)
|
119
|
+
height = 100
|
120
|
+
offset = 100
|
121
|
+
|
122
|
+
top = ::Appium::Core::TouchAction.new(driver)
|
123
|
+
top.swipe start_x: offset, start_y: 1.0 * height + offset,
|
124
|
+
offset_x: 0.0, offset_y: (rate - 1) * height, duration: 1_000
|
125
|
+
|
126
|
+
bottom = ::Appium::Core::TouchAction.new(driver)
|
127
|
+
bottom.swipe start_x: offset, start_y: 0.0 + offset,
|
128
|
+
offset_x: 0.0, offset_y: (1 - rate) * height, duration: 1_000
|
129
|
+
|
130
|
+
[top, bottom]
|
131
|
+
end
|
132
|
+
|
133
|
+
# @private
|
134
|
+
def pinch_for_xcuitest(rate, driver)
|
135
|
+
height = 100
|
136
|
+
offset = 100
|
137
|
+
|
138
|
+
ele = driver.find_element :class, 'XCUIElementTypeApplication'
|
139
|
+
top = ::Appium::Core::TouchAction.new(driver)
|
140
|
+
top.swipe({ start_x: 0.5, start_y: 0.0 + offset,
|
141
|
+
offset_x: 0.0, offset_y: (1 - rate) * height }, ele)
|
142
|
+
|
143
|
+
bottom = ::Appium::Core::TouchAction.new(driver)
|
144
|
+
bottom.swipe({ start_x: 0.5, start_y: 1.0 + offset,
|
145
|
+
offset_x: 0.0, offset_y: rate * height }, ele)
|
146
|
+
|
147
|
+
[top, bottom]
|
148
|
+
end
|
149
|
+
|
150
|
+
# @private
|
151
|
+
def pinch_ios(rate, driver)
|
152
|
+
height = 100
|
153
|
+
offset = 100
|
154
|
+
|
155
|
+
top = ::Appium::Core::TouchAction.new(driver)
|
156
|
+
top.swipe start_x: 0.5, start_y: 0.0 + offset,
|
157
|
+
offset_x: 0.0, offset_y: (1 - rate) * height, duration: 1_000
|
158
|
+
|
159
|
+
bottom = ::Appium::Core::TouchAction.new(driver)
|
160
|
+
bottom.swipe start_x: 0.5, start_y: 1.0 + offset,
|
161
|
+
offset_x: 0.0, offset_y: rate * height, duration: 1_000
|
162
|
+
|
163
|
+
[top, bottom]
|
164
|
+
end
|
165
|
+
|
166
|
+
# @private
|
167
|
+
def zoom_android(rate, driver)
|
168
|
+
height = 100
|
169
|
+
offset = 100
|
170
|
+
|
171
|
+
top = ::Appium::Core::TouchAction.new(driver)
|
172
|
+
top.swipe start_x: offset, start_y: (1.0 - rate) * height + offset,
|
173
|
+
offset_x: 0.0, offset_y: (rate - 1.0) * height, duration: 1_000
|
174
|
+
|
175
|
+
bottom = ::Appium::Core::TouchAction.new(driver)
|
176
|
+
bottom.swipe start_x: offset, start_y: rate * height + offset,
|
177
|
+
offset_x: 0.0, offset_y: (1.0 - rate) * height, duration: 1_000
|
178
|
+
|
179
|
+
[top, bottom]
|
180
|
+
end
|
181
|
+
|
182
|
+
# @private
|
183
|
+
def zoom_for_xcuitest(rate, driver)
|
184
|
+
height = 100
|
185
|
+
offset = 100
|
186
|
+
|
187
|
+
ele = driver.find_element :class, 'XCUIElementTypeApplication'
|
188
|
+
top = ::Appium::Core::TouchAction.new(driver)
|
189
|
+
top.swipe({ start_x: 0.5, start_y: (1 - rate) * height + offset,
|
190
|
+
offset_x: 0.0, offset_y: - (1 - rate) * height }, ele)
|
191
|
+
|
192
|
+
bottom = ::Appium::Core::TouchAction.new(driver)
|
193
|
+
bottom.swipe({ start_x: 0.5, start_y: rate * height + offset,
|
194
|
+
offset_x: 0.0, offset_y: (1 - rate) * height }, ele)
|
195
|
+
|
196
|
+
[top, bottom]
|
197
|
+
end
|
198
|
+
|
199
|
+
# @private
|
200
|
+
def zoom_ios(rate, driver)
|
201
|
+
height = 100
|
202
|
+
offset = 100
|
203
|
+
|
204
|
+
top = ::Appium::Core::TouchAction.new(driver)
|
205
|
+
top.swipe start_x: 0.5, start_y: (1 - rate) * height + offset,
|
206
|
+
offset_x: 0.0, offset_y: - (1 - rate) * height, duration: 1_000
|
207
|
+
|
208
|
+
bottom = ::Appium::Core::TouchAction.new(driver)
|
209
|
+
bottom.swipe start_x: 0.5, start_y: rate * height + offset,
|
210
|
+
offset_x: 0.0, offset_y: (1 - rate) * height, duration: 1_000
|
211
|
+
|
212
|
+
[top, bottom]
|
81
213
|
end
|
82
214
|
end # self
|
83
215
|
|
216
|
+
attr_reader :driver
|
217
|
+
|
84
218
|
def initialize(driver = $driver)
|
85
|
-
|
219
|
+
@actions = []
|
220
|
+
@driver = driver
|
221
|
+
end
|
222
|
+
|
223
|
+
# Add a touch_action to be performed
|
224
|
+
# @param chain (TouchAction) The action to add to the chain
|
225
|
+
def add(chain)
|
226
|
+
@actions << chain.actions
|
227
|
+
end
|
228
|
+
|
229
|
+
# Ask Appium to perform the actions
|
230
|
+
def perform
|
231
|
+
@driver.multi_touch @actions
|
232
|
+
@actions.clear
|
86
233
|
end
|
87
234
|
end # class MultiTouch
|
88
235
|
end # module Appium
|
@@ -47,5 +47,26 @@ module Appium
|
|
47
47
|
def initialize(driver = $driver)
|
48
48
|
super driver
|
49
49
|
end
|
50
|
+
|
51
|
+
def swipe(opts, ele = nil)
|
52
|
+
start_x = opts.fetch :start_x, 0
|
53
|
+
start_y = opts.fetch :start_y, 0
|
54
|
+
offset_x = opts.fetch :offset_x, nil
|
55
|
+
offset_y = opts.fetch :offset_y, nil
|
56
|
+
end_x = opts.fetch :end_x, nil
|
57
|
+
end_y = opts.fetch :end_y, nil
|
58
|
+
duration = opts.fetch :duration, 200
|
59
|
+
|
60
|
+
if end_x || end_y
|
61
|
+
warn '[DEPRECATION] end_x and end_y will be removed. Please use offset_x and offset_y for all platform.'
|
62
|
+
end_x ||= 0
|
63
|
+
end_y ||= 0
|
64
|
+
|
65
|
+
offset_x = end_x - start_x
|
66
|
+
offset_y = end_y - start_y
|
67
|
+
end
|
68
|
+
|
69
|
+
super(start_x: start_x, start_y: start_y, offset_x: offset_x, offset_y: offset_y, duration: duration, ele: ele)
|
70
|
+
end
|
50
71
|
end # class TouchAction
|
51
72
|
end # module Appium
|
@@ -8,14 +8,6 @@ module Appium
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
# process opts before calling _generic_wait
|
12
|
-
# @private
|
13
|
-
def _process_wait_opts(opts)
|
14
|
-
opts = { timeout: opts } if opts.is_a?(Numeric)
|
15
|
-
raise 'opts must be a hash' unless opts.is_a? Hash
|
16
|
-
opts
|
17
|
-
end
|
18
|
-
|
19
11
|
# Check every interval seconds to see if yield returns a truthy value.
|
20
12
|
# Note this isn't a strict boolean true, any truthy value is accepted.
|
21
13
|
# false and nil are considered failures.
|
@@ -32,13 +24,7 @@ module Appium
|
|
32
24
|
# @option opts [String] :message Exception message if timed out.
|
33
25
|
# @option opts [Array, Exception] :ignore Exceptions to ignore while polling (default: Exception)
|
34
26
|
def wait_true(opts = {})
|
35
|
-
|
36
|
-
|
37
|
-
opts[:timeout] ||= @core.wait_timeout
|
38
|
-
opts[:interval] ||= @core.wait_interval
|
39
|
-
|
40
|
-
wait = ::Appium::Common::Wait.new opts
|
41
|
-
wait.until { yield }
|
27
|
+
@core.wait_true(opts) { yield }
|
42
28
|
end
|
43
29
|
|
44
30
|
# Check every interval seconds to see if yield doesn't raise an exception.
|
@@ -55,13 +41,7 @@ module Appium
|
|
55
41
|
# @option opts [String] :message Exception message if timed out.
|
56
42
|
# @option opts [Array, Exception] :ignore Exceptions to ignore while polling (default: Exception)
|
57
43
|
def wait(opts = {})
|
58
|
-
|
59
|
-
|
60
|
-
opts[:timeout] ||= @core.wait_timeout
|
61
|
-
opts[:interval] ||= @core.wait_interval
|
62
|
-
|
63
|
-
wait = ::Appium::Common::Wait.new opts
|
64
|
-
wait.until { yield }
|
44
|
+
@core.wait(opts) { yield }
|
65
45
|
end
|
66
46
|
end
|
67
47
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative '../../android_espresso'
|
2
|
+
|
3
|
+
module Appium
|
4
|
+
module Core
|
5
|
+
module Android
|
6
|
+
module Espresso
|
7
|
+
module Bridge
|
8
|
+
def self.for(target)
|
9
|
+
target.extend Appium::Android::Device
|
10
|
+
Core::Android::SearchContext.extend
|
11
|
+
|
12
|
+
Core::Android::Touch.extend_touch_actions
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Appium
|
2
|
+
module Core
|
3
|
+
module Android
|
4
|
+
module Touch
|
5
|
+
def self.extend_touch_actions
|
6
|
+
::Appium::Core::TouchAction.class_eval do
|
7
|
+
def swipe_coordinates(start_x: 0, start_y: 0, offset_x: 0, offset_y: 0)
|
8
|
+
{ offset_x: (start_x + offset_x), offset_y: (start_y + offset_y) }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/appium_lib/core/core.rb
CHANGED
@@ -6,10 +6,10 @@ require_relative 'driver'
|
|
6
6
|
|
7
7
|
# for multi touch related methods
|
8
8
|
require_relative 'device/touch_actions'
|
9
|
-
require_relative 'device/multi_touch'
|
10
9
|
|
11
10
|
require_relative 'android'
|
12
11
|
require_relative 'android_uiautomator2'
|
12
|
+
require_relative 'android_espresso'
|
13
13
|
|
14
14
|
require_relative 'ios'
|
15
15
|
require_relative 'ios_xcuitest'
|
@@ -128,21 +128,17 @@ module Appium
|
|
128
128
|
#
|
129
129
|
# @option opts [int] :start_x Where to start swiping, on the x axis. Default 0.
|
130
130
|
# @option opts [int] :start_y Where to start swiping, on the y axis. Default 0.
|
131
|
-
# @option opts [int] :offset_x
|
132
|
-
# @option opts [int] :offset_y
|
133
|
-
# @option opts [int] :end_x For Android. Where to end swiping, on the x axis. Default 0.
|
134
|
-
# @option opts [int] :end_y For Android. Where to end swiping, on the y axis. Default 0.
|
131
|
+
# @option opts [int] :offset_x Offset, on the x axis. Default 0.
|
132
|
+
# @option opts [int] :offset_y Offset, on the y axis. Default 0.
|
135
133
|
# @option opts [int] :duration How long the actual swipe takes to complete in milliseconds. Default 200.
|
136
134
|
def swipe(opts, ele = nil)
|
137
135
|
start_x = opts.fetch :start_x, 0
|
138
136
|
start_y = opts.fetch :start_y, 0
|
139
|
-
offset_x = opts.fetch :offset_x,
|
140
|
-
offset_y = opts.fetch :offset_y,
|
141
|
-
end_x = opts.fetch :end_x, nil
|
142
|
-
end_y = opts.fetch :end_y, nil
|
137
|
+
offset_x = opts.fetch :offset_x, 0
|
138
|
+
offset_y = opts.fetch :offset_y, 0
|
143
139
|
duration = opts.fetch :duration, 200
|
144
140
|
|
145
|
-
coordinates = swipe_coordinates(
|
141
|
+
coordinates = swipe_coordinates(start_x: start_x, start_y: start_y, offset_x: offset_x, offset_y: offset_y)
|
146
142
|
|
147
143
|
if ele # pinch/zoom for XCUITest
|
148
144
|
press x: start_x, y: start_y, element: ele
|
@@ -173,20 +169,9 @@ module Appium
|
|
173
169
|
|
174
170
|
# Visible for testing
|
175
171
|
# @private
|
176
|
-
def swipe_coordinates(
|
177
|
-
|
178
|
-
|
179
|
-
end_x ||= 0
|
180
|
-
end_y ||= 0
|
181
|
-
return { offset_x: end_x, offset_y: end_y }
|
182
|
-
elsif offset_x.nil? || offset_y.nil?
|
183
|
-
puts 'offset_x and offset_y are used for iOS. Not end_x and end_y point.'
|
184
|
-
end
|
185
|
-
|
186
|
-
offset_x ||= 0
|
187
|
-
offset_y ||= 0
|
188
|
-
|
189
|
-
{ offset_x: offset_x, offset_y: offset_y }
|
172
|
+
def swipe_coordinates(start_x: 0, start_y: 0, offset_x: 0, offset_y: 0)
|
173
|
+
raise NotImplementedError,
|
174
|
+
"Please define swipe_coordinates with #{start_x}, #{start_y}, #{offset_x}, #{offset_y}"
|
190
175
|
end
|
191
176
|
|
192
177
|
private
|