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.
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