validates_timeliness 1.0.0

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 +43 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +320 -0
  4. data/Rakefile +58 -0
  5. data/TODO +8 -0
  6. data/lib/validates_timeliness.rb +66 -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 +310 -0
  14. data/lib/validates_timeliness/locale/en.yml +11 -0
  15. data/lib/validates_timeliness/spec/rails/matchers/validate_timeliness.rb +121 -0
  16. data/lib/validates_timeliness/validation_methods.rb +82 -0
  17. data/lib/validates_timeliness/validator.rb +120 -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 +178 -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 +438 -0
  35. metadata +105 -0
@@ -0,0 +1,48 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe ValidatesTimeliness::ActiveRecord::MultiparameterAttributes do
4
+ def obj
5
+ @obj ||= Person.new
6
+ end
7
+
8
+ it "should convert array for datetime type into datetime string" do
9
+ time_string = obj.time_array_to_string([2000,2,1,9,10,11], :datetime)
10
+ time_string.should == "2000-02-01 09:10:11"
11
+ end
12
+
13
+ it "should convert array for date type into date string" do
14
+ time_string = obj.time_array_to_string([2000,2,1], :date)
15
+ time_string.should == "2000-02-01"
16
+ end
17
+
18
+ it "should convert array for time type into time string" do
19
+ time_string = obj.time_array_to_string([2000,1,1,9,10,11], :time)
20
+ time_string.should == "09:10:11"
21
+ end
22
+
23
+ describe "execute_callstack_for_multiparameter_attributes" do
24
+ before do
25
+ @callstack = {
26
+ 'birth_date_and_time' => [2000,2,1,9,10,11],
27
+ 'birth_date' => [2000,2,1,9,10,11],
28
+ 'birth_time' => [2000,2,1,9,10,11]
29
+ }
30
+ end
31
+
32
+ it "should store datetime string for datetime column" do
33
+ obj.should_receive(:birth_date_and_time=).once.with("2000-02-01 09:10:11")
34
+ obj.send(:execute_callstack_for_multiparameter_attributes, @callstack)
35
+ end
36
+
37
+ it "should store date string for a date column" do
38
+ obj.should_receive(:birth_date=).once.with("2000-02-01")
39
+ obj.send(:execute_callstack_for_multiparameter_attributes, @callstack)
40
+ end
41
+
42
+ it "should store time string for a time column" do
43
+ obj.should_receive(:birth_time=).once.with("09:10:11")
44
+ obj.send(:execute_callstack_for_multiparameter_attributes, @callstack)
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,31 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe ValidatesTimeliness::CoreExtensions::Date do
4
+ before do
5
+ @a_date = Date.new(2008, 7, 1)
6
+ end
7
+
8
+ it "should make a date value into a dummy time value" do
9
+ @a_date.to_dummy_time.should == Time.utc(2000,1,1,0,0,0)
10
+ end
11
+ end
12
+
13
+ describe ValidatesTimeliness::CoreExtensions::Time do
14
+ before do
15
+ @a_time = Time.mktime(2008, 7, 1, 2, 3, 4)
16
+ end
17
+
18
+ it "should make a time value into a dummy time value" do
19
+ @a_time.to_dummy_time.should == Time.utc(2000,1,1,2,3,4)
20
+ end
21
+ end
22
+
23
+ describe ValidatesTimeliness::CoreExtensions::DateTime do
24
+ before do
25
+ @a_datetime = DateTime.new(2008, 7, 1, 2, 3, 4)
26
+ end
27
+
28
+ it "should make a datetime value into a dummy time value" do
29
+ @a_datetime.to_dummy_time.should == Time.utc(2000,1,1,2,3,4)
30
+ end
31
+ end
@@ -0,0 +1,274 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe ValidatesTimeliness::Formats do
4
+ attr_reader :formats
5
+
6
+ before do
7
+ @formats = ValidatesTimeliness::Formats
8
+ end
9
+
10
+ describe "expression generator" do
11
+ it "should generate regexp for time" do
12
+ generate_regexp_str('hh:nn:ss').should == '/(\d{2}):(\d{2}):(\d{2})/'
13
+ end
14
+
15
+ it "should generate regexp for time with meridian" do
16
+ generate_regexp_str('hh:nn:ss ampm').should == '/(\d{2}):(\d{2}):(\d{2}) ((?:[aApP])\.?[mM]\.?)/'
17
+ end
18
+
19
+ it "should generate regexp for time with meridian and optional space between" do
20
+ generate_regexp_str('hh:nn:ss_ampm').should == '/(\d{2}):(\d{2}):(\d{2})\s?((?:[aApP])\.?[mM]\.?)/'
21
+ end
22
+
23
+ it "should generate regexp for time with single or double digits" do
24
+ generate_regexp_str('h:n:s').should == '/(\d{1,2}):(\d{1,2}):(\d{1,2})/'
25
+ end
26
+
27
+ it "should generate regexp for date" do
28
+ generate_regexp_str('yyyy-mm-dd').should == '/(\d{4})-(\d{2})-(\d{2})/'
29
+ end
30
+
31
+ it "should generate regexp for date with slashes" do
32
+ generate_regexp_str('dd/mm/yyyy').should == '/(\d{2})\/(\d{2})\/(\d{4})/'
33
+ end
34
+
35
+ it "should generate regexp for date with dots" do
36
+ generate_regexp_str('dd.mm.yyyy').should == '/(\d{2})\.(\d{2})\.(\d{4})/'
37
+ end
38
+
39
+ it "should generate regexp for Ruby time string" do
40
+ expected = '/(\w{3,9}) (\w{3,9}) (\d{2}):(\d{2}):(\d{2}) (?:[+-]\d{2}:?\d{2}) (\d{4})/'
41
+ generate_regexp_str('ddd mmm hh:nn:ss zo yyyy').should == expected
42
+ end
43
+
44
+ it "should generate regexp for iso8601 datetime" do
45
+ expected = '/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:Z|(?:[+-]\d{2}:?\d{2}))/'
46
+ generate_regexp_str('yyyy-mm-ddThh:nn:ss(?:Z|zo)').should == expected
47
+ end
48
+ end
49
+
50
+ describe "format proc generator" do
51
+ it "should generate proc which outputs date array with values in correct order" do
52
+ generate_proc('yyyy-mm-dd').call('2000', '1', '2').should == [2000,1,2,0,0,0,0]
53
+ end
54
+
55
+ it "should generate proc which outputs date array from format with different order" do
56
+ generate_proc('dd/mm/yyyy').call('2', '1', '2000').should == [2000,1,2,0,0,0,0]
57
+ end
58
+
59
+ it "should generate proc which outputs time array" do
60
+ generate_proc('hh:nn:ss').call('01', '02', '03').should == [0,0,0,1,2,3,0]
61
+ end
62
+
63
+ it "should generate proc which outputs time array with meridian 'pm' adjusted hour" do
64
+ generate_proc('hh:nn:ss ampm').call('01', '02', '03', 'pm').should == [0,0,0,13,2,3,0]
65
+ end
66
+
67
+ it "should generate proc which outputs time array with meridian 'am' unadjusted hour" do
68
+ generate_proc('hh:nn:ss ampm').call('01', '02', '03', 'am').should == [0,0,0,1,2,3,0]
69
+ end
70
+
71
+ it "should generate proc which outputs time array with microseconds" do
72
+ generate_proc('hh:nn:ss.u').call('01', '02', '03', '99').should == [0,0,0,1,2,3,990000]
73
+ end
74
+ end
75
+
76
+ describe "validation regexps" do
77
+
78
+ describe "for time formats" do
79
+ format_tests = {
80
+ 'hh:nn:ss' => {:pass => ['12:12:12', '01:01:01'], :fail => ['1:12:12', '12:1:12', '12:12:1', '12-12-12']},
81
+ 'hh-nn-ss' => {:pass => ['12-12-12', '01-01-01'], :fail => ['1-12-12', '12-1-12', '12-12-1', '12:12:12']},
82
+ 'h:nn' => {:pass => ['12:12', '1:01'], :fail => ['12:2', '12-12']},
83
+ 'h.nn' => {:pass => ['2.12', '12.12'], :fail => ['2.1', '12:12']},
84
+ 'h nn' => {:pass => ['2 12', '12 12'], :fail => ['2 1', '2.12', '12:12']},
85
+ 'h-nn' => {:pass => ['2-12', '12-12'], :fail => ['2-1', '2.12', '12:12']},
86
+ 'h:nn_ampm' => {:pass => ['2:12am', '2:12 pm', '2:12 AM', '2:12PM'], :fail => ['1:2am', '1:12 pm', '2.12am']},
87
+ 'h.nn_ampm' => {:pass => ['2.12am', '2.12 pm'], :fail => ['1:2am', '1:12 pm', '2:12am']},
88
+ 'h nn_ampm' => {:pass => ['2 12am', '2 12 pm'], :fail => ['1 2am', '1 12 pm', '2:12am']},
89
+ 'h-nn_ampm' => {:pass => ['2-12am', '2-12 pm'], :fail => ['1-2am', '1-12 pm', '2:12am']},
90
+ 'h_ampm' => {:pass => ['2am', '2 am', '12 pm'], :fail => ['1.am', '12 pm', '2:12am']},
91
+ }
92
+ format_tests.each do |format, values|
93
+ it "should correctly validate times in format '#{format}'" do
94
+ regexp = generate_regexp(format)
95
+ values[:pass].each {|value| value.should match(regexp)}
96
+ values[:fail].each {|value| value.should_not match(regexp)}
97
+ end
98
+ end
99
+ end
100
+
101
+ describe "for date formats" do
102
+ format_tests = {
103
+ 'yyyy/mm/dd' => {:pass => ['2000/02/01'], :fail => ['2000\02\01', '2000/2/1', '00/02/01']},
104
+ 'yyyy-mm-dd' => {:pass => ['2000-02-01'], :fail => ['2000\02\01', '2000-2-1', '00-02-01']},
105
+ 'yyyy.mm.dd' => {:pass => ['2000.02.01'], :fail => ['2000\02\01', '2000.2.1', '00.02.01']},
106
+ 'm/d/yy' => {:pass => ['2/1/01', '02/01/00', '02/01/2000'], :fail => ['2/1/0', '2.1.01']},
107
+ 'd/m/yy' => {:pass => ['1/2/01', '01/02/00', '01/02/2000'], :fail => ['1/2/0', '1.2.01']},
108
+ 'm\d\yy' => {:pass => ['2\1\01', '2\01\00', '02\01\2000'], :fail => ['2\1\0', '2/1/01']},
109
+ 'd\m\yy' => {:pass => ['1\2\01', '1\02\00', '01\02\2000'], :fail => ['1\2\0', '1/2/01']},
110
+ 'd-m-yy' => {:pass => ['1-2-01', '1-02-00', '01-02-2000'], :fail => ['1-2-0', '1/2/01']},
111
+ 'd.m.yy' => {:pass => ['1.2.01', '1.02.00', '01.02.2000'], :fail => ['1.2.0', '1/2/01']},
112
+ 'd mmm yy' => {:pass => ['1 Feb 00', '1 Feb 2000', '1 February 00', '01 February 2000'],
113
+ :fail => ['1 Fe 00', 'Feb 1 2000', '1 Feb 0']}
114
+ }
115
+ format_tests.each do |format, values|
116
+ it "should correctly validate dates in format '#{format}'" do
117
+ regexp = generate_regexp(format)
118
+ values[:pass].each {|value| value.should match(regexp)}
119
+ values[:fail].each {|value| value.should_not match(regexp)}
120
+ end
121
+ end
122
+ end
123
+
124
+ describe "for datetime formats" do
125
+ format_tests = {
126
+ 'ddd mmm d hh:nn:ss zo yyyy' => {:pass => ['Sat Jul 19 12:00:00 +1000 2008'], :fail => []},
127
+ 'yyyy-mm-ddThh:nn:ss(?:Z|zo)' => {:pass => ['2008-07-19T12:00:00+10:00', '2008-07-19T12:00:00Z'], :fail => ['2008-07-19T12:00:00Z+10:00']},
128
+ }
129
+ format_tests.each do |format, values|
130
+ it "should correctly validate datetimes in format '#{format}'" do
131
+ regexp = generate_regexp(format)
132
+ values[:pass].each {|value| value.should match(regexp)}
133
+ values[:fail].each {|value| value.should_not match(regexp)}
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ describe "extracting values" do
140
+
141
+ it "should return time array from date string" do
142
+ time_array = formats.parse('12:13:14', :time, true)
143
+ time_array.should == [0,0,0,12,13,14,0]
144
+ end
145
+
146
+ it "should return date array from time string" do
147
+ time_array = formats.parse('2000-02-01', :date, true)
148
+ time_array.should == [2000,2,1,0,0,0,0]
149
+ end
150
+
151
+ it "should return datetime array from string value" do
152
+ time_array = formats.parse('2000-02-01 12:13:14', :datetime, true)
153
+ time_array.should == [2000,2,1,12,13,14,0]
154
+ end
155
+
156
+ it "should parse date string when type is datetime" do
157
+ time_array = formats.parse('2000-02-01', :datetime, false)
158
+ time_array.should == [2000,2,1,0,0,0,0]
159
+ end
160
+
161
+ it "should ignore time when extracting date and strict is false" do
162
+ time_array = formats.parse('2000-02-01 12:12', :date, false)
163
+ time_array.should == [2000,2,1,0,0,0,0]
164
+ end
165
+
166
+ it "should ignore date when extracting time and strict is false" do
167
+ time_array = formats.parse('2000-02-01 12:12', :time, false)
168
+ time_array.should == [0,0,0,12,12,0,0]
169
+ end
170
+ end
171
+
172
+ describe "removing formats" do
173
+ before do
174
+ formats.compile_format_expressions
175
+ end
176
+
177
+ it "should remove format from format array" do
178
+ formats.remove_formats(:time, 'h.nn_ampm')
179
+ formats.time_formats.should_not include("h o'clock")
180
+ end
181
+
182
+ it "should not match time after its format is removed" do
183
+ validate('2.12am', :time).should be_true
184
+ formats.remove_formats(:time, 'h.nn_ampm')
185
+ validate('2.12am', :time).should be_false
186
+ end
187
+
188
+ it "should raise error if format does not exist" do
189
+ lambda { formats.remove_formats(:time, "ss:hh:nn") }.should raise_error()
190
+ end
191
+
192
+ after do
193
+ formats.time_formats << 'h.nn_ampm'
194
+ # reload class instead
195
+ end
196
+ end
197
+
198
+ describe "adding formats" do
199
+ before do
200
+ formats.compile_format_expressions
201
+ end
202
+
203
+ it "should add format to format array" do
204
+ formats.add_formats(:time, "h o'clock")
205
+ formats.time_formats.should include("h o'clock")
206
+ end
207
+
208
+ it "should match new format after its added" do
209
+ validate("12 o'clock", :time).should be_false
210
+ formats.add_formats(:time, "h o'clock")
211
+ validate("12 o'clock", :time).should be_true
212
+ end
213
+
214
+ it "should add format before specified format and be higher precedence" do
215
+ formats.add_formats(:time, "ss:hh:nn", :before => 'hh:nn:ss')
216
+ validate("59:23:58", :time).should be_true
217
+ time_array = formats.parse('59:23:58', :time)
218
+ time_array.should == [0,0,0,23,58,59,0]
219
+ end
220
+
221
+ it "should raise error if format exists" do
222
+ lambda { formats.add_formats(:time, "hh:nn:ss") }.should raise_error()
223
+ end
224
+
225
+ it "should raise error if format exists" do
226
+ lambda { formats.add_formats(:time, "ss:hh:nn", :before => 'nn:hh:ss') }.should raise_error()
227
+ end
228
+
229
+ after do
230
+ formats.time_formats.delete("h o'clock")
231
+ formats.time_formats.delete("ss:hh:nn")
232
+ # reload class instead
233
+ end
234
+ end
235
+
236
+ describe "removing US formats" do
237
+ it "should validate a date as European format when US formats removed" do
238
+ time_array = formats.parse('01/02/2000', :date)
239
+ time_array.should == [2000, 1, 2,0,0,0,0]
240
+ formats.remove_us_formats
241
+ time_array = formats.parse('01/02/2000', :date)
242
+ time_array.should == [2000, 2, 1,0,0,0,0]
243
+ end
244
+
245
+ after do
246
+ # reload class
247
+ end
248
+ end
249
+
250
+ def validate(time_string, type)
251
+ valid = false
252
+ formats.send("#{type}_expressions").each do |(regexp, processor)|
253
+ valid = true and break if /\A#{regexp}\Z/ =~ time_string
254
+ end
255
+ valid
256
+ end
257
+
258
+ def generate_regexp(format)
259
+ # wrap in line start and end anchors to emulate extract values method
260
+ /\A#{formats.send(:format_expression_generator, format)[0]}\Z/
261
+ end
262
+
263
+ def generate_regexp_str(format)
264
+ formats.send(:format_expression_generator, format)[0].inspect
265
+ end
266
+
267
+ def generate_proc(format)
268
+ formats.send(:format_expression_generator, format)[1]
269
+ end
270
+
271
+ def delete_format(type, format)
272
+ formats.send("#{type}_formats").delete(format)
273
+ end
274
+ end
@@ -0,0 +1,19 @@
1
+ # For use with the ginger gem to test plugin against multiple versions of Rails.
2
+ #
3
+ # To use ginger:
4
+ #
5
+ # sudo gem install freelancing-god-ginger --source=http://gems.github.com
6
+ #
7
+ # Then run
8
+ #
9
+ # ginger spec
10
+ #
11
+ Ginger.configure do |config|
12
+ rails_versions = ['2.0.2', '2.1.2', '2.2.2']
13
+
14
+ rails_versions.each do |v|
15
+ g = Ginger::Scenario.new
16
+ g['rails'] = v
17
+ config.scenarios << g.dup
18
+ end
19
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationController; end
2
+
@@ -0,0 +1,3 @@
1
+ class Person < ActiveRecord::Base
2
+ set_table_name 'people'
3
+ end
@@ -0,0 +1,10 @@
1
+ ActiveRecord::Schema.define(:version => 1) do
2
+
3
+ create_table "people", :force => true do |t|
4
+ t.column "name", :string
5
+ t.column "birth_date_and_time", :datetime
6
+ t.column "birth_date", :date
7
+ t.column "birth_time", :time
8
+ end
9
+
10
+ end
@@ -0,0 +1,19 @@
1
+ # patches adapter in rails 2.0 which mistakenly made time attributes map to datetime column type
2
+ ActiveRecord::ConnectionAdapters::SQLiteAdapter.class_eval do
3
+ def native_database_types #:nodoc:
4
+ {
5
+ :primary_key => default_primary_key_type,
6
+ :string => { :name => "varchar", :limit => 255 },
7
+ :text => { :name => "text" },
8
+ :integer => { :name => "integer" },
9
+ :float => { :name => "float" },
10
+ :decimal => { :name => "decimal" },
11
+ :datetime => { :name => "datetime" },
12
+ :timestamp => { :name => "datetime" },
13
+ :time => { :name => "time" },
14
+ :date => { :name => "date" },
15
+ :binary => { :name => "blob" },
16
+ :boolean => { :name => "boolean" }
17
+ }
18
+ end
19
+ end
@@ -0,0 +1,178 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
2
+
3
+ class NoValidation < Person
4
+ end
5
+
6
+ class WithValidation < Person
7
+ validates_date :birth_date,
8
+ :before => '2000-01-10', :after => '2000-01-01',
9
+ :on_or_before => '2000-01-09', :on_or_after => '2000-01-02'
10
+ validates_time :birth_time,
11
+ :before => '23:00', :after => '09:00',
12
+ :on_or_before => '22:00', :on_or_after => '10:00'
13
+ validates_datetime :birth_date_and_time,
14
+ :before => '2000-01-10 23:00', :after => '2000-01-01 09:00',
15
+ :on_or_before => '2000-01-09 23:00', :on_or_after => '2000-01-02 09:00'
16
+
17
+ end
18
+
19
+ class CustomMessages < Person
20
+ validates_date :birth_date, :invalid_date_message => 'is not really a date',
21
+ :before => '2000-01-10', :before_message => 'is too late',
22
+ :after => '2000-01-01', :after_message => 'is too early',
23
+ :on_or_before=> '2000-01-09', :on_or_before_message => 'is just too late',
24
+ :on_or_after => '2000-01-02', :on_or_after_message => 'is just too early'
25
+ end
26
+
27
+ describe "ValidateTimeliness matcher" do
28
+ attr_accessor :no_validation, :with_validation
29
+
30
+ before do
31
+ @no_validation = NoValidation.new
32
+ @with_validation = WithValidation.new
33
+ end
34
+
35
+ [:date, :time, :datetime].each do |type|
36
+ attribute = type == :datetime ? :date_and_time : type
37
+
38
+ it "should report that #{type} is validated" do
39
+ with_validation.should self.send("validate_#{type}", "birth_#{attribute}".to_sym)
40
+ end
41
+
42
+ it "should report that #{type} is not validated" do
43
+ no_validation.should_not self.send("validate_#{type}", "birth_#{attribute}".to_sym)
44
+ end
45
+ end
46
+
47
+ describe "with before option" do
48
+ test_values = {
49
+ :date => ['2000-01-10', '2000-01-11'],
50
+ :time => ['23:00', '22:59'],
51
+ :datetime => ['2000-01-10 23:00', '2000-01-10 22:59']
52
+ }
53
+
54
+ [:date, :time, :datetime].each do |type|
55
+ attribute = type == :datetime ? :date_and_time : type
56
+
57
+ it "should report that #{type} is validated" do
58
+ with_validation.should self.send("validate_#{type}", "birth_#{attribute}", :before => test_values[type][0])
59
+ end
60
+
61
+ it "should report that #{type} is not validated when option value is incorrect" do
62
+ with_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :before => test_values[type][1])
63
+ end
64
+
65
+ it "should report that #{type} is not validated with option" do
66
+ no_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :before => test_values[type][0])
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "with after option" do
72
+ test_values = {
73
+ :date => ['2000-01-01', '2000-01-02'],
74
+ :time => ['09:00', '09:01'],
75
+ :datetime => ['2000-01-01 09:00', '2000-01-01 09:01']
76
+ }
77
+
78
+ [:date, :time, :datetime].each do |type|
79
+ attribute = type == :datetime ? :date_and_time : type
80
+
81
+ it "should report that #{type} is validated" do
82
+ with_validation.should self.send("validate_#{type}", "birth_#{attribute}", :after => test_values[type][0])
83
+ end
84
+
85
+ it "should report that #{type} is not validated when option value is incorrect" do
86
+ with_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :after => test_values[type][1])
87
+ end
88
+
89
+ it "should report that #{type} is not validated with option" do
90
+ no_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :after => test_values[type][0])
91
+ end
92
+ end
93
+ end
94
+
95
+ describe "with on_or_before option" do
96
+ test_values = {
97
+ :date => ['2000-01-09', '2000-01-08'],
98
+ :time => ['22:00', '21:59'],
99
+ :datetime => ['2000-01-09 23:00', '2000-01-09 22:59']
100
+ }
101
+
102
+ [:date, :time, :datetime].each do |type|
103
+ attribute = type == :datetime ? :date_and_time : type
104
+
105
+ it "should report that #{type} is validated" do
106
+ with_validation.should self.send("validate_#{type}", "birth_#{attribute}", :on_or_before => test_values[type][0])
107
+ end
108
+
109
+ it "should report that #{type} is not validated when option value is incorrect" do
110
+ with_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :on_or_before => test_values[type][1])
111
+ end
112
+
113
+ it "should report that #{type} is not validated with option" do
114
+ no_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :on_or_before => test_values[type][0])
115
+ end
116
+ end
117
+ end
118
+
119
+ describe "with on_or_after option" do
120
+ test_values = {
121
+ :date => ['2000-01-02', '2000-01-03'],
122
+ :time => ['10:00', '10:01'],
123
+ :datetime => ['2000-01-02 09:00', '2000-01-02 09:01']
124
+ }
125
+
126
+ [:date, :time, :datetime].each do |type|
127
+ attribute = type == :datetime ? :date_and_time : type
128
+
129
+ it "should report that #{type} is validated" do
130
+ with_validation.should self.send("validate_#{type}", "birth_#{attribute}", :on_or_after => test_values[type][0])
131
+ end
132
+
133
+ it "should report that #{type} is not validated when option value is incorrect" do
134
+ with_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :on_or_after => test_values[type][1])
135
+ end
136
+
137
+ it "should report that #{type} is not validated with option" do
138
+ no_validation.should_not self.send("validate_#{type}", "birth_#{attribute}", :on_or_after => test_values[type][0])
139
+ end
140
+ end
141
+ end
142
+
143
+ describe "custom messages" do
144
+
145
+ before do
146
+ @person = CustomMessages.new
147
+ end
148
+
149
+ it "should match error message for invalid" do
150
+ @person.should validate_date(:birth_date, :invalid_date_message => 'is not really a date')
151
+ end
152
+
153
+ it "should match error message for before option" do
154
+ @person.should validate_date(:birth_date, :before => '2000-01-10',
155
+ :invalid_date_message => 'is not really a date',
156
+ :before_message => 'is too late')
157
+ end
158
+
159
+ it "should match error message for after option" do
160
+ @person.should validate_date(:birth_date, :after => '2000-01-01',
161
+ :invalid_date_message => 'is not really a date',
162
+ :after_message => 'is too early')
163
+ end
164
+
165
+ it "should match error message for on_or_before option" do
166
+ @person.should validate_date(:birth_date, :on_or_before => '2000-01-09',
167
+ :invalid_date_message => 'is not really a date',
168
+ :on_or_before_message => 'is just too late')
169
+ end
170
+
171
+ it "should match error message for on_or_after option" do
172
+ @person.should validate_date(:birth_date, :on_or_after => '2000-01-02',
173
+ :invalid_date_message => 'is not really a date',
174
+ :on_or_after_message => 'is just too early')
175
+ end
176
+
177
+ end
178
+ end