adzap-validates_timeliness 1.1.1

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 (35) hide show
  1. data/CHANGELOG +49 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +329 -0
  4. data/Rakefile +58 -0
  5. data/TODO +7 -0
  6. data/lib/validates_timeliness.rb +67 -0
  7. data/lib/validates_timeliness/action_view/instance_tag.rb +45 -0
  8. data/lib/validates_timeliness/active_record/attribute_methods.rb +157 -0
  9. data/lib/validates_timeliness/active_record/multiparameter_attributes.rb +64 -0
  10. data/lib/validates_timeliness/core_ext/date.rb +13 -0
  11. data/lib/validates_timeliness/core_ext/date_time.rb +13 -0
  12. data/lib/validates_timeliness/core_ext/time.rb +13 -0
  13. data/lib/validates_timeliness/formats.rb +309 -0
  14. data/lib/validates_timeliness/locale/en.yml +12 -0
  15. data/lib/validates_timeliness/spec/rails/matchers/validate_timeliness.rb +157 -0
  16. data/lib/validates_timeliness/validation_methods.rb +82 -0
  17. data/lib/validates_timeliness/validator.rb +163 -0
  18. data/spec/action_view/instance_tag_spec.rb +38 -0
  19. data/spec/active_record/attribute_methods_spec.rb +204 -0
  20. data/spec/active_record/multiparameter_attributes_spec.rb +48 -0
  21. data/spec/core_ext/dummy_time_spec.rb +31 -0
  22. data/spec/formats_spec.rb +274 -0
  23. data/spec/ginger_scenarios.rb +19 -0
  24. data/spec/resources/application.rb +2 -0
  25. data/spec/resources/person.rb +3 -0
  26. data/spec/resources/schema.rb +10 -0
  27. data/spec/resources/sqlite_patch.rb +19 -0
  28. data/spec/spec/rails/matchers/validate_timeliness_spec.rb +206 -0
  29. data/spec/spec_helper.rb +54 -0
  30. data/spec/time_travel/MIT-LICENSE +20 -0
  31. data/spec/time_travel/time_extensions.rb +33 -0
  32. data/spec/time_travel/time_travel.rb +12 -0
  33. data/spec/validation_methods_spec.rb +61 -0
  34. data/spec/validator_spec.rb +475 -0
  35. metadata +105 -0
@@ -0,0 +1,475 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe ValidatesTimeliness::Validator do
4
+ attr_accessor :person, :validator
5
+
6
+ before :all do
7
+ # freezes time using time_travel plugin
8
+ Time.now = Time.utc(2000, 1, 1, 0, 0, 0)
9
+ end
10
+
11
+ after :all do
12
+ Time.now = nil
13
+ end
14
+
15
+ before :each do
16
+ @person = Person.new
17
+ end
18
+
19
+ describe "restriction_value" do
20
+ it "should return Time object when restriction is Time object" do
21
+ restriction_value(Time.now, :datetime).should be_kind_of(Time)
22
+ end
23
+
24
+ it "should return Time object when restriction is string" do
25
+ restriction_value("2007-01-01 12:00", :datetime).should be_kind_of(Time)
26
+ end
27
+
28
+ it "should return Time object when restriction is method and method returns Time object" do
29
+ person.stub!(:datetime_attr).and_return(Time.now)
30
+ restriction_value(:datetime_attr, :datetime).should be_kind_of(Time)
31
+ end
32
+
33
+ it "should return Time object when restriction is method and method returns string" do
34
+ person.stub!(:datetime_attr).and_return("2007-01-01 12:00")
35
+ restriction_value(:datetime_attr, :datetime).should be_kind_of(Time)
36
+ end
37
+
38
+ it "should return Time object when restriction is proc which returns Time object" do
39
+ restriction_value(lambda { Time.now }, :datetime).should be_kind_of(Time)
40
+ end
41
+
42
+ it "should return Time object when restriction is proc which returns string" do
43
+ restriction_value(lambda {"2007-01-01 12:00"}, :datetime).should be_kind_of(Time)
44
+ end
45
+
46
+ it "should return array of Time objects when restriction is array of Time objects" do
47
+ time1, time2 = Time.now, 1.day.ago
48
+ restriction_value([time1, time2], :datetime).should == [time2, time1]
49
+ end
50
+
51
+ it "should return array of Time objects when restriction is array of strings" do
52
+ time1, time2 = "2000-01-02", "2000-01-01"
53
+ restriction_value([time1, time2], :datetime).should == [Person.parse_date_time(time2, :datetime), Person.parse_date_time(time1, :datetime)]
54
+ end
55
+
56
+ it "should return array of Time objects when restriction is Range of Time objects" do
57
+ time1, time2 = Time.now, 1.day.ago
58
+ restriction_value(time1..time2, :datetime).should == [time2, time1]
59
+ end
60
+
61
+ it "should return array of Time objects when restriction is Range of time strings" do
62
+ time1, time2 = "2000-01-02", "2000-01-01"
63
+ restriction_value(time1..time2, :datetime).should == [Person.parse_date_time(time2, :datetime), Person.parse_date_time(time1, :datetime)]
64
+ end
65
+ def restriction_value(restriction, type)
66
+ configure_validator(:type => type)
67
+ validator.send(:restriction_value, restriction, person)
68
+ end
69
+ end
70
+
71
+ describe "instance with defaults" do
72
+
73
+ describe "for datetime type" do
74
+ before do
75
+ configure_validator(:type => :datetime)
76
+ end
77
+
78
+ it "should have invalid error when date component is invalid" do
79
+ validate_with(:birth_date_and_time, "2000-01-32 01:02:03")
80
+ should_have_error(:birth_date_and_time, :invalid_datetime)
81
+ end
82
+
83
+ it "should have invalid error when time component is invalid" do
84
+ validate_with(:birth_date_and_time, "2000-01-01 25:02:03")
85
+ should_have_error(:birth_date_and_time, :invalid_datetime)
86
+ end
87
+
88
+ it "should have blank error when value is nil" do
89
+ validate_with(:birth_date_and_time, nil)
90
+ should_have_error(:birth_date_and_time, :blank)
91
+ end
92
+
93
+ it "should have no errors when value is valid" do
94
+ validate_with(:birth_date_and_time, "2000-01-01 12:00:00")
95
+ should_have_no_error(:birth_date_and_time, :invalid_datetime)
96
+ end
97
+ end
98
+
99
+ describe "for date type" do
100
+ before do
101
+ configure_validator(:type => :date)
102
+ end
103
+
104
+ it "should have invalid error when value is invalid" do
105
+ validate_with(:birth_date, "2000-01-32")
106
+ should_have_error(:birth_date, :invalid_date)
107
+ end
108
+
109
+ it "should have blank error when value is nil" do
110
+ validate_with(:birth_date, nil)
111
+ should_have_error(:birth_date, :blank)
112
+ end
113
+
114
+ it "should have no error when value is valid" do
115
+ validate_with(:birth_date, "2000-01-31")
116
+ should_have_no_error(:birth_date, :invalid_date)
117
+ end
118
+ end
119
+
120
+ describe "for time type" do
121
+ before do
122
+ configure_validator(:type => :time)
123
+ end
124
+
125
+ it "should have invalid error when value is invalid" do
126
+ validate_with(:birth_time, "25:00")
127
+ should_have_error(:birth_time, :invalid_time)
128
+ end
129
+
130
+ it "should have blank error when value is nil" do
131
+ validate_with(:birth_time, nil)
132
+ should_have_error(:birth_time, :blank)
133
+ end
134
+
135
+ it "should have no errors when value is valid" do
136
+ validate_with(:birth_date_and_time, "12:00")
137
+ should_have_no_error(:birth_time, :invalid_time)
138
+ end
139
+ end
140
+
141
+ end
142
+
143
+ describe "instance with before and after restrictions" do
144
+
145
+ describe "for datetime type" do
146
+ before :each do
147
+ configure_validator(:before => lambda { Time.now }, :after => lambda { 1.day.ago})
148
+ end
149
+
150
+ it "should have before error when value is past :before restriction" do
151
+ validate_with(:birth_date_and_time, 1.minute.from_now)
152
+ should_have_error(:birth_date_and_time, :before)
153
+ end
154
+
155
+ it "should have before error when value is on boundary of :before restriction" do
156
+ validate_with(:birth_date_and_time, Time.now)
157
+ should_have_error(:birth_date_and_time, :before)
158
+ end
159
+
160
+ it "should have after error when value is before :after restriction" do
161
+ validate_with(:birth_date_and_time, 2.days.ago)
162
+ should_have_error(:birth_date_and_time, :after)
163
+ end
164
+
165
+ it "should have after error when value is on boundary of :after restriction" do
166
+ validate_with(:birth_date_and_time, 1.day.ago)
167
+ should_have_error(:birth_date_and_time, :after)
168
+ end
169
+ end
170
+
171
+ describe "for date type" do
172
+ before :each do
173
+ configure_validator(:before => 1.day.from_now, :after => 1.day.ago, :type => :date)
174
+ end
175
+
176
+ it "should have error when value is past :before restriction" do
177
+ validate_with(:birth_date, 2.days.from_now)
178
+ should_have_error(:birth_date, :before)
179
+ end
180
+
181
+ it "should have error when value is before :after restriction" do
182
+ validate_with(:birth_date, 2.days.ago)
183
+ should_have_error(:birth_date, :after)
184
+ end
185
+
186
+ it "should have no error when value is before :before restriction" do
187
+ validate_with(:birth_date, Time.now)
188
+ should_have_no_error(:birth_date, :before)
189
+ end
190
+
191
+ it "should have no error when value is after :after restriction" do
192
+ validate_with(:birth_date, Time.now)
193
+ should_have_no_error(:birth_date, :after)
194
+ end
195
+ end
196
+
197
+ describe "for time type" do
198
+ before :each do
199
+ configure_validator(:before => "23:00", :after => "06:00", :type => :time)
200
+ end
201
+
202
+ it "should have error when value is on boundary of :before restriction" do
203
+ validate_with(:birth_time, "23:00")
204
+ should_have_error(:birth_time, :before)
205
+ end
206
+
207
+ it "should have error when value is on boundary of :after restriction" do
208
+ validate_with(:birth_time, "06:00")
209
+ should_have_error(:birth_time, :after)
210
+ end
211
+
212
+ it "should have error when value is past :before restriction" do
213
+ validate_with(:birth_time, "23:01")
214
+ should_have_error(:birth_time, :before)
215
+ end
216
+
217
+ it "should have error when value is before :after restriction" do
218
+ validate_with(:birth_time, "05:59")
219
+ should_have_error(:birth_time, :after)
220
+ end
221
+
222
+ it "should not have error when value is before :before restriction" do
223
+ validate_with(:birth_time, "22:59")
224
+ should_have_no_error(:birth_time, :before)
225
+ end
226
+
227
+ it "should have error when value is before :after restriction" do
228
+ validate_with(:birth_time, "06:01")
229
+ should_have_no_error(:birth_time, :before)
230
+ end
231
+ end
232
+ end
233
+
234
+ describe "instance with between restriction" do
235
+
236
+ describe "for datetime type" do
237
+ before do
238
+ configure_validator(:between => [1.day.ago.at_midnight, 1.day.from_now.at_midnight])
239
+ end
240
+
241
+ it "should have error when value is before earlist :between restriction" do
242
+ validate_with(:birth_date_and_time, 2.days.ago)
243
+ should_have_error(:birth_date_and_time, :between)
244
+ end
245
+
246
+ it "should have error when value is after latest :between restriction" do
247
+ validate_with(:birth_date_and_time, 2.days.from_now)
248
+ should_have_error(:birth_date_and_time, :between)
249
+ end
250
+
251
+ it "should be valid when value is equal to earliest :between restriction" do
252
+ validate_with(:birth_date_and_time, 1.day.ago.at_midnight)
253
+ should_have_no_error(:birth_date_and_time, :between)
254
+ end
255
+
256
+ it "should be valid when value is equal to latest :between restriction" do
257
+ validate_with(:birth_date_and_time, 1.day.from_now.at_midnight)
258
+ should_have_no_error(:birth_date_and_time, :between)
259
+ end
260
+
261
+ it "should allow a range for between restriction" do
262
+ configure_validator(:type => :datetime, :between => (1.day.ago.at_midnight)..(1.day.from_now.at_midnight))
263
+ validate_with(:birth_date_and_time, 1.day.from_now.at_midnight)
264
+ should_have_no_error(:birth_date_and_time, :between)
265
+ end
266
+ end
267
+
268
+ describe "for date type" do
269
+ before do
270
+ configure_validator(:type => :date, :between => [1.day.ago.to_date, 1.day.from_now.to_date])
271
+ end
272
+
273
+ it "should have error when value is before earlist :between restriction" do
274
+ validate_with(:birth_date, 2.days.ago.to_date)
275
+ should_have_error(:birth_date, :between)
276
+ end
277
+
278
+ it "should have error when value is after latest :between restriction" do
279
+ validate_with(:birth_date, 2.days.from_now.to_date)
280
+ should_have_error(:birth_date, :between)
281
+ end
282
+
283
+ it "should be valid when value is equal to earliest :between restriction" do
284
+ validate_with(:birth_date, 1.day.ago.to_date)
285
+ should_have_no_error(:birth_date, :between)
286
+ end
287
+
288
+ it "should be valid when value is equal to latest :between restriction" do
289
+ validate_with(:birth_date, 1.day.from_now.to_date)
290
+ should_have_no_error(:birth_date, :between)
291
+ end
292
+
293
+ it "should allow a range for between restriction" do
294
+ configure_validator(:type => :date, :between => (1.day.ago.to_date)..(1.day.from_now.to_date))
295
+ validate_with(:birth_date, 1.day.from_now.to_date)
296
+ should_have_no_error(:birth_date, :between)
297
+ end
298
+ end
299
+
300
+ describe "for time type" do
301
+ before do
302
+ configure_validator(:type => :time, :between => ["09:00", "17:00"])
303
+ end
304
+
305
+ it "should have error when value is before earlist :between restriction" do
306
+ validate_with(:birth_time, "08:59")
307
+ should_have_error(:birth_time, :between)
308
+ end
309
+
310
+ it "should have error when value is after latest :between restriction" do
311
+ validate_with(:birth_time, "17:01")
312
+ should_have_error(:birth_time, :between)
313
+ end
314
+
315
+ it "should be valid when value is equal to earliest :between restriction" do
316
+ validate_with(:birth_time, "09:00")
317
+ should_have_no_error(:birth_time, :between)
318
+ end
319
+
320
+ it "should be valid when value is equal to latest :between restriction" do
321
+ validate_with(:birth_time, "17:00")
322
+ should_have_no_error(:birth_time, :between)
323
+ end
324
+
325
+ it "should allow a range for between restriction" do
326
+ configure_validator(:type => :time, :between => "09:00".."17:00")
327
+ validate_with(:birth_time, "17:00")
328
+ should_have_no_error(:birth_time, :between)
329
+ end
330
+ end
331
+ end
332
+
333
+ describe "instance with mixed value and restriction types" do
334
+
335
+ it "should validate datetime attribute with Date restriction" do
336
+ configure_validator(:type => :datetime, :on_or_before => Date.new(2000,1,1))
337
+ validate_with(:birth_date_and_time, "2000-01-01 00:00:00")
338
+ should_have_no_error(:birth_date_and_time, :on_or_before)
339
+ end
340
+
341
+ it "should validate date attribute with DateTime restriction value" do
342
+ configure_validator(:type => :date, :on_or_before => DateTime.new(2000, 1, 1, 0,0,0))
343
+ validate_with(:birth_date, "2000-01-01")
344
+ should_have_no_error(:birth_date, :on_or_before)
345
+ end
346
+
347
+ it "should validate date attribute with Time restriction value" do
348
+ configure_validator(:type => :date, :on_or_before => Time.utc(2000, 1, 1, 0,0,0))
349
+ validate_with(:birth_date, "2000-01-01")
350
+ should_have_no_error(:birth_date, :on_or_before)
351
+ end
352
+
353
+ it "should validate time attribute with DateTime restriction value" do
354
+ configure_validator(:type => :time, :on_or_before => DateTime.new(2000, 1, 1, 12,0,0))
355
+ validate_with(:birth_time, "12:00")
356
+ should_have_no_error(:birth_time, :on_or_before)
357
+ end
358
+
359
+ it "should validate time attribute with Time restriction value" do
360
+ configure_validator(:type => :time, :on_or_before => Time.utc(2000, 1, 1, 12,0,0))
361
+ validate_with(:birth_time, "12:00")
362
+ should_have_no_error(:birth_time, :on_or_before)
363
+ end
364
+ end
365
+
366
+ describe "restriction errors" do
367
+ before :each do
368
+ configure_validator(:type => :date, :before => lambda { raise })
369
+ end
370
+
371
+ it "should be added by default for invalid restriction" do
372
+ ValidatesTimeliness::Validator.ignore_restriction_errors = false
373
+ validate_with(:birth_date, Date.today)
374
+ person.errors.on(:birth_date).should match(/restriction 'before' value was invalid/)
375
+ end
376
+
377
+ it "should not be added when ignore switch is true and restriction is invalid" do
378
+ ValidatesTimeliness::Validator.ignore_restriction_errors = true
379
+ person.should be_valid
380
+ end
381
+
382
+ after :all do
383
+ ValidatesTimeliness::Validator.ignore_restriction_errors = false
384
+ end
385
+ end
386
+
387
+ describe "restriction value error message" do
388
+
389
+ describe "default formats" do
390
+
391
+ it "should format datetime value of restriction" do
392
+ configure_validator(:type => :datetime, :after => 1.day.from_now)
393
+ validate_with(:birth_date_and_time, Time.now)
394
+ person.errors.on(:birth_date_and_time).should match(/after \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\Z/)
395
+ end
396
+
397
+ it "should format date value of restriction" do
398
+ configure_validator(:type => :date, :after => 1.day.from_now)
399
+ validate_with(:birth_date, Time.now)
400
+ person.errors.on(:birth_date).should match(/after \d{4}-\d{2}-\d{2}\Z/)
401
+ end
402
+
403
+ it "should format time value of restriction" do
404
+ configure_validator(:type => :time, :after => '12:00')
405
+ validate_with(:birth_time, '11:59')
406
+ person.errors.on(:birth_time).should match(/after \d{2}:\d{2}:\d{2}\Z/)
407
+ end
408
+ end
409
+
410
+ describe "custom formats" do
411
+
412
+ before :all do
413
+ @@formats = ValidatesTimeliness::Validator.error_value_formats
414
+ ValidatesTimeliness::Validator.error_value_formats = {
415
+ :time => '%H:%M %p',
416
+ :date => '%d-%m-%Y',
417
+ :datetime => '%d-%m-%Y %H:%M %p'
418
+ }
419
+ end
420
+
421
+ it "should format datetime value of restriction" do
422
+ configure_validator(:type => :datetime, :after => 1.day.from_now)
423
+ validate_with(:birth_date_and_time, Time.now)
424
+ person.errors.on(:birth_date_and_time).should match(/after \d{2}-\d{2}-\d{4} \d{2}:\d{2} (AM|PM)\Z/)
425
+ end
426
+
427
+ it "should format date value of restriction" do
428
+ configure_validator(:type => :date, :after => 1.day.from_now)
429
+ validate_with(:birth_date, Time.now)
430
+ person.errors.on(:birth_date).should match(/after \d{2}-\d{2}-\d{4}\Z/)
431
+ end
432
+
433
+ it "should format time value of restriction" do
434
+ configure_validator(:type => :time, :after => '12:00')
435
+ validate_with(:birth_time, '11:59')
436
+ person.errors.on(:birth_time).should match(/after \d{2}:\d{2} (AM|PM)\Z/)
437
+ end
438
+
439
+ after :all do
440
+ ValidatesTimeliness::Validator.error_value_formats = @@formats
441
+ end
442
+ end
443
+
444
+ end
445
+
446
+ def configure_validator(options={})
447
+ @validator = ValidatesTimeliness::Validator.new(options)
448
+ end
449
+
450
+ def validate_with(attr_name, value)
451
+ person.send("#{attr_name}=", value)
452
+ validator.call(person, attr_name)
453
+ end
454
+
455
+ def should_have_error(attr_name, error)
456
+ message = error_messages[error]
457
+ person.errors.on(attr_name).should match(/#{message}/)
458
+ end
459
+
460
+ def should_have_no_error(attr_name, error)
461
+ message = error_messages[error]
462
+ errors = person.errors.on(attr_name)
463
+ if errors
464
+ errors.should_not match(/#{message}/)
465
+ else
466
+ errors.should be_nil
467
+ end
468
+ end
469
+
470
+ def error_messages
471
+ return @error_messages if defined?(@error_messages)
472
+ messages = validator.send(:error_messages)
473
+ @error_messages = messages.inject({}) {|h, (k, v)| h[k] = v.sub(/ (\%s|\{\{\w*\}\}).*/, ''); h }
474
+ end
475
+ end