appium_lib 9.7.2 → 9.7.3

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/docs/android_docs.md +220 -168
  4. data/docs/docs.md +13 -37
  5. data/docs/ios_docs.md +278 -220
  6. data/docs/ios_xcuitest.md +0 -4
  7. data/docs/parallel.md +8 -0
  8. data/lib/appium_lib/android/android.rb +3 -0
  9. data/lib/appium_lib/android/common/helper.rb +3 -0
  10. data/lib/appium_lib/android/espresso.rb +9 -0
  11. data/lib/appium_lib/android/espresso/bridge.rb +14 -0
  12. data/lib/appium_lib/common/multi_touch.rb +151 -4
  13. data/lib/appium_lib/common/touch_actions.rb +21 -0
  14. data/lib/appium_lib/common/wait.rb +2 -22
  15. data/lib/appium_lib/core/android.rb +1 -0
  16. data/lib/appium_lib/core/android/espresso/bridge.rb +18 -0
  17. data/lib/appium_lib/core/android/touch.rb +15 -0
  18. data/lib/appium_lib/core/android/uiautomator1/bridge.rb +3 -1
  19. data/lib/appium_lib/core/android/uiautomator2/bridge.rb +3 -1
  20. data/lib/appium_lib/core/android_espresso.rb +5 -0
  21. data/lib/appium_lib/core/android_uiautomator2.rb +1 -0
  22. data/lib/appium_lib/core/core.rb +1 -1
  23. data/lib/appium_lib/core/device/touch_actions.rb +8 -23
  24. data/lib/appium_lib/core/driver.rb +93 -17
  25. data/lib/appium_lib/core/ios.rb +1 -0
  26. data/lib/appium_lib/core/ios/touch.rb +16 -0
  27. data/lib/appium_lib/core/ios/uiautomation/bridge.rb +2 -0
  28. data/lib/appium_lib/core/ios/xcuitest/bridge.rb +2 -0
  29. data/lib/appium_lib/core/ios/xcuitest/search_context.rb +23 -12
  30. data/lib/appium_lib/core/ios_xcuitest.rb +1 -0
  31. data/lib/appium_lib/driver.rb +18 -15
  32. data/lib/appium_lib/ios/xcuitest/bridge.rb +1 -0
  33. data/lib/appium_lib/ios/xcuitest/command.rb +1 -0
  34. data/lib/appium_lib/ios/xcuitest/command/source.rb +20 -0
  35. data/lib/appium_lib/version.rb +2 -2
  36. data/readme.md +14 -29
  37. data/release_notes.md +8 -0
  38. metadata +10 -3
  39. data/lib/appium_lib/core/device/multi_touch.rb +0 -213
@@ -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)
@@ -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
@@ -9,6 +9,9 @@ require_relative 'element/text'
9
9
  # android - uiautomator2
10
10
  require_relative 'uiautomator2'
11
11
 
12
+ # android - espresso
13
+ require_relative 'espresso'
14
+
12
15
  module Appium
13
16
  module Android
14
17
  class Bridge
@@ -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
@@ -0,0 +1,9 @@
1
+ require_relative 'espresso/bridge'
2
+
3
+ module Appium
4
+ module Android
5
+ module Espresso
6
+ # parent
7
+ end # module Uiautomator2
8
+ end # module Android
9
+ end # module Appium
@@ -0,0 +1,14 @@
1
+ require_relative '../android'
2
+
3
+ module Appium
4
+ module Android
5
+ module Espresso
6
+ class Bridge
7
+ def self.for(target)
8
+ target.extend Appium::Android
9
+ target.extend Appium::Android::Espresso
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -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 < ::Appium::Core::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
- ::Appium::Core::MultiTouch.pinch percentage: percentage, auto_perform: auto_perform, driver: driver
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
- ::Appium::Core::MultiTouch.zoom percentage: percentage, auto_perform: auto_perform, driver: driver
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
- super driver
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
- opts = _process_wait_opts(opts).merge(return_if_true: true)
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
- opts = _process_wait_opts(opts).merge(return_if_true: false)
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
@@ -1,4 +1,5 @@
1
1
  # loaded in common/driver.rb
2
2
  require_relative 'android/search_context'
3
3
  require_relative 'android/device'
4
+ require_relative 'android/touch'
4
5
  require_relative 'android/uiautomator1/bridge'
@@ -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
@@ -7,7 +7,9 @@ module Appium
7
7
  module Bridge
8
8
  def self.for(target)
9
9
  target.extend Appium::Android::Device
10
- ::Appium::Core::Android::SearchContext.extend
10
+ Core::Android::SearchContext.extend
11
+
12
+ Core::Android::Touch.extend_touch_actions
11
13
  end
12
14
  end
13
15
  end
@@ -7,7 +7,9 @@ module Appium
7
7
  module Bridge
8
8
  def self.for(target)
9
9
  target.extend Appium::Android::Device
10
- ::Appium::Core::Android::SearchContext.extend
10
+ Core::Android::SearchContext.extend
11
+
12
+ Core::Android::Touch.extend_touch_actions
11
13
  end
12
14
  end
13
15
  end
@@ -0,0 +1,5 @@
1
+ # loaded in common/driver.rb
2
+ require_relative 'android/search_context'
3
+ require_relative 'android/device'
4
+ require_relative 'android/touch'
5
+ require_relative 'android/espresso/bridge'
@@ -1,4 +1,5 @@
1
1
  # loaded in common/driver.rb
2
2
  require_relative 'android/search_context'
3
3
  require_relative 'android/device'
4
+ require_relative 'android/touch'
4
5
  require_relative 'android/uiautomator2/bridge'
@@ -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 For iOS. Offset, on the x axis. Default 0.
132
- # @option opts [int] :offset_y For iOS. Offset, on the y axis. Default 0.
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, nil
140
- offset_y = opts.fetch :offset_y, nil
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(end_x: end_x, end_y: end_y, offset_x: offset_x, offset_y: offset_y)
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(end_x: nil, end_y: nil, offset_x: nil, offset_y: nil)
177
- if @driver.device_is_android?
178
- puts 'end_x and end_y are used for Android. Not offset_x and offset_y.' if end_x.nil? || end_y.nil?
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