adzap-validates_timeliness 1.1.1

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