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
@@ -57,10 +57,12 @@ module Calabash
57
57
  @on_error = {}
58
58
  end
59
59
 
60
+ # @!visibility private
60
61
  def on_error(type, &block)
61
62
  @on_error[type] = block
62
63
  end
63
64
 
65
+ # @!visibility private
64
66
  def change_server(new_server)
65
67
  @server = new_server
66
68
  end
@@ -107,7 +109,7 @@ module Calabash
107
109
  interval = options.fetch(:interval, @interval)
108
110
  header = options.fetch(:header, HEADER)
109
111
 
110
- @logger.log "Getting: #{@server.endpoint + request.route}"
112
+ @logger.log "Getting: #{@server.endpoint + request.route} #{options}"
111
113
 
112
114
  start_time = Time.now
113
115
  last_error = nil
@@ -1,12 +1,75 @@
1
1
  module Calabash
2
- # @!visibility private
2
+ # Query, flash, backdoor, etc.
3
3
  module Interactions
4
- # @todo Needs docs!
4
+ # Queries the view hierarchy to find all views matching `query`.
5
+ # Optionally query takes a variable number of “invocation” arguments
6
+ # (args below).
7
+ # If called with an empty list of *args, query will find the views
8
+ # specified by `query` and return a QueryResult of serialized views.
9
+ #
10
+ # @note If this method is called with invocation arguments, it might allow
11
+ # the author of the test to do an interaction with app that a user would
12
+ # not be able to (for example changing the text of a view).
13
+ #
14
+ # @example
15
+ # query("* marked:'my view'")
16
+ # query("* id:'foo' descendant UIButton")
17
+ # query("android.widget.ProgressBar")
18
+ # query("* {text CONTAINS 'something'}")
19
+ # query("* {y > 200}")
20
+ #
21
+ # @example
22
+ # # Find all the elements, visible as well as invisible
23
+ # query("all *")
24
+ #
25
+ # @example
26
+ # query("editText", :setText => 'my text')
27
+ # query("scrollView", :scrollBy => [50, 10])
28
+ #
29
+ # @example
30
+ # irb(main):009:0> query("UITabBarButton index:0")
31
+ # [
32
+ # [0] {
33
+ # "class" => "UITabBarButton",
34
+ # "id" => nil,
35
+ # "rect" => {
36
+ # "center_x" => 40,
37
+ # "y" => 520,
38
+ # "width" => 76,
39
+ # "x" => 2,
40
+ # "center_y" => 544,
41
+ # "height" => 48
42
+ # },
43
+ # "frame" => {
44
+ # "y" => 1,
45
+ # "width" => 76,
46
+ # "x" => 2,
47
+ # "height" => 48
48
+ # },
49
+ # "label" => "Reader",
50
+ # "description" => "<UITabBarButton: 0xdabb510; frame = (2 1; 76 48); opaque = NO; layer = <CALayer: 0xdabd8e0>>"
51
+ # }
52
+ # ]
53
+ #
54
+ # @note Even if the query matches only one view, the QueryResult returned
55
+ # is still a list of elements.
56
+ #
57
+ # @param [String, Hash, Calabash::Query] query The query to match the
58
+ # view(s)
59
+ #
60
+ # @param args Optional var-args list describing a chain of method
61
+ # names (selectors).
62
+ #
63
+ # @return [Calabash::QueryResult] A result of the query
5
64
  def query(query, *args)
6
65
  Calabash::Device.default.map_route(Query.new(query), :query, *args)
7
66
  end
8
67
 
9
- # @todo Needs docs!
68
+ # Flashes any views matching `query`. Only one view is flashed at a time,
69
+ # in the order they are returned.
70
+ #
71
+ # @param [String, Hash, Calabash::Query] query The query to match the
72
+ # view(s)
10
73
  def flash(query)
11
74
  Calabash::Device.default.map_route(Query.new(query), :flash)
12
75
  end
@@ -18,7 +81,7 @@ module Calabash
18
81
  # # iOS
19
82
  # evaluate_javascript_in("UIWebView", "2+2")
20
83
  # # Android
21
- # evaluate_javascript_in("WebView", "return 2+2"
84
+ # evaluate_javascript_in("WebView", "return 2+2")
22
85
  #
23
86
  # @example
24
87
  # # iOS
@@ -79,7 +142,7 @@ module Calabash
79
142
  #
80
143
  # @example
81
144
  # # iOS
82
- # backdoor('calabashBackdoor:'', '')
145
+ # backdoor('calabashBackdoor:', '')
83
146
  #
84
147
  # @example
85
148
  # # iOS
data/lib/calabash/ios.rb CHANGED
@@ -30,6 +30,8 @@ module Calabash
30
30
  require 'calabash/ios/scroll'
31
31
  require 'calabash/ios/runtime'
32
32
  require 'calabash/ios/gestures'
33
+ require 'calabash/ios/slider'
34
+ require 'calabash/ios/date_picker'
33
35
 
34
36
  include Calabash::IOS::Conditions
35
37
  include Calabash::IOS::Orientation
@@ -39,6 +41,8 @@ module Calabash
39
41
  include Calabash::IOS::Scroll
40
42
  include Calabash::IOS::Runtime
41
43
  include Calabash::IOS::Gestures
44
+ include Calabash::IOS::Slider
45
+ include Calabash::IOS::DatePicker
42
46
 
43
47
  end
44
48
  end
@@ -27,7 +27,7 @@ module Calabash
27
27
  application_path = Environment::APP_PATH
28
28
 
29
29
  if application_path.nil?
30
- raise 'No application path is set'
30
+ raise 'No application path is set. Specify application with environment variable CAL_APP'
31
31
  end
32
32
 
33
33
  Application.new(application_path)
@@ -67,6 +67,13 @@ module Calabash
67
67
  @device_binary
68
68
  end
69
69
 
70
+ # Is this application an iOS application
71
+ #
72
+ # @return [Boolean] Always returns true
73
+ def ios_application?
74
+ true
75
+ end
76
+
70
77
  # Returns the sha1 of the directory or binary of this app's path.
71
78
  # @return [String] A checksum.
72
79
  def sha1
@@ -1,6 +1,8 @@
1
1
  module Calabash
2
2
  module IOS
3
- # @!visibility private
3
+
4
+ # Methods for waiting for things to happen on iOS, like animations to
5
+ # complete.
4
6
  module Conditions
5
7
 
6
8
  # Waits for all elements to stop animating.
@@ -0,0 +1,412 @@
1
+ require 'date'
2
+
3
+ module Calabash
4
+ module IOS
5
+
6
+ # A collection of methods for interacting with UIDatePicker.
7
+ module DatePicker
8
+
9
+ # The API has been tested in various time zones and tested
10
+ # once while crossing the international date line (on a boat).
11
+ # With that said, the API makes some assumptions about locales
12
+ # and time zones. It is possible to customize the ruby date
13
+ # format and Objective-C date format to get the behavior you
14
+ # need. You will need to monkey patch the following methods:
15
+ #
16
+ # * date_picker_ruby_date_format
17
+ # * date_picker_objc_date_format
18
+ #
19
+ # Before going down this path, we recommend that you ask for
20
+ # advice on the Calabash support channels.
21
+
22
+ # @!visibility private
23
+ # Provided for monkey patching, but not part of the public API.
24
+ def date_picker_ruby_date_format
25
+ RUBY_DATE_AND_TIME_FMT
26
+ end
27
+
28
+ # @!visibility private
29
+ # Provided for monkey patching, but not part of the public API.
30
+ def date_picker_objc_date_format
31
+ OBJC_DATE_AND_TIME_FMT
32
+ end
33
+
34
+ # @!visibility private
35
+ # Returns the picker mode of the first UIDatePicker match by `query`.
36
+ #
37
+ # @see #time_mode?
38
+ # @see #date_mode?
39
+ # @see #date_and_time_mode?
40
+ # @see #countdown_mode?
41
+ #
42
+ # @param [String, Hash, Calabash::Query] query A query that can be used
43
+ # to find UIDatePickers.
44
+ # @return [String] Returns the picker mode which will be one of
45
+ # `{'0', '1', '2', '3'}`
46
+ # @raise [RuntimeError] If no picker can be found.
47
+ # @raise [RuntimeError] If an unknown mode is returned.
48
+ # @raise [RuntimeError] If first view matched by query does not responde
49
+ # to 'datePickerMode'.
50
+ def date_picker_mode(query)
51
+ Query.ensure_valid_query(query)
52
+
53
+ message = "Timed out waiting for picker with #{query}"
54
+ mode = nil
55
+
56
+ wait_for(message) do
57
+ result = query(query, :datePickerMode)
58
+ if result.empty?
59
+ false
60
+ else
61
+ mode = result.first
62
+ if [0, 1, 2, 3].include?(mode)
63
+ mode
64
+ else
65
+ if mode == '*****'
66
+ raise RuntimeError,
67
+ "Query #{query} matched a view that does not respond 'datePickerMode'"
68
+ else
69
+ raise RuntimeError,
70
+ "Query #{query} returned an unknown mode '#{mode}' for 'datePickerMode'"
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ # Is the date picker in time mode?
78
+ #
79
+ # @see #time_mode?
80
+ # @see #date_mode?
81
+ # @see #date_and_time_mode?
82
+ # @see #countdown_mode?
83
+ #
84
+ # @param [String, Hash, Calabash::Query] query A query that can be used
85
+ # to find UIDatePickers.
86
+ #
87
+ # @return [Boolean] True if the picker is in time mode.
88
+ #
89
+ # @raise [RuntimeError] If no picker can be found.
90
+ # @raise [RuntimeError] If an unknown mode is returned.
91
+ # @raise [RuntimeError] If first view matched by query does not responde
92
+ # to 'datePickerMode'.
93
+ def time_mode?(query)
94
+ date_picker_mode(query) == UI_DATE_PICKER_MODE_TIME
95
+ end
96
+
97
+ # Is the date picker in date mode?
98
+ #
99
+ # @see #time_mode?
100
+ # @see #date_mode?
101
+ # @see #date_and_time_mode?
102
+ # @see #countdown_mode?
103
+ #
104
+ # @param [String, Hash, Calabash::Query] query A query that can be used
105
+ # to find UIDatePickers.
106
+ #
107
+ # @return [Boolean] True if the picker is in date mode.
108
+ #
109
+ # @raise [RuntimeError] If no picker can be found.
110
+ # @raise [RuntimeError] If an unknown mode is returned.
111
+ # @raise [RuntimeError] If first view matched by query does not responde
112
+ # to 'datePickerMode'.
113
+ def date_mode?(query)
114
+ date_picker_mode(query) == UI_DATE_PICKER_MODE_DATE
115
+ end
116
+
117
+ # Is the date picker in date and time mode?
118
+ #
119
+ # @see #time_mode?
120
+ # @see #date_mode?
121
+ # @see #date_and_time_mode?
122
+ # @see #countdown_mode?
123
+ #
124
+ # @param [String, Hash, Calabash::Query] query A query that can be used
125
+ # to find UIDatePickers.
126
+ #
127
+ # @return [Boolean] True if the picker is in date and time mode.
128
+ #
129
+ # @raise [RuntimeError] If no picker can be found.
130
+ # @raise [RuntimeError] If an unknown mode is returned.
131
+ # @raise [RuntimeError] If first view matched by query does not responde
132
+ # to 'datePickerMode'.
133
+ def date_and_time_mode?(query)
134
+ date_picker_mode(query) == UI_DATE_PICKER_MODE_DATE_AND_TIME
135
+ end
136
+
137
+ # Is the date picker in countdown mode?
138
+ #
139
+ # @see #time_mode?
140
+ # @see #date_mode?
141
+ # @see #date_and_time_mode?
142
+ # @see #countdown_mode?
143
+ #
144
+ # @param [String, Hash, Calabash::Query] query A query that can be used
145
+ # to find UIDatePickers.
146
+ #
147
+ # @return [Boolean] True if the picker is in countdown mode.
148
+ #
149
+ # @raise [RuntimeError] If no picker can be found.
150
+ # @raise [RuntimeError] If an unknown mode is returned.
151
+ # @raise [RuntimeError] If first view matched by query does not responde
152
+ # to 'datePickerMode'.
153
+ def countdown_mode?(query)
154
+ date_picker_mode(query) == UI_DATE_PICKER_MODE_COUNT_DOWN_TIMER
155
+ end
156
+
157
+ # The maximum date for a picker. If there is no maximum date, this
158
+ # method returns nil.
159
+ #
160
+ # @note
161
+ # From the Apple docs:
162
+ # `The property is an NSDate object or nil (the default)`.
163
+ #
164
+ # @param [String, Hash, Calabash::Query] query A query that can be used
165
+ # to find UIDatePickers.
166
+ #
167
+ # @return [DateTime] The maximum date on the picker or nil if no maximum
168
+ # exists
169
+ #
170
+ # @raise [RuntimeError] If the picker is in countdown mode.
171
+ # @raise [RuntimeError] If no picker can be found.
172
+ # @raise [RuntimeError] If the date returned by the server cannot be
173
+ # converted to a DateTime object.
174
+ def maximum_date_time_from_picker(query)
175
+ Query.ensure_valid_query(query)
176
+
177
+ wait_for_view(query)
178
+
179
+ if countdown_mode?(query)
180
+ fail('Countdown pickers do not have a maximum date.')
181
+ end
182
+
183
+ result = query(query, :maximumDate)
184
+
185
+ if result.empty?
186
+ fail("Expected '#{query}' to return a visible UIDatePicker")
187
+ else
188
+ if result.first.nil?
189
+ nil
190
+ else
191
+ date_str = result.first
192
+ begin
193
+ date_time = DateTime.parse(date_str)
194
+ rescue TypeError, ArgumentError => _
195
+ raise RuntimeError,
196
+ "Could not convert string '#{date_str}' into a valid DateTime object"
197
+ end
198
+ date_time
199
+ end
200
+ end
201
+ end
202
+
203
+ # The minimum date for a picker. If there is no minimum date, this
204
+ # method returns nil.
205
+ #
206
+ # @note
207
+ # From the Apple docs:
208
+ # `The property is an NSDate object or nil (the default)`.
209
+ #
210
+ # @param [String, Hash, Calabash::Query] query A query that can be used
211
+ # to find UIDatePickers.
212
+ #
213
+ # @return [DateTime] The minimum date on the picker or nil if no minimum
214
+ # exists
215
+ #
216
+ # @raise [RuntimeError] If the picker is in countdown mode.
217
+ # @raise [RuntimeError] If no picker can be found.
218
+ # @raise [RuntimeError] If the date returned by the server cannot be
219
+ # converted to a DateTime object.
220
+ def minimum_date_time_from_picker(query)
221
+ Query.ensure_valid_query(query)
222
+
223
+ wait_for_view(query)
224
+
225
+ if countdown_mode?(query)
226
+ fail('Countdown pickers do not have a minimum date.')
227
+ end
228
+
229
+ result = query(query, :minimumDate)
230
+
231
+ if result.empty?
232
+ fail("Expected '#{query}' to return a visible UIDatePicker")
233
+ else
234
+ if result.first.nil?
235
+ nil
236
+ else
237
+ date_str = result.first
238
+ begin
239
+ date_time = DateTime.parse(date_str)
240
+ rescue TypeError, ArgumentError => _
241
+ raise RuntimeError,
242
+ "Could not convert string '#{date_str}' into a valid DateTime object"
243
+ end
244
+ date_time
245
+ end
246
+ end
247
+ end
248
+
249
+ # Returns the date and time from the picker as DateTime object.
250
+ #
251
+ # @param [String, Hash, Calabash::Query] query A query that can be used
252
+ # to find UIDatePickers.
253
+ #
254
+ # @return [DateTime] The date on the picker
255
+ #
256
+ # @raise [RuntimeError] If the picker is in countdown mode.
257
+ # @raise [RuntimeError] If no picker can be found.
258
+ # @raise [RuntimeError] If the date returned by the server cannot be
259
+ # converted to a DateTime object.
260
+ def date_time_from_picker(query)
261
+ Query.ensure_valid_query(query)
262
+
263
+ wait_for_view(query)
264
+
265
+ if countdown_mode?(query)
266
+ fail('This method is available for pickers in countdown mode.')
267
+ end
268
+
269
+ result = query(query, :date)
270
+
271
+ if result.empty?
272
+ fail("Expected '#{query}' to return a visible UIDatePicker")
273
+ else
274
+ if result.first.nil?
275
+ nil
276
+ else
277
+ date_str = result.first
278
+ date_time = DateTime.parse(date_str)
279
+ if date_time.nil?
280
+ raise RuntimeError,
281
+ "Could not convert string '#{date_str}' into a valid DateTime object"
282
+ end
283
+ date_time
284
+ end
285
+ end
286
+ end
287
+
288
+ # Sets the date and time on the _first_ UIDatePicker matched by
289
+ # `query`.
290
+ #
291
+ # This method is not valid for UIDatePickers in _countdown_ mode.
292
+ #
293
+ # @param [DateTime] date_time The date and time you want to change to.
294
+ #
295
+ # @raise [RuntimeError] If `query` does match exactly one picker.
296
+ # @raise [RuntimeError] If `query` matches a picker in countdown mode.
297
+ # @raise [RuntimeError] If the target date is greater than the picker's
298
+ # maximum date.
299
+ # @raise [RuntimeError] If the target date is less than the picker's
300
+ # minimum date
301
+ # @raise [ArgumentError] If the target date is not a DateTime instance.
302
+ def picker_set_date_time(date_time)
303
+ picker_set_date_time_in("UIDatePicker index:0", date_time)
304
+ end
305
+
306
+ # Sets the date and time on the _first_ UIDatePicker matched by
307
+ # `query`.
308
+ #
309
+ # This method is not valid for UIDatePickers in _countdown_ mode.
310
+ #
311
+ # An error will be raised if more than on view is matched by `query`.
312
+ #
313
+ # To avoid matching more than one UIPickerView or subclass:
314
+ # * Make the query more specific: "UIPickerView marked:'alarm'"
315
+ # * Use the index language feature: "UIPickerView index:0"
316
+ # * Query by custom class: "view:'MyPickerView'"
317
+ #
318
+ # @param [String, Hash, Calabash::Query] query A query that can be used
319
+ # to find UIDatePickers.
320
+ # @param [DateTime] date_time The date and time you want to change to.
321
+ #
322
+ # @raise [RuntimeError] If `query` does match exactly one picker.
323
+ # @raise [RuntimeError] If `query` matches a picker in countdown mode.
324
+ # @raise [RuntimeError] If the target date is greater than the picker's
325
+ # maximum date.
326
+ # @raise [RuntimeError] If the target date is less than the picker's
327
+ # minimum date
328
+ # @raise [ArgumentError] If the target date is not a DateTime instance.
329
+ def picker_set_date_time_in(query, date_time)
330
+ unless date_time.is_a?(DateTime)
331
+ raise ArgumentError,
332
+ "Date time argument '#{date_time}' must be a DateTime but found '#{date_time.class}'"
333
+ end
334
+
335
+ Query.ensure_valid_query(query)
336
+
337
+ message = "Timed out waiting for UIDatePicker with '#{query}'"
338
+
339
+ wait_for(message) do
340
+ result = query(query)
341
+ if result.length > 1
342
+ fail("Query '#{query}' matched more than on UIDatePicker")
343
+ else
344
+ !result.empty?
345
+ end
346
+ end
347
+
348
+ if countdown_mode?(query)
349
+ message =
350
+ [
351
+ "Query '#{query}' matched a picker in countdown mode.",
352
+ 'Setting the date or time on a countdown picker is not supported'
353
+ ].join("\n")
354
+ fail(message)
355
+ end
356
+
357
+ minimum_date = minimum_date_time_from_picker(query)
358
+ if !minimum_date.nil? && minimum_date > date_time
359
+ message = [
360
+ "Cannot set the date on the picker matched by '#{query}'",
361
+ "Picker minimum date: '#{minimum_date}'",
362
+ " Date to change to: '#{date_time}'",
363
+ "Target date comes before the minimum date."].join("\n")
364
+ fail(message)
365
+ end
366
+
367
+ maximum_date = maximum_date_time_from_picker(query)
368
+ if !maximum_date.nil? && maximum_date < date_time
369
+ message = [
370
+ "Cannot set the date on the picker matched by '#{query}'",
371
+ "Picker maximum date: '#{maximum_date}'",
372
+ " Date to change to: '#{date_time}'",
373
+ "Target date comes after the maximum date."].join("\n")
374
+ fail(message)
375
+ end
376
+
377
+ ruby_format = date_picker_ruby_date_format
378
+ objc_format = date_picker_objc_date_format
379
+ target_date_string = date_time.strftime(ruby_format).squeeze(' ').strip
380
+
381
+ Device.default.map_route(query,
382
+ :changeDatePickerDate,
383
+ target_date_string,
384
+ objc_format,
385
+ # notify targets
386
+ true,
387
+ # animate
388
+ true)
389
+ end
390
+
391
+ private
392
+
393
+ # @!visibility private
394
+ OBJC_DATE_AND_TIME_FMT = 'yyyy_MM_dd_HH_mm'
395
+
396
+ # @!visibility private
397
+ RUBY_DATE_AND_TIME_FMT = '%Y_%m_%d_%H_%M'
398
+
399
+ # UIDatePicker modes
400
+
401
+ # @!visibility private
402
+ UI_DATE_PICKER_MODE_TIME = 0
403
+ # @!visibility private
404
+ UI_DATE_PICKER_MODE_DATE = 1
405
+ # @!visibility private
406
+ UI_DATE_PICKER_MODE_DATE_AND_TIME = 2
407
+ # @!visibility private
408
+ UI_DATE_PICKER_MODE_COUNT_DOWN_TIMER = 3
409
+ end
410
+ end
411
+ end
412
+