markos_validates_timeliness 2.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/CHANGELOG +121 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +402 -0
  4. data/Rakefile +52 -0
  5. data/TODO +8 -0
  6. data/lib/validates_timeliness/action_view/instance_tag.rb +52 -0
  7. data/lib/validates_timeliness/active_record/attribute_methods.rb +77 -0
  8. data/lib/validates_timeliness/active_record/multiparameter_attributes.rb +69 -0
  9. data/lib/validates_timeliness/formats.rb +368 -0
  10. data/lib/validates_timeliness/locale/en.new.yml +18 -0
  11. data/lib/validates_timeliness/locale/en.old.yml +18 -0
  12. data/lib/validates_timeliness/matcher.rb +1 -0
  13. data/lib/validates_timeliness/parser.rb +44 -0
  14. data/lib/validates_timeliness/spec/rails/matchers/validate_timeliness.rb +162 -0
  15. data/lib/validates_timeliness/validation_methods.rb +46 -0
  16. data/lib/validates_timeliness/validator.rb +230 -0
  17. data/lib/validates_timeliness/version.rb +3 -0
  18. data/lib/validates_timeliness.rb +59 -0
  19. data/spec/action_view/instance_tag_spec.rb +194 -0
  20. data/spec/active_record/attribute_methods_spec.rb +157 -0
  21. data/spec/active_record/multiparameter_attributes_spec.rb +118 -0
  22. data/spec/formats_spec.rb +313 -0
  23. data/spec/ginger_scenarios.rb +19 -0
  24. data/spec/parser_spec.rb +65 -0
  25. data/spec/resources/application.rb +2 -0
  26. data/spec/resources/person.rb +3 -0
  27. data/spec/resources/schema.rb +10 -0
  28. data/spec/resources/sqlite_patch.rb +19 -0
  29. data/spec/spec/rails/matchers/validate_timeliness_spec.rb +245 -0
  30. data/spec/spec_helper.rb +58 -0
  31. data/spec/time_travel/MIT-LICENSE +20 -0
  32. data/spec/time_travel/time_extensions.rb +33 -0
  33. data/spec/time_travel/time_travel.rb +12 -0
  34. data/spec/validator_spec.rb +723 -0
  35. metadata +104 -0
@@ -0,0 +1,723 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe ValidatesTimeliness::Validator do
4
+ attr_accessor :person, :validator
5
+
6
+ if ValidatesTimeliness::I18N_LATEST
7
+ I18N_REGEXP = /\%\{\w*\}/
8
+ I18N_INTERPOLATION = '%{%s}'
9
+ else
10
+ I18N_REGEXP = /\{\{\w*\}\}/
11
+ I18N_INTERPOLATION = '{{%s}}'
12
+ end
13
+
14
+ before :all do
15
+ # freezes time using time_travel plugin
16
+ Time.now = Time.utc(2000, 1, 1, 0, 0, 0)
17
+ end
18
+
19
+ after :all do
20
+ Time.now = nil
21
+ end
22
+
23
+ def person
24
+ @person ||= Person.new
25
+ end
26
+
27
+ describe "option keys validation" do
28
+ before(:all) do
29
+ ActiveSupport::Deprecation.silenced = true
30
+ end
31
+
32
+ before do
33
+ keys = ValidatesTimeliness::Validator::VALID_OPTION_KEYS - [:invalid_date_message, :invalid_time_message, :with_date, :with_time]
34
+ @valid_options = keys.inject({}) {|hash, opt| hash[opt] = nil; hash }
35
+ end
36
+
37
+ it "should raise error if invalid option key passed" do
38
+ @valid_options.update(:invalid_key => 'will not open lock')
39
+ lambda { Person.validates_datetime(@valid_options) }.should raise_error(ArgumentError)
40
+ end
41
+
42
+ it "should not raise error if option keys are valid" do
43
+ lambda { Person.validates_datetime(@valid_options) }.should_not raise_error(ArgumentError)
44
+ end
45
+
46
+ it "should display deprecation notice for :equal_to" do
47
+ ::ActiveSupport::Deprecation.should_receive(:warn)
48
+ Person.validates_datetime :equal_to => Time.now
49
+ end
50
+
51
+ after(:all) do
52
+ ActiveSupport::Deprecation.silenced = false
53
+ end
54
+ end
55
+
56
+ describe "evaluate_option_value" do
57
+ it "should return Time object when restriction is Time object" do
58
+ evaluate_option_value(Time.now, :datetime).should be_kind_of(Time)
59
+ end
60
+
61
+ it "should return Time object when restriction is string" do
62
+ evaluate_option_value("2007-01-01 12:00", :datetime).should be_kind_of(Time)
63
+ end
64
+
65
+ it "should return Time object when restriction is method and method returns Time object" do
66
+ person.stub!(:datetime_attr).and_return(Time.now)
67
+ evaluate_option_value(:datetime_attr, :datetime).should be_kind_of(Time)
68
+ end
69
+
70
+ it "should return Time object when restriction is method and method returns string" do
71
+ person.stub!(:datetime_attr).and_return("2007-01-01 12:00")
72
+ evaluate_option_value(:datetime_attr, :datetime).should be_kind_of(Time)
73
+ end
74
+
75
+ it "should return Time object when restriction is proc which returns Time object" do
76
+ evaluate_option_value(lambda { Time.now }, :datetime).should be_kind_of(Time)
77
+ end
78
+
79
+ it "should return Time object when restriction is proc which returns string" do
80
+ evaluate_option_value(lambda {"2007-01-01 12:00"}, :datetime).should be_kind_of(Time)
81
+ end
82
+
83
+ it "should return array of Time objects when restriction is array of Time objects" do
84
+ time1, time2 = Time.now, 1.day.ago
85
+ evaluate_option_value([time1, time2], :datetime).should == [time2, time1]
86
+ end
87
+
88
+ it "should return array of Time objects when restriction is array of strings" do
89
+ time1, time2 = "2000-01-02", "2000-01-01"
90
+ evaluate_option_value([time1, time2], :datetime).should == [parse(time2, :datetime), parse(time1, :datetime)]
91
+ end
92
+
93
+ it "should return array of Time objects when restriction is Range of Time objects" do
94
+ time1, time2 = Time.now, 1.day.ago
95
+ evaluate_option_value(time1..time2, :datetime).should == [time2, time1]
96
+ end
97
+
98
+ it "should return array of Time objects when restriction is Range of time strings" do
99
+ time1, time2 = "2000-01-02", "2000-01-01"
100
+ evaluate_option_value(time1..time2, :datetime).should == [parse(time2, :datetime), parse(time1, :datetime)]
101
+ end
102
+ def evaluate_option_value(restriction, type)
103
+ configure_validator(:type => type)
104
+ validator.class.send(:evaluate_option_value, restriction, type, person)
105
+ end
106
+ end
107
+
108
+ describe "instance with defaults" do
109
+
110
+ describe "for datetime type" do
111
+ before do
112
+ configure_validator(:type => :datetime)
113
+ end
114
+
115
+ it "should have invalid error when date component is invalid" do
116
+ validate_with(:birth_date_and_time, "2000-01-32 01:02:03")
117
+ should_have_error(:birth_date_and_time, :invalid_datetime)
118
+ end
119
+
120
+ it "should have invalid error when time component is invalid" do
121
+ validate_with(:birth_date_and_time, "2000-01-01 25:02:03")
122
+ should_have_error(:birth_date_and_time, :invalid_datetime)
123
+ end
124
+
125
+ it "should have blank error when value is nil" do
126
+ validate_with(:birth_date_and_time, nil)
127
+ should_have_error(:birth_date_and_time, :blank)
128
+ end
129
+
130
+ it "should have no errors when value is valid" do
131
+ validate_with(:birth_date_and_time, "2000-01-01 12:00:00")
132
+ should_have_no_error(:birth_date_and_time, :invalid_datetime)
133
+ end
134
+ end
135
+
136
+ describe "for date type" do
137
+ before do
138
+ configure_validator(:type => :date)
139
+ end
140
+
141
+ it "should have invalid error when value is invalid" do
142
+ validate_with(:birth_date, "2000-01-32")
143
+ should_have_error(:birth_date, :invalid_date)
144
+ end
145
+
146
+ it "should have blank error when value is nil" do
147
+ validate_with(:birth_date, nil)
148
+ should_have_error(:birth_date, :blank)
149
+ end
150
+
151
+ it "should have no error when value is valid" do
152
+ validate_with(:birth_date, "2000-01-31")
153
+ should_have_no_error(:birth_date, :invalid_date)
154
+ end
155
+ end
156
+
157
+ describe "for time type" do
158
+ before do
159
+ configure_validator(:type => :time)
160
+ end
161
+
162
+ it "should have invalid error when value is invalid" do
163
+ validate_with(:birth_time, "25:00")
164
+ should_have_error(:birth_time, :invalid_time)
165
+ end
166
+
167
+ it "should have blank error when value is nil" do
168
+ validate_with(:birth_time, nil)
169
+ should_have_error(:birth_time, :blank)
170
+ end
171
+
172
+ it "should have no errors when value is valid" do
173
+ validate_with(:birth_date_and_time, "12:00")
174
+ should_have_no_error(:birth_time, :invalid_time)
175
+ end
176
+ end
177
+
178
+ end
179
+
180
+ describe "instance with before and after restrictions" do
181
+
182
+ describe "for datetime type" do
183
+ before :each do
184
+ configure_validator(:before => lambda { Time.now }, :after => lambda { 1.day.ago})
185
+ end
186
+
187
+ it "should have before error when value is past :before restriction" do
188
+ validate_with(:birth_date_and_time, 1.minute.from_now)
189
+ should_have_error(:birth_date_and_time, :before)
190
+ end
191
+
192
+ it "should have before error when value is on boundary of :before restriction" do
193
+ validate_with(:birth_date_and_time, Time.now)
194
+ should_have_error(:birth_date_and_time, :before)
195
+ end
196
+
197
+ it "should have after error when value is before :after restriction" do
198
+ validate_with(:birth_date_and_time, 2.days.ago)
199
+ should_have_error(:birth_date_and_time, :after)
200
+ end
201
+
202
+ it "should have after error when value is on boundary of :after restriction" do
203
+ validate_with(:birth_date_and_time, 1.day.ago)
204
+ should_have_error(:birth_date_and_time, :after)
205
+ end
206
+ end
207
+
208
+ describe "for date type" do
209
+ before :each do
210
+ configure_validator(:before => 1.day.from_now, :after => 1.day.ago, :type => :date)
211
+ end
212
+
213
+ it "should have error when value is past :before restriction" do
214
+ validate_with(:birth_date, 2.days.from_now)
215
+ should_have_error(:birth_date, :before)
216
+ end
217
+
218
+ it "should have error when value is before :after restriction" do
219
+ validate_with(:birth_date, 2.days.ago)
220
+ should_have_error(:birth_date, :after)
221
+ end
222
+
223
+ it "should have no error when value is before :before restriction" do
224
+ validate_with(:birth_date, Time.now)
225
+ should_have_no_error(:birth_date, :before)
226
+ end
227
+
228
+ it "should have no error when value is after :after restriction" do
229
+ validate_with(:birth_date, Time.now)
230
+ should_have_no_error(:birth_date, :after)
231
+ end
232
+ end
233
+
234
+ describe "for time type" do
235
+ before :each do
236
+ configure_validator(:before => "23:00", :after => "06:00", :type => :time)
237
+ end
238
+
239
+ it "should have error when value is on boundary of :before restriction" do
240
+ validate_with(:birth_time, "23:00")
241
+ should_have_error(:birth_time, :before)
242
+ end
243
+
244
+ it "should have error when value is on boundary of :after restriction" do
245
+ validate_with(:birth_time, "06:00")
246
+ should_have_error(:birth_time, :after)
247
+ end
248
+
249
+ it "should have error when value is past :before restriction" do
250
+ validate_with(:birth_time, "23:01")
251
+ should_have_error(:birth_time, :before)
252
+ end
253
+
254
+ it "should have error when value is before :after restriction" do
255
+ validate_with(:birth_time, "05:59")
256
+ should_have_error(:birth_time, :after)
257
+ end
258
+
259
+ it "should not have error when value is before :before restriction" do
260
+ validate_with(:birth_time, "22:59")
261
+ should_have_no_error(:birth_time, :before)
262
+ end
263
+
264
+ it "should have error when value is before :after restriction" do
265
+ validate_with(:birth_time, "06:01")
266
+ should_have_no_error(:birth_time, :before)
267
+ end
268
+ end
269
+ end
270
+
271
+ describe "instance with between restriction" do
272
+
273
+ describe "for datetime type" do
274
+ before do
275
+ configure_validator(:between => [1.day.ago.at_midnight, 1.day.from_now.at_midnight])
276
+ end
277
+
278
+ it "should have error when value is before earlist :between restriction" do
279
+ validate_with(:birth_date_and_time, 2.days.ago)
280
+ should_have_error(:birth_date_and_time, :between)
281
+ end
282
+
283
+ it "should have error when value is after latest :between restriction" do
284
+ validate_with(:birth_date_and_time, 2.days.from_now)
285
+ should_have_error(:birth_date_and_time, :between)
286
+ end
287
+
288
+ it "should be valid when value is equal to earliest :between restriction" do
289
+ validate_with(:birth_date_and_time, 1.day.ago.at_midnight)
290
+ should_have_no_error(:birth_date_and_time, :between)
291
+ end
292
+
293
+ it "should be valid when value is equal to latest :between restriction" do
294
+ validate_with(:birth_date_and_time, 1.day.from_now.at_midnight)
295
+ should_have_no_error(:birth_date_and_time, :between)
296
+ end
297
+
298
+ it "should allow a range for between restriction" do
299
+ configure_validator(:type => :datetime, :between => (1.day.ago.at_midnight)..(1.day.from_now.at_midnight))
300
+ validate_with(:birth_date_and_time, 1.day.from_now.at_midnight)
301
+ should_have_no_error(:birth_date_and_time, :between)
302
+ end
303
+ end
304
+
305
+ describe "for date type" do
306
+ before do
307
+ configure_validator(:type => :date, :between => [1.day.ago.to_date, 1.day.from_now.to_date])
308
+ end
309
+
310
+ it "should have error when value is before earlist :between restriction" do
311
+ validate_with(:birth_date, 2.days.ago.to_date)
312
+ should_have_error(:birth_date, :between)
313
+ end
314
+
315
+ it "should have error when value is after latest :between restriction" do
316
+ validate_with(:birth_date, 2.days.from_now.to_date)
317
+ should_have_error(:birth_date, :between)
318
+ end
319
+
320
+ it "should be valid when value is equal to earliest :between restriction" do
321
+ validate_with(:birth_date, 1.day.ago.to_date)
322
+ should_have_no_error(:birth_date, :between)
323
+ end
324
+
325
+ it "should be valid when value is equal to latest :between restriction" do
326
+ validate_with(:birth_date, 1.day.from_now.to_date)
327
+ should_have_no_error(:birth_date, :between)
328
+ end
329
+
330
+ it "should allow a range for between restriction" do
331
+ configure_validator(:type => :date, :between => (1.day.ago.to_date)..(1.day.from_now.to_date))
332
+ validate_with(:birth_date, 1.day.from_now.to_date)
333
+ should_have_no_error(:birth_date, :between)
334
+ end
335
+ end
336
+
337
+ describe "for time type" do
338
+ before do
339
+ configure_validator(:type => :time, :between => ["09:00", "17:00"])
340
+ end
341
+
342
+ it "should have error when value is before earlist :between restriction" do
343
+ validate_with(:birth_time, "08:59")
344
+ should_have_error(:birth_time, :between)
345
+ end
346
+
347
+ it "should have error when value is after latest :between restriction" do
348
+ validate_with(:birth_time, "17:01")
349
+ should_have_error(:birth_time, :between)
350
+ end
351
+
352
+ it "should be valid when value is equal to earliest :between restriction" do
353
+ validate_with(:birth_time, "09:00")
354
+ should_have_no_error(:birth_time, :between)
355
+ end
356
+
357
+ it "should be valid when value is equal to latest :between restriction" do
358
+ validate_with(:birth_time, "17:00")
359
+ should_have_no_error(:birth_time, :between)
360
+ end
361
+
362
+ it "should allow a range for between restriction" do
363
+ configure_validator(:type => :time, :between => "09:00".."17:00")
364
+ validate_with(:birth_time, "17:00")
365
+ should_have_no_error(:birth_time, :between)
366
+ end
367
+ end
368
+ end
369
+
370
+ describe "instance with :is_at restriction" do
371
+
372
+ describe "for datetime type" do
373
+ before do
374
+ configure_validator(:is_at => Time.now)
375
+ end
376
+
377
+ it "should have error when value not equal to :is_at restriction" do
378
+ validate_with(:birth_date_and_time, Time.now + 1)
379
+ should_have_error(:birth_date_and_time, :is_at)
380
+ end
381
+
382
+ it "should be valid when value is equal to :is_at restriction" do
383
+ validate_with(:birth_date_and_time, Time.now)
384
+ should_have_no_error(:birth_date_and_time, :is_at)
385
+ end
386
+ end
387
+
388
+ describe "for date type" do
389
+ before do
390
+ configure_validator(:type => :date, :is_at => Date.today)
391
+ end
392
+
393
+ it "should have error when value is not equal to :is_at restriction" do
394
+ validate_with(:birth_date, Date.today + 1)
395
+ should_have_error(:birth_date, :is_at)
396
+ end
397
+
398
+ it "should be valid when value is equal to :is_at restriction" do
399
+ validate_with(:birth_date, Date.today)
400
+ should_have_no_error(:birth_date, :is_at)
401
+ end
402
+ end
403
+
404
+ describe "for time type" do
405
+ before do
406
+ configure_validator(:type => :time, :is_at => "09:00:00")
407
+ end
408
+
409
+ it "should have error when value is not equal to :is_at restriction" do
410
+ validate_with(:birth_time, "09:00:01")
411
+ should_have_error(:birth_time, :is_at)
412
+ end
413
+
414
+ it "should be valid when value is equal to :is_at restriction" do
415
+ validate_with(:birth_time, "09:00:00")
416
+ should_have_no_error(:birth_time, :is_at)
417
+ end
418
+ end
419
+ end
420
+
421
+ describe "instance with :ignore_usec option" do
422
+
423
+ it "should ignore usec on time values when evaluated" do
424
+ configure_validator(:is_at => Time.utc(2000, 1, 1, 0, 0, 0, 0), :ignore_usec => true)
425
+ validate_with(:birth_date_and_time, Time.utc(2000, 1, 1, 0, 0, 0, 500))
426
+ should_have_no_error(:birth_date_and_time, :is_at)
427
+ end
428
+
429
+ end
430
+
431
+ describe "instance with :with_time option" do
432
+
433
+ it "should validate date attribute as datetime combining value of :with_time against restrictions " do
434
+ configure_validator(:type => :date, :with_time => '12:31', :on_or_before => Time.mktime(2000,1,1,12,30))
435
+ validate_with(:birth_date, "2000-01-01")
436
+ should_have_error(:birth_date, :on_or_before)
437
+ end
438
+
439
+ it "should skip restriction validation if :with_time value is nil" do
440
+ configure_validator(:type => :date, :with_time => nil, :on_or_before => Time.mktime(2000,1,1,12,30))
441
+ validate_with(:birth_date, "2000-01-01")
442
+ should_have_no_error(:birth_date, :on_or_before)
443
+ end
444
+
445
+ it "should should ignore usec value on combined value if :ignore_usec option is true" do
446
+ configure_validator(:type => :date, :with_time => Time.mktime(2000,1,1,12,30,0,500), :is_at => Time.mktime(2000,1,1,12,30), :ignore_usec => true)
447
+ validate_with(:birth_date, "2000-01-01")
448
+ should_have_no_error(:birth_date, :is_at)
449
+ end
450
+ end
451
+
452
+ describe "instance with :with_date option" do
453
+
454
+ it "should validate time attribute as datetime combining value of :with_date against restrictions " do
455
+ configure_validator(:type => :time, :with_date => '2009-01-01', :on_or_before => Time.mktime(2000,1,1,12,30))
456
+ validate_with(:birth_time, "12:30")
457
+ should_have_error(:birth_time, :on_or_before)
458
+ end
459
+
460
+ it "should skip restriction validation if :with_date value is nil" do
461
+ configure_validator(:type => :time, :with_date => nil, :on_or_before => Time.mktime(2000,1,1,12,30))
462
+ validate_with(:birth_time, "12:30")
463
+ should_have_no_error(:birth_time, :on_or_before)
464
+ end
465
+
466
+ it "should should ignore usec value on combined value if :ignore_usec option is true" do
467
+ configure_validator(:type => :time, :with_date => Date.new(2000,1,1), :on_or_before => Time.mktime(2000,1,1,12,30), :ignore_usec => true)
468
+ validate_with(:birth_time, Time.mktime(2000,1,1,12,30,0,50))
469
+ should_have_no_error(:birth_time, :on_or_before)
470
+ end
471
+ end
472
+
473
+ describe "instance with mixed value and restriction types" do
474
+
475
+ it "should validate datetime attribute with Date restriction" do
476
+ configure_validator(:type => :datetime, :on_or_before => Date.new(2000,1,1))
477
+ validate_with(:birth_date_and_time, "2000-01-01 00:00:00")
478
+ should_have_no_error(:birth_date_and_time, :on_or_before)
479
+ end
480
+
481
+ it "should validate date attribute with DateTime restriction value" do
482
+ configure_validator(:type => :date, :on_or_before => DateTime.new(2000, 1, 1, 0,0,0))
483
+ validate_with(:birth_date, "2000-01-01")
484
+ should_have_no_error(:birth_date, :on_or_before)
485
+ end
486
+
487
+ it "should validate date attribute with Time restriction value" do
488
+ configure_validator(:type => :date, :on_or_before => Time.utc(2000, 1, 1, 0,0,0))
489
+ validate_with(:birth_date, "2000-01-01")
490
+ should_have_no_error(:birth_date, :on_or_before)
491
+ end
492
+
493
+ it "should validate time attribute with DateTime restriction value" do
494
+ configure_validator(:type => :time, :on_or_before => DateTime.new(2000, 1, 1, 12,0,0))
495
+ validate_with(:birth_time, "12:00")
496
+ should_have_no_error(:birth_time, :on_or_before)
497
+ end
498
+
499
+ it "should validate time attribute with Time restriction value" do
500
+ configure_validator(:type => :time, :on_or_before => Time.utc(2000, 1, 1, 12,0,0))
501
+ validate_with(:birth_time, "12:00")
502
+ should_have_no_error(:birth_time, :on_or_before)
503
+ end
504
+ end
505
+
506
+ describe "instance with format option" do
507
+ it "should validate attribute when value matches format" do
508
+ configure_validator(:type => :time, :format => 'hh:nn:ss')
509
+ validate_with(:birth_time, "12:00:00")
510
+ should_have_no_error(:birth_time, :invalid_time)
511
+ end
512
+
513
+ it "should not validate attribute when value does not match format" do
514
+ configure_validator(:type => :time, :format => 'hh:nn:ss')
515
+ validate_with(:birth_time, "12:00")
516
+ should_have_error(:birth_time, :invalid_time)
517
+ end
518
+ end
519
+
520
+ if defined?(I18n)
521
+
522
+ describe "localized error messages" do
523
+ before(:all) do
524
+ message = "retfa #{I18N_INTERPOLATION}" % 'restriction'
525
+ translations = {
526
+ :activerecord => {:errors => {:messages => { :after => message }}},
527
+ :validates_timeliness => {:error_value_formats => {}}
528
+ }
529
+ I18n.backend.store_translations 'zz', translations
530
+ I18n.locale = :zz
531
+ end
532
+
533
+ it "should be used if defined" do
534
+ configure_validator(:type => :date, :after => Date.today)
535
+ validate_with(:birth_date, 1.day.ago)
536
+ person.errors.on(:birth_date).should match(/retfa/)
537
+ end
538
+
539
+ it "should use I18n translation missing message when not defined" do
540
+ configure_validator(:type => :date, :on_or_after => Date.today)
541
+ validate_with(:birth_date, 1.day.ago)
542
+ person.errors.on(:birth_date).should match(/translation missing/)
543
+ end
544
+
545
+ after(:all) do
546
+ I18n.locale = :en
547
+ end
548
+
549
+ end
550
+
551
+ end
552
+
553
+ describe "custom_error_messages" do
554
+ it "should return hash of custom error messages from configuration with _message truncated from keys" do
555
+ configure_validator(:type => :date, :invalid_date_message => 'thats no date')
556
+ validator.send(:custom_error_messages)[:invalid_date].should == 'thats no date'
557
+ end
558
+
559
+ it "should return empty hash if no custom error messages in configuration" do
560
+ configure_validator(:type => :date)
561
+ validator.send(:custom_error_messages).should be_empty
562
+ end
563
+ end
564
+
565
+ describe "interpolation_values" do
566
+ if defined?(I18n)
567
+ it "should return hash of interpolation keys with restriction values" do
568
+ before = '1900-01-01'
569
+ configure_validator(:type => :date, :before => before)
570
+ validator.send(:interpolation_values, :before, before.to_date).should == {:restriction => before}
571
+ end
572
+ else
573
+ it "should return array of interpolation values" do
574
+ before = '1900-01-01'
575
+ configure_validator(:type => :date, :before => before)
576
+ validator.send(:interpolation_values, :before, before.to_date).should == [before]
577
+ end
578
+ end
579
+ end
580
+
581
+ describe "restriction errors" do
582
+ before :each do
583
+ configure_validator(:type => :date, :before => lambda { raise })
584
+ end
585
+
586
+ it "should be added by default for invalid restriction" do
587
+ ValidatesTimeliness::Validator.ignore_restriction_errors = false
588
+ validate_with(:birth_date, Date.today)
589
+ person.errors.on(:birth_date).should match(/restriction 'before' value was invalid/)
590
+ end
591
+
592
+ it "should not be added when ignore switch is true and restriction is invalid" do
593
+ ValidatesTimeliness::Validator.ignore_restriction_errors = true
594
+ person.should be_valid
595
+ end
596
+
597
+ after :all do
598
+ ValidatesTimeliness::Validator.ignore_restriction_errors = false
599
+ end
600
+ end
601
+
602
+ describe "restriction value error message" do
603
+
604
+ describe "default formats" do
605
+
606
+ it "should format datetime value of restriction" do
607
+ configure_validator(:type => :datetime, :after => 1.day.from_now)
608
+ validate_with(:birth_date_and_time, Time.now)
609
+ person.errors.on(:birth_date_and_time).should match(/after \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\Z/)
610
+ end
611
+
612
+ it "should format date value of restriction" do
613
+ configure_validator(:type => :date, :after => 1.day.from_now)
614
+ validate_with(:birth_date, Time.now)
615
+ person.errors.on(:birth_date).should match(/after \d{4}-\d{2}-\d{2}\Z/)
616
+ end
617
+
618
+ it "should format time value of restriction" do
619
+ configure_validator(:type => :time, :after => '12:00')
620
+ validate_with(:birth_time, '11:59')
621
+ person.errors.on(:birth_time).should match(/after \d{2}:\d{2}:\d{2}\Z/)
622
+ end
623
+
624
+ if defined?(I18n)
625
+
626
+ describe "I18n" do
627
+ it "should use global default if locale format missing" do
628
+ message = "after #{I18N_INTERPOLATION}" % 'restriction'
629
+ I18n.backend.store_translations 'zz', :activerecord => {:errors => {:messages => { :after => message }}}
630
+ I18n.locale = :zz
631
+ configure_validator(:type => :datetime, :after => 1.day.from_now)
632
+ validate_with(:birth_date_and_time, Time.now)
633
+ person.errors.on(:birth_date_and_time).should match(/after \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\Z/)
634
+ end
635
+
636
+ after do
637
+ I18n.locale = :en
638
+ end
639
+ end
640
+
641
+ end
642
+ end
643
+
644
+ describe "custom formats" do
645
+
646
+ before :all do
647
+ custom = {
648
+ :time => '%H:%M %p',
649
+ :date => '%d-%m-%Y',
650
+ :datetime => '%d-%m-%Y %H:%M %p'
651
+ }
652
+
653
+ if defined?(I18n)
654
+ I18n.backend.store_translations 'en', :validates_timeliness => { :error_value_formats => custom }
655
+ else
656
+ @@formats = ValidatesTimeliness::Validator.error_value_formats
657
+ ValidatesTimeliness::Validator.error_value_formats = custom
658
+ end
659
+ end
660
+
661
+ it "should format datetime value of restriction" do
662
+ configure_validator(:type => :datetime, :after => 1.day.from_now)
663
+ validate_with(:birth_date_and_time, Time.now)
664
+ person.errors.on(:birth_date_and_time).should match(/after \d{2}-\d{2}-\d{4} \d{2}:\d{2} (AM|PM)\Z/)
665
+ end
666
+
667
+ it "should format date value of restriction" do
668
+ configure_validator(:type => :date, :after => 1.day.from_now)
669
+ validate_with(:birth_date, Time.now)
670
+ person.errors.on(:birth_date).should match(/after \d{2}-\d{2}-\d{4}\Z/)
671
+ end
672
+
673
+ it "should format time value of restriction" do
674
+ configure_validator(:type => :time, :after => '12:00')
675
+ validate_with(:birth_time, '11:59')
676
+ person.errors.on(:birth_time).should match(/after \d{2}:\d{2} (AM|PM)\Z/)
677
+ end
678
+
679
+ after :all do
680
+ if defined?(I18n)
681
+ I18n.reload!
682
+ else
683
+ ValidatesTimeliness::Validator.error_value_formats = @@formats
684
+ end
685
+ end
686
+ end
687
+
688
+ end
689
+
690
+ def parse(*args)
691
+ ValidatesTimeliness::Parser.parse(*args)
692
+ end
693
+
694
+ def configure_validator(options={})
695
+ @validator = ValidatesTimeliness::Validator.new(options)
696
+ end
697
+
698
+ def validate_with(attr_name, value)
699
+ person.send("#{attr_name}=", value)
700
+ validator.call(person, attr_name, value)
701
+ end
702
+
703
+ def should_have_error(attr_name, error)
704
+ message = error_messages[error]
705
+ person.errors.on(attr_name).should match(/#{message}/)
706
+ end
707
+
708
+ def should_have_no_error(attr_name, error)
709
+ message = error_messages[error]
710
+ errors = person.errors.on(attr_name)
711
+ if errors
712
+ errors.should_not match(/#{message}/)
713
+ else
714
+ errors.should be_nil
715
+ end
716
+ end
717
+
718
+ def error_messages
719
+ return @error_messages if defined?(@error_messages)
720
+ messages = defined?(I18n) ? I18n.t('activerecord.errors.messages') : validator.send(:error_messages)
721
+ @error_messages = messages.inject({}) {|h, (k, v)| h[k] = v.sub(/ (\%s|#{I18N_REGEXP}).*/, ''); h }
722
+ end
723
+ end