calabash 1.9.9.pre3 → 2.0.0.prelegacy

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -33
  3. data/bin/calabash +45 -36
  4. data/lib/calabash.rb +137 -13
  5. data/lib/calabash/android.rb +6 -0
  6. data/lib/calabash/android/adb.rb +25 -1
  7. data/lib/calabash/android/application.rb +14 -3
  8. data/lib/calabash/android/build/builder.rb +16 -3
  9. data/lib/calabash/android/build/java_keystore.rb +10 -0
  10. data/lib/calabash/android/build/resigner.rb +23 -1
  11. data/lib/calabash/android/build/test_server.rb +2 -0
  12. data/lib/calabash/android/defaults.rb +1 -0
  13. data/lib/calabash/android/device.rb +55 -3
  14. data/lib/calabash/android/environment.rb +10 -0
  15. data/lib/calabash/android/interactions.rb +106 -3
  16. data/lib/calabash/android/legacy.rb +143 -0
  17. data/lib/calabash/android/lib/TestServer.apk +0 -0
  18. data/lib/calabash/android/life_cycle.rb +6 -4
  19. data/lib/calabash/android/physical_buttons.rb +12 -1
  20. data/lib/calabash/android/screenshot.rb +1 -0
  21. data/lib/calabash/android/scroll.rb +115 -0
  22. data/lib/calabash/android/server.rb +3 -1
  23. data/lib/calabash/android/text.rb +16 -25
  24. data/lib/calabash/application.rb +29 -0
  25. data/lib/calabash/cli/build.rb +15 -1
  26. data/lib/calabash/cli/console.rb +9 -5
  27. data/lib/calabash/cli/generate.rb +5 -0
  28. data/lib/calabash/cli/helpers.rb +7 -1
  29. data/lib/calabash/cli/resign.rb +1 -0
  30. data/lib/calabash/cli/run.rb +10 -6
  31. data/lib/calabash/cli/setup_keystore.rb +2 -0
  32. data/lib/calabash/color.rb +7 -0
  33. data/lib/calabash/console_helpers.rb +4 -2
  34. data/lib/calabash/defaults.rb +1 -0
  35. data/lib/calabash/device.rb +8 -9
  36. data/lib/calabash/environment.rb +5 -0
  37. data/lib/calabash/gestures.rb +159 -66
  38. data/lib/calabash/http/retriable_client.rb +3 -1
  39. data/lib/calabash/interactions.rb +68 -5
  40. data/lib/calabash/ios.rb +4 -0
  41. data/lib/calabash/ios/application.rb +8 -1
  42. data/lib/calabash/ios/conditions.rb +3 -1
  43. data/lib/calabash/ios/date_picker.rb +412 -0
  44. data/lib/calabash/ios/defaults.rb +1 -0
  45. data/lib/calabash/ios/device.rb +1 -0
  46. data/lib/calabash/ios/device/device_implementation.rb +33 -16
  47. data/lib/calabash/ios/device/gestures_mixin.rb +202 -48
  48. data/lib/calabash/ios/device/ipad_1x_2x_mixin.rb +253 -0
  49. data/lib/calabash/ios/device/keyboard_mixin.rb +2 -0
  50. data/lib/calabash/ios/device/rotation_mixin.rb +11 -8
  51. data/lib/calabash/ios/device/routes/condition_route_mixin.rb +1 -0
  52. data/lib/calabash/ios/device/routes/handle_route_mixin.rb +5 -1
  53. data/lib/calabash/ios/device/routes/map_route_mixin.rb +1 -0
  54. data/lib/calabash/ios/device/routes/response_parser.rb +1 -0
  55. data/lib/calabash/ios/device/routes/uia_route_mixin.rb +44 -6
  56. data/lib/calabash/ios/device/runtime_attributes.rb +4 -5
  57. data/lib/calabash/ios/device/text_mixin.rb +2 -0
  58. data/lib/calabash/ios/device/uia_keyboard_mixin.rb +9 -0
  59. data/lib/calabash/ios/device/uia_mixin.rb +1 -0
  60. data/lib/calabash/ios/gestures.rb +82 -8
  61. data/lib/calabash/ios/interactions.rb +30 -1
  62. data/lib/calabash/ios/orientation.rb +21 -21
  63. data/lib/calabash/ios/runtime.rb +154 -2
  64. data/lib/calabash/ios/slider.rb +70 -0
  65. data/lib/calabash/ios/text.rb +11 -47
  66. data/lib/calabash/ios/uia.rb +24 -2
  67. data/lib/calabash/legacy.rb +7 -0
  68. data/lib/calabash/lib/skeleton/config/cucumber.yml +1 -3
  69. data/lib/calabash/lib/skeleton/features/support/dry_run.rb +8 -0
  70. data/lib/calabash/lib/skeleton/features/support/env.rb +15 -1
  71. data/lib/calabash/life_cycle.rb +78 -32
  72. data/lib/calabash/location.rb +2 -1
  73. data/lib/calabash/orientation.rb +0 -1
  74. data/lib/calabash/page.rb +51 -5
  75. data/lib/calabash/patch.rb +1 -0
  76. data/lib/calabash/patch/array.rb +7 -7
  77. data/lib/calabash/query.rb +17 -2
  78. data/lib/calabash/query_result.rb +14 -0
  79. data/lib/calabash/screenshot.rb +28 -8
  80. data/lib/calabash/text.rb +105 -8
  81. data/lib/calabash/utility.rb +6 -6
  82. data/lib/calabash/version.rb +1 -1
  83. data/lib/calabash/wait.rb +37 -11
  84. metadata +14 -7
@@ -1,5 +1,6 @@
1
1
  module Calabash
2
2
  module IOS
3
+ # Runtime defaults for iOS.
3
4
  module Defaults
4
5
  # Sets up the default application based on the
5
6
  # environment, and the default device based on the default application
@@ -18,6 +18,7 @@ module Calabash
18
18
  require 'calabash/ios/device/uia_keyboard_mixin'
19
19
  require 'calabash/ios/device/text_mixin'
20
20
  require 'calabash/ios/device/uia_mixin'
21
+ require 'calabash/ios/device/ipad_1x_2x_mixin'
21
22
  require 'calabash/ios/device/device_implementation'
22
23
 
23
24
  end
@@ -19,11 +19,9 @@ module Calabash
19
19
  include Calabash::IOS::UIAKeyboardMixin
20
20
  include Calabash::IOS::TextMixin
21
21
  include Calabash::IOS::UIAMixin
22
-
22
+ include Calabash::IOS::IPadMixin
23
23
  include Calabash::IOS::GesturesMixin
24
24
 
25
- # @todo Should these be public?
26
- # @todo If public, document!
27
25
  attr_reader :run_loop
28
26
  attr_reader :uia_strategy
29
27
  attr_reader :start_options
@@ -80,7 +78,7 @@ module Calabash
80
78
  identifier = Environment::DEVICE_IDENTIFIER
81
79
 
82
80
  if identifier.nil?
83
- connected_devices = RunLoop::XCTools.new.instruments(:devices)
81
+ connected_devices = RunLoop::Instruments.new.physical_devices
84
82
  if connected_devices.empty?
85
83
  raise 'There are no physical devices connected.'
86
84
  elsif connected_devices.count > 1
@@ -292,6 +290,13 @@ module Calabash
292
290
  runtime_attributes.server_version
293
291
  end
294
292
 
293
+ # @!visibility private
294
+ # A dump of runtime details.
295
+ def runtime_details
296
+ expect_runtime_attributes_available(__method__)
297
+ @runtime_attributes.runtime_info
298
+ end
299
+
295
300
  # Is this device a simulator?
296
301
  # @return [Boolean] Returns true if this device is a simulator.
297
302
  def simulator?
@@ -334,6 +339,10 @@ module Calabash
334
339
  else
335
340
  raise "Invalid application #{application} for iOS platform."
336
341
  end
342
+
343
+ # @todo Get the language code from the server!
344
+ ensure_ipad_emulation_1x
345
+
337
346
  {
338
347
  :device => self,
339
348
  :application => application,
@@ -362,7 +371,7 @@ module Calabash
362
371
 
363
372
  expect_app_installed_on_simulator(bridge)
364
373
 
365
- installed_app = Calabash::IOS::Application.new(bridge.fetch_app_dir)
374
+ installed_app = Calabash::IOS::Application.new(bridge.send(:installed_app_bundle_dir))
366
375
  expect_matching_sha1s(installed_app, application)
367
376
  end
368
377
 
@@ -463,7 +472,7 @@ module Calabash
463
472
  bridge = run_loop_bridge(@run_loop_device, application)
464
473
 
465
474
  if bridge.app_is_installed?
466
- installed_app = Calabash::IOS::Application.new(bridge.fetch_app_dir)
475
+ installed_app = Calabash::IOS::Application.new(bridge.send(:installed_app_bundle_dir))
467
476
 
468
477
  if installed_app.same_sha1_as?(application)
469
478
  true
@@ -566,9 +575,9 @@ module Calabash
566
575
  # @!visibility private
567
576
  def uninstall_app_on_simulator(application, run_loop_device, bridge)
568
577
  begin
569
- bridge.uninstall
578
+ bridge.uninstall_app_and_sandbox
570
579
  true
571
- rescue e
580
+ rescue => e
572
581
  raise "Could not uninstall #{application.identifier} on #{run_loop_device}: #{e}"
573
582
  end
574
583
  end
@@ -594,10 +603,11 @@ module Calabash
594
603
  end
595
604
 
596
605
  # @!visibility private
597
- # Do not memoize this. The Bridge initializer does a bunch of work to
606
+ # Do not memoize this. The CoreSimulator initializer does a bunch of work to
598
607
  # prepare the environment for simctl actions.
599
608
  def run_loop_bridge(run_loop_simulator_device, application)
600
- RunLoop::Simctl::Bridge.new(run_loop_simulator_device, application.path)
609
+ run_loop_app = RunLoop::App.new(application.path)
610
+ RunLoop::CoreSimulator.new(run_loop_simulator_device, run_loop_app)
601
611
  end
602
612
 
603
613
  # @!visibility private
@@ -610,7 +620,7 @@ module Calabash
610
620
  bridge = run_loop_bridge
611
621
  end
612
622
 
613
- bridge.uninstall
623
+ bridge.uninstall_app_and_sandbox
614
624
  bridge.install
615
625
  rescue StandardError => e
616
626
  raise "Could not install #{application} on #{run_loop_device}: #{e}"
@@ -630,8 +640,8 @@ module Calabash
630
640
  # @!visibility private
631
641
  # Very expensive!
632
642
  def Device.fetch_matching_physical_device(udid_or_name)
633
- xctools = RunLoop::XCTools.new
634
- xctools.instruments(:devices).detect do |device|
643
+ instruments = RunLoop::Instruments.new
644
+ instruments.physical_devices.detect do |device|
635
645
  device.name == udid_or_name ||
636
646
  device.udid == udid_or_name
637
647
  end
@@ -729,11 +739,18 @@ module Calabash
729
739
 
730
740
  # @!visibility private
731
741
  def expect_runtime_attributes_available(method_name)
742
+
732
743
  if runtime_attributes.nil?
733
- logger.log("The method '#{method_name}' is not available to IOS::Device until", :info)
734
- logger.log('the app has been launched with Calabash start_app.', :info)
735
- raise "The method '#{method_name}' can only be called after the app has been launched"
744
+ begin
745
+ # Populates the @runtime_attributes
746
+ wait_for_server_to_start({:timeout => 1.0})
747
+ rescue Calabash::Device::EnsureTestServerReadyTimeoutError => _
748
+ logger.log("The method '#{method_name}' is not available to IOS::Device until", :info)
749
+ logger.log('the app has been launched with Calabash start_app.', :info)
750
+ raise "The method '#{method_name}' can only be called after the app has been launched"
751
+ end
736
752
  end
753
+
737
754
  true
738
755
  end
739
756
 
@@ -1,5 +1,6 @@
1
1
  module Calabash
2
2
  module IOS
3
+
3
4
  # @!visibility private
4
5
  #
5
6
  # Gestures should wait for the views involved before performing the
@@ -13,26 +14,117 @@ module Calabash
13
14
  # @todo Needs unit tests.
14
15
  module GesturesMixin
15
16
 
17
+ # @!visibility private
18
+ class UIAutomationError < StandardError; end
19
+
20
+ # @!visibility private
21
+ #
22
+ # Since iOS 7, Apple's UIAutomation API:
23
+ #
24
+ # * dragInsideWithOptions
25
+ # * flickInsideWithOptions
26
+ #
27
+ # has been broken for iOS Simulators under the following conditions:
28
+ #
29
+ # * View is UIScrollView or UIScrollView subclass
30
+ # * View is inside a UIScrollView or UIScrollView subclass
31
+ #
32
+ # @todo Check for fix on iOS 9
33
+ def check_for_broken_uia_automation(query, view, gesture_waiter)
34
+ # Only broken for simulators.
35
+ return if Device.default.physical_device?
36
+
37
+ conditions = [
38
+ # All UIScrollViews have content_offset.
39
+ lambda do
40
+ content_offset = gesture_waiter.query(query, :contentOffset).first
41
+ content_offset != '*****'
42
+ end,
43
+
44
+ # If view looks like a table view cell.
45
+ lambda do
46
+ view['class'][/TableViewCell/, 0]
47
+ end,
48
+
49
+ # Or a collection view cell.
50
+ lambda do
51
+ view['class'][/CollectionViewCell/, 0]
52
+ end,
53
+
54
+ # If view in inside a UITableViewCell.
55
+ lambda do
56
+ if query.to_s == '*'
57
+ # '*' parent UITableViewCell is too broad.
58
+ false
59
+ else
60
+ new_query = "#{query} parent UITableViewCell"
61
+ !gesture_waiter.query(new_query).empty?
62
+ end
63
+ end,
64
+
65
+ # Or inside a UICollectionViewCell
66
+ lambda do
67
+ if query.to_s == '*'
68
+ # '*' parent UICollectionViewCell is too broad.
69
+ false
70
+ else
71
+ new_query = "#{query} parent UICollectionViewCell"
72
+ !gesture_waiter.query(new_query).empty?
73
+ end
74
+ end
75
+ ]
76
+
77
+ if conditions.any? { |condition| condition.call }
78
+ message = [
79
+ '',
80
+ "Apple's public UIAutomation API `dragInsideWithOptions` is broken for iOS Simulators >= 7",
81
+ '',
82
+ 'If you are trying to swipe-to-delete on a simulator, it will only work on a device.',
83
+ '',
84
+ 'If you are trying to manipulate a table, collection or scroll view, try using the Scroll API.',
85
+ ' * scroll # Scroll in a direction.',
86
+ ' * scroll_to_row # Scroll to a row with row / section indexes.',
87
+ ' * scroll_to_row_with_mark # Scroll to table row with a mark.',
88
+ ' * scroll_to_item # Scroll to collection item with item / section indexes.',
89
+ ' * scroll_to_item_with_mark # Scroll to collection item with a mark.',
90
+ '',
91
+ 'All gestures work on physical devices.'
92
+ ].map { |msg| Color.red(msg) }.join("\n")
93
+ raise UIAutomationError, message
94
+ end
95
+ end
96
+
97
+ # @!visibility private
16
98
  def _tap(query, options={})
17
99
  view_to_touch = _gesture_waiter.wait_for_view(query, options)
18
100
 
19
- offset = uia_center_of_view(view_to_touch)
101
+ rect = view_to_touch['rect']
102
+ x = rect['x'] + (rect['width'] * (options[:at][:x] / 100.0)).to_i
103
+ y = rect['y'] + (rect['height'] * (options[:at][:y] / 100.0)).to_i
104
+
105
+ offset = coordinate(x, y)
20
106
 
21
107
  uia_serialize_and_call(:tapOffset, offset, options)
22
108
 
23
109
  Calabash::QueryResult.create([view_to_touch], query)
24
110
  end
25
111
 
112
+ # @!visibility private
26
113
  def _double_tap(query, options={})
27
114
  view_to_touch = _gesture_waiter.wait_for_view(query, options)
28
115
 
29
- offset = uia_center_of_view(view_to_touch)
116
+ rect = view_to_touch['rect']
117
+ x = rect['x'] + (rect['width'] * (options[:at][:x] / 100.0)).to_i
118
+ y = rect['y'] + (rect['height'] * (options[:at][:y] / 100.0)).to_i
119
+
120
+ offset = coordinate(x, y)
30
121
 
31
122
  uia_serialize_and_call(:doubleTapOffset, offset, options)
32
123
 
33
124
  Calabash::QueryResult.create([view_to_touch], query)
34
125
  end
35
126
 
127
+ # @!visibility private
36
128
  def _long_press(query, options={})
37
129
 
38
130
  begin
@@ -43,13 +135,18 @@ module Calabash
43
135
 
44
136
  view_to_touch = _gesture_waiter.wait_for_view(query, options)
45
137
 
46
- offset = uia_center_of_view(view_to_touch)
138
+ rect = view_to_touch['rect']
139
+ x = rect['x'] + (rect['width'] * (options[:at][:x] / 100.0)).to_i
140
+ y = rect['y'] + (rect['height'] * (options[:at][:y] / 100.0)).to_i
141
+
142
+ offset = coordinate(x, y)
47
143
 
48
144
  uia_serialize_and_call(:touchHoldOffset, options[:duration], offset)
49
145
 
50
146
  Calabash::QueryResult.create([view_to_touch], query)
51
147
  end
52
148
 
149
+ # @!visibility private
53
150
  def _pan_between(query_from, query_to, options={})
54
151
 
55
152
  begin
@@ -72,17 +169,14 @@ module Calabash
72
169
  }
73
170
  end
74
171
 
75
- # The default to and from for the pan_* methods are not good for iOS.
172
+ # @!visibility private
173
+ # @todo The default to and from for the pan_* methods are not good for iOS.
76
174
  #
77
175
  # * from: {x: 90, y: 50}
78
176
  # * to: {x: 10, y: 50}
79
177
  #
80
- # If the view has a UINavigationBar or UITabBar, the defaults will
178
+ # If the view has a UINavigationBar or UITabBar, the defaults *might*
81
179
  # cause vertical gestures to start and/or end on one of these bars.
82
- #
83
- # dragInsideWithOptions broke in iOS 7, so the condition should really be
84
- # `Device.default.simulator? && !Device.ios6?`, but I haven't checked on
85
- # iOS 9 yet, so I will leave the condition out.
86
180
  def _pan(query, from, to, options={})
87
181
 
88
182
  begin
@@ -94,66 +188,125 @@ module Calabash
94
188
  gesture_waiter = _gesture_waiter
95
189
  view_to_pan = gesture_waiter.wait_for_view(query, options)
96
190
 
97
- # * will never match a UIScrollView or subclass.
98
- if Device.default.simulator? && query.to_s != '*'
99
- should_raise = false
100
-
101
- content_offset = gesture_waiter.query(query, :contentOffset).first
102
- if content_offset != '*****'
103
- # Panning on anything with a content offset is broken.
104
- should_raise = true
105
- elsif view_to_pan['class'][/TableViewCell/, 0]
106
- should_raise = true
107
- else
108
- new_query = "#{query} parent UITableViewCell"
109
- should_raise = !gesture_waiter.query(new_query).empty?
110
- # TODO: Identify other conditions
111
- # TODO: Can we detect UITableViewCells?
112
- # The gist is that if the view is a UIScrollView or in a UIScrollView
113
- # dragInsideWithOptions does not work
114
- end
115
-
116
- if should_raise
117
- message = [
118
- '',
119
- "Apple's public UIAutomation API `dragInsideWithOptions` is broken for iOS Simulators >= 7",
120
- '',
121
- 'If you are trying to swipe-to-delete on a simulator, it will only work on a device.',
122
- '',
123
- 'If you are trying to manipulate a table, collection or scroll view, try using the Scroll API.',
124
- ' * scroll # Scroll in a direction.',
125
- ' * scroll_to_row # Scroll to a row with row / section indexes.',
126
- ' * scroll_to_row_with_mark # Scroll to table row with a mark.',
127
- ' * scroll_to_item # Scroll to collection item with item / section indexes.',
128
- ' * scroll_to_item_with_mark # Scroll to collection item with a mark.',
129
- '',
130
- 'All gestures work on physical devices.'
131
- ].map { |msg| Color.red(msg) }.join("\n")
132
- raise message
133
- end
191
+ begin
192
+ check_for_broken_uia_automation(query, view_to_pan, gesture_waiter)
193
+ rescue => e
194
+ raise "Could not pan with query: #{query}\n#{e.message}"
134
195
  end
135
196
 
136
197
  rect = view_to_pan['rect']
137
198
 
138
199
  from_x = rect['width'] * (from[:x]/100.0)
139
200
  from_y = rect['height'] * (from[:y]/100.0)
140
- from_offset = percent(from_x, from_y)
201
+ from_offset = coordinate(from_x, from_y)
141
202
 
142
203
  to_x = rect['width'] * (to[:x]/100.0)
143
204
  to_y = rect['height'] * (to[:y]/100.0)
144
- to_offset = percent(to_x, to_y)
205
+ to_offset = coordinate(to_x, to_y)
145
206
 
146
207
  uia_serialize_and_call(:panOffset, from_offset, to_offset)
147
208
 
148
209
  Calabash::QueryResult.create([view_to_pan], query)
149
210
  end
150
211
 
212
+ # @!visibility private
151
213
  def pan_screen(view_to_pan, from_offset, to_offset, options)
214
+ begin
215
+ _expect_valid_duration(options)
216
+ rescue ArgumentError => e
217
+ raise ArgumentError, e
218
+ end
219
+
152
220
  uia_serialize_and_call(:panOffset, from_offset, to_offset, options)
153
221
 
154
222
  Calabash::QueryResult.create([view_to_pan], '*')
155
223
  end
156
224
 
225
+ # @!visibility private
226
+ # @todo The default to and from for the screen_* methods are not good for iOS.
227
+ #
228
+ # * from: {x: 90, y: 50}
229
+ # * to: {x: 10, y: 50}
230
+ #
231
+ # If the view has a UINavigationBar or UITabBar, the defaults *might*
232
+ # cause vertical gestures to start and/or end on one of these bars.
233
+ def _flick(query, from, to, options)
234
+ begin
235
+ _expect_valid_duration(options)
236
+ rescue ArgumentError => e
237
+ raise ArgumentError, e
238
+ end
239
+
240
+ gesture_waiter = _gesture_waiter
241
+ view_to_flick = gesture_waiter.wait_for_view(query, options)
242
+
243
+ begin
244
+ check_for_broken_uia_automation(query, view_to_flick, gesture_waiter)
245
+ rescue => e
246
+ raise "Could not flick with query: #{query}\n#{e.message}"
247
+ end
248
+
249
+ rect = view_to_flick['rect']
250
+
251
+ from_x = rect['width'] * (from[:x]/100.0)
252
+ from_y = rect['height'] * (from[:y]/100.0)
253
+ from_offset = percent(from_x, from_y)
254
+
255
+ to_x = rect['width'] * (to[:x]/100.0)
256
+ to_y = rect['height'] * (to[:y]/100.0)
257
+ to_offset = percent(to_x, to_y)
258
+
259
+ uia_serialize_and_call(:flickOffset, from_offset, to_offset, options)
260
+
261
+ Calabash::QueryResult.create([view_to_flick], query)
262
+ end
263
+
264
+ # @!visibility private
265
+ def flick_screen(view_to_pan, from_offset, to_offset, options)
266
+ begin
267
+ _expect_valid_duration(options)
268
+ rescue ArgumentError => e
269
+ raise ArgumentError, e
270
+ end
271
+
272
+ uia_serialize_and_call(:flickOffset, from_offset, to_offset, options)
273
+
274
+ Calabash::QueryResult.create([view_to_pan], '*')
275
+ end
276
+
277
+ # @!visibility private
278
+ # @todo The pinch gestures are incredibly coarse grained.
279
+ #
280
+ # https://github.com/krukow/calabash-script/commit/fa33550ac7ac4f37da649498becef441d2284cd8
281
+ def _pinch(direction, query, options={})
282
+ begin
283
+ _expect_valid_duration(options)
284
+ rescue ArgumentError => e
285
+ raise ArgumentError, e
286
+ end
287
+
288
+ gesture_waiter = _gesture_waiter
289
+
290
+ view_to_pinch = gesture_waiter.wait_for_view(query, options)
291
+ offset = uia_center_of_view(view_to_pinch)
292
+
293
+ gesture_direction = direction == :in ? :out : :in
294
+
295
+ uia_serialize_and_call(:pinchOffset, gesture_direction, offset, options)
296
+
297
+ after = gesture_waiter.query(query)
298
+ if after.empty?
299
+ after_result = nil
300
+ else
301
+ after_result = after.first
302
+ end
303
+
304
+ {
305
+ :before => Calabash::QueryResult.create([view_to_pinch], query),
306
+ :after => Calabash::QueryResult.create([after_result], query)
307
+ }
308
+ end
309
+
157
310
  private
158
311
 
159
312
  # @!visibility private
@@ -189,6 +342,7 @@ module Calabash
189
342
  end.call(self)
190
343
  end
191
344
 
345
+ # @!visibility private
192
346
  def _expect_valid_duration(options)
193
347
  duration = options[:duration].to_f
194
348
  if duration < 0.5 || duration > 60