validates_timeliness 1.0.0

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