szilm-validates_timeliness 2.3.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 (34) hide show
  1. data/CHANGELOG +116 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +403 -0
  4. data/Rakefile +52 -0
  5. data/TODO +8 -0
  6. data/lib/validates_timeliness.rb +49 -0
  7. data/lib/validates_timeliness/action_view/instance_tag.rb +52 -0
  8. data/lib/validates_timeliness/active_record/attribute_methods.rb +77 -0
  9. data/lib/validates_timeliness/active_record/multiparameter_attributes.rb +69 -0
  10. data/lib/validates_timeliness/formats.rb +365 -0
  11. data/lib/validates_timeliness/locale/en.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/spec/action_view/instance_tag_spec.rb +194 -0
  19. data/spec/active_record/attribute_methods_spec.rb +157 -0
  20. data/spec/active_record/multiparameter_attributes_spec.rb +118 -0
  21. data/spec/formats_spec.rb +306 -0
  22. data/spec/ginger_scenarios.rb +19 -0
  23. data/spec/parser_spec.rb +61 -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 +245 -0
  29. data/spec/spec_helper.rb +58 -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/validator_spec.rb +713 -0
  34. metadata +102 -0
@@ -0,0 +1,306 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe ValidatesTimeliness::Formats do
4
+
5
+ describe "format proc generator" do
6
+ it "should generate proc which outputs date array with values in correct order" do
7
+ generate_proc('yyyy-mm-dd').call('2000', '1', '2').should == [2000,1,2,0,0,0,0]
8
+ end
9
+
10
+ it "should generate proc which outputs date array from format with different order" do
11
+ generate_proc('dd/mm/yyyy').call('2', '1', '2000').should == [2000,1,2,0,0,0,0]
12
+ end
13
+
14
+ it "should generate proc which outputs time array" do
15
+ generate_proc('hh:nn:ss').call('01', '02', '03').should == [0,0,0,1,2,3,0]
16
+ end
17
+
18
+ it "should generate proc which outputs time array with meridian 'pm' adjusted hour" do
19
+ generate_proc('hh:nn:ss ampm').call('01', '02', '03', 'pm').should == [0,0,0,13,2,3,0]
20
+ end
21
+
22
+ it "should generate proc which outputs time array with meridian 'am' unadjusted hour" do
23
+ generate_proc('hh:nn:ss ampm').call('01', '02', '03', 'am').should == [0,0,0,1,2,3,0]
24
+ end
25
+
26
+ it "should generate proc which outputs time array with microseconds" do
27
+ generate_proc('hh:nn:ss.u').call('01', '02', '03', '99').should == [0,0,0,1,2,3,990000]
28
+ end
29
+
30
+ it "should generate proc which outputs datetime array with zone offset" do
31
+ generate_proc('yyyy-mm-dd hh:nn:ss.u zo').call('2001', '02', '03', '04', '05', '06', '99', '+10:00').should == [2001,2,3,4,5,6,990000,36000]
32
+ end
33
+ end
34
+
35
+ describe "validate regexps" do
36
+
37
+ describe "for time formats" do
38
+ format_tests = {
39
+ 'hh:nn:ss' => {:pass => ['12:12:12', '01:01:01'], :fail => ['1:12:12', '12:1:12', '12:12:1', '12-12-12']},
40
+ 'hh-nn-ss' => {:pass => ['12-12-12', '01-01-01'], :fail => ['1-12-12', '12-1-12', '12-12-1', '12:12:12']},
41
+ 'h:nn' => {:pass => ['12:12', '1:01'], :fail => ['12:2', '12-12']},
42
+ 'h.nn' => {:pass => ['2.12', '12.12'], :fail => ['2.1', '12:12']},
43
+ 'h nn' => {:pass => ['2 12', '12 12'], :fail => ['2 1', '2.12', '12:12']},
44
+ 'h-nn' => {:pass => ['2-12', '12-12'], :fail => ['2-1', '2.12', '12:12']},
45
+ 'h:nn_ampm' => {:pass => ['2:12am', '2:12 pm', '2:12 AM', '2:12PM'], :fail => ['1:2am', '1:12 pm', '2.12am']},
46
+ 'h.nn_ampm' => {:pass => ['2.12am', '2.12 pm'], :fail => ['1:2am', '1:12 pm', '2:12am']},
47
+ 'h nn_ampm' => {:pass => ['2 12am', '2 12 pm'], :fail => ['1 2am', '1 12 pm', '2:12am']},
48
+ 'h-nn_ampm' => {:pass => ['2-12am', '2-12 pm'], :fail => ['1-2am', '1-12 pm', '2:12am']},
49
+ 'h_ampm' => {:pass => ['2am', '2 am', '12 pm'], :fail => ['1.am', '12 pm', '2:12am']},
50
+ }
51
+ format_tests.each do |format, values|
52
+ it "should correctly validate times in format '#{format}'" do
53
+ regexp = generate_regexp(format)
54
+ values[:pass].each {|value| value.should match(regexp)}
55
+ values[:fail].each {|value| value.should_not match(regexp)}
56
+ end
57
+ end
58
+ end
59
+
60
+ describe "for date formats" do
61
+ format_tests = {
62
+ 'yyyy/mm/dd' => {:pass => ['2000/02/01'], :fail => ['2000\02\01', '2000/2/1', '00/02/01']},
63
+ 'yyyy-mm-dd' => {:pass => ['2000-02-01'], :fail => ['2000\02\01', '2000-2-1', '00-02-01']},
64
+ 'yyyy.mm.dd' => {:pass => ['2000.02.01'], :fail => ['2000\02\01', '2000.2.1', '00.02.01']},
65
+ 'm/d/yy' => {:pass => ['2/1/01', '02/01/00', '02/01/2000'], :fail => ['2/1/0', '2.1.01']},
66
+ 'd/m/yy' => {:pass => ['1/2/01', '01/02/00', '01/02/2000'], :fail => ['1/2/0', '1.2.01']},
67
+ 'm\d\yy' => {:pass => ['2\1\01', '2\01\00', '02\01\2000'], :fail => ['2\1\0', '2/1/01']},
68
+ 'd\m\yy' => {:pass => ['1\2\01', '1\02\00', '01\02\2000'], :fail => ['1\2\0', '1/2/01']},
69
+ 'd-m-yy' => {:pass => ['1-2-01', '1-02-00', '01-02-2000'], :fail => ['1-2-0', '1/2/01']},
70
+ 'd.m.yy' => {:pass => ['1.2.01', '1.02.00', '01.02.2000'], :fail => ['1.2.0', '1/2/01']},
71
+ 'd mmm yy' => {:pass => ['1 Feb 00', '1 Feb 2000', '1 February 00', '01 February 2000'],
72
+ :fail => ['1 Fe 00', 'Feb 1 2000', '1 Feb 0']}
73
+ }
74
+ format_tests.each do |format, values|
75
+ it "should correctly validate dates in format '#{format}'" do
76
+ regexp = generate_regexp(format)
77
+ values[:pass].each {|value| value.should match(regexp)}
78
+ values[:fail].each {|value| value.should_not match(regexp)}
79
+ end
80
+ end
81
+ end
82
+
83
+ describe "for datetime formats" do
84
+ format_tests = {
85
+ 'ddd mmm d hh:nn:ss zo yyyy' => {:pass => ['Sat Jul 19 12:00:00 +1000 2008'], :fail => []},
86
+ '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']},
87
+ }
88
+ format_tests.each do |format, values|
89
+ it "should correctly validate datetimes in format '#{format}'" do
90
+ regexp = generate_regexp(format)
91
+ values[:pass].each {|value| value.should match(regexp)}
92
+ values[:fail].each {|value| value.should_not match(regexp)}
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ describe "parse" do
99
+
100
+ it "should return time array from date string" do
101
+ time_array = formats.parse('12:13:14', :time, :strict => true)
102
+ time_array.should == [2000,1,1,12,13,14,0]
103
+ end
104
+
105
+ it "should return date array from time string" do
106
+ time_array = formats.parse('2000-02-01', :date, :strict => true)
107
+ time_array.should == [2000,2,1,0,0,0,0]
108
+ end
109
+
110
+ it "should return datetime array from string value" do
111
+ time_array = formats.parse('2000-02-01 12:13:14', :datetime, :strict => true)
112
+ time_array.should == [2000,2,1,12,13,14,0]
113
+ end
114
+
115
+ it "should parse date string when type is datetime" do
116
+ time_array = formats.parse('2000-02-01', :datetime, :strict => false)
117
+ time_array.should == [2000,2,1,0,0,0,0]
118
+ end
119
+
120
+ it "should ignore time when extracting date and strict is false" do
121
+ time_array = formats.parse('2000-02-01 12:13', :date, :strict => false)
122
+ time_array.should == [2000,2,1,0,0,0,0]
123
+ end
124
+
125
+ it "should ignore time when extracting date from format with trailing year and strict is false" do
126
+ time_array = formats.parse('01-02-2000 12:13', :date, :strict => false)
127
+ time_array.should == [2000,2,1,0,0,0,0]
128
+ end
129
+
130
+ it "should ignore date when extracting time and strict is false" do
131
+ time_array = formats.parse('2000-02-01 12:13', :time, :strict => false)
132
+ time_array.should == [2000,1,1,12,13,0,0]
133
+ end
134
+
135
+ it "should return zone offset when :include_offset option is true" do
136
+ time_array = formats.parse('2000-02-01T12:13:14-10:30', :datetime, :include_offset => true)
137
+ time_array.should == [2000,2,1,12,13,14,0,-37800]
138
+ end
139
+ end
140
+
141
+ describe "parse with format option" do
142
+ it "should return values if string matches specified format" do
143
+ time_array = formats.parse('2000-02-01 12:13:14', :datetime, :format => 'yyyy-mm-dd hh:nn:ss')
144
+ time_array.should == [2000,2,1,12,13,14,0]
145
+ end
146
+
147
+ it "should return nil if string does not match specified format" do
148
+ time_array = formats.parse('2000-02-01 12:13', :datetime, :format => 'yyyy-mm-dd hh:nn:ss')
149
+ time_array.should be_nil
150
+ end
151
+ end
152
+
153
+ describe "parsing date with ambiguous year" do
154
+ it "should return year in current century if year below threshold" do
155
+ time_array = formats.parse('01-02-29', :date)
156
+ time_array.should == [2029,2,1,0,0,0,0]
157
+ end
158
+
159
+ it "should return year in last century if year at or above threshold" do
160
+ time_array = formats.parse('01-02-30', :date)
161
+ time_array.should == [1930,2,1,0,0,0,0]
162
+ end
163
+
164
+ it "should allow custom threshold" do
165
+ default = ValidatesTimeliness::Formats.ambiguous_year_threshold
166
+ ValidatesTimeliness::Formats.ambiguous_year_threshold = 40
167
+ time_array = formats.parse('01-02-39', :date)
168
+ time_array.should == [2039,2,1,0,0,0,0]
169
+ time_array = formats.parse('01-02-40', :date)
170
+ time_array.should == [1940,2,1,0,0,0,0]
171
+ ValidatesTimeliness::Formats.ambiguous_year_threshold = default
172
+ end
173
+ end
174
+
175
+ describe "parse with custom dummy date values" do
176
+ before(:all) do
177
+ @old_dummy_date = formats.dummy_date_for_time_type
178
+ formats.dummy_date_for_time_type = [2009,1,1]
179
+ end
180
+
181
+ it "should return time array with custom dummy date" do
182
+ time_array = formats.parse('12:13:14', :time, :strict => true)
183
+ time_array.should == [2009,1,1,12,13,14,0]
184
+ end
185
+
186
+ after(:all) do
187
+ formats.dummy_date_for_time_type = @old_dummy_date
188
+ end
189
+ end
190
+
191
+ describe "parse ISO8601 datetime" do
192
+ it "should return array without zone offset when no offset in string" do
193
+ time_array = formats.parse('2000-02-01T12:13:14Z', :datetime, :strict => true)
194
+ time_array.should == [2000,2,1,12,13,14,0]
195
+ end
196
+
197
+ it "should return array with zone offset when offset in string" do
198
+ time_array = formats.parse('2000-02-01T12:13:14+10:00', :datetime, :strict => true)
199
+ time_array.should == [2000,2,1,12,13,14,0,36000]
200
+ end
201
+ end
202
+
203
+ describe "removing formats" do
204
+ it "should remove format from format array" do
205
+ formats.remove_formats(:time, 'h.nn_ampm')
206
+ formats.time_formats.should_not include("h o'clock")
207
+ end
208
+
209
+ it "should not match time after its format is removed" do
210
+ validate('2.12am', :time).should be_true
211
+ formats.remove_formats(:time, 'h.nn_ampm')
212
+ validate('2.12am', :time).should be_false
213
+ end
214
+
215
+ it "should raise error if format does not exist" do
216
+ lambda { formats.remove_formats(:time, "ss:hh:nn") }.should raise_error()
217
+ end
218
+
219
+ after do
220
+ formats.time_formats << 'h.nn_ampm'
221
+ formats.compile_format_expressions
222
+ end
223
+ end
224
+
225
+ describe "adding formats" do
226
+ before do
227
+ formats.compile_format_expressions
228
+ end
229
+
230
+ it "should add format to format array" do
231
+ formats.add_formats(:time, "h o'clock")
232
+ formats.time_formats.should include("h o'clock")
233
+ end
234
+
235
+ it "should match new format after its added" do
236
+ validate("12 o'clock", :time).should be_false
237
+ formats.add_formats(:time, "h o'clock")
238
+ validate("12 o'clock", :time).should be_true
239
+ end
240
+
241
+ it "should add format before specified format and be higher precedence" do
242
+ formats.add_formats(:time, "ss:hh:nn", :before => 'hh:nn:ss')
243
+ validate("59:23:58", :time).should be_true
244
+ time_array = formats.parse('59:23:58', :time)
245
+ time_array.should == [2000,1,1,23,58,59,0]
246
+ end
247
+
248
+ it "should raise error if format exists" do
249
+ lambda { formats.add_formats(:time, "hh:nn:ss") }.should raise_error()
250
+ end
251
+
252
+ it "should raise error if format exists" do
253
+ lambda { formats.add_formats(:time, "ss:hh:nn", :before => 'nn:hh:ss') }.should raise_error()
254
+ end
255
+
256
+ after do
257
+ formats.time_formats.delete("h o'clock")
258
+ formats.time_formats.delete("ss:hh:nn")
259
+ # reload class instead
260
+ end
261
+ end
262
+
263
+ describe "removing US formats" do
264
+ it "should validate a date as European format when US formats removed" do
265
+ time_array = formats.parse('01/02/2000', :date)
266
+ time_array.should == [2000, 1, 2,0,0,0,0]
267
+ formats.remove_us_formats
268
+ time_array = formats.parse('01/02/2000', :date)
269
+ time_array.should == [2000, 2, 1,0,0,0,0]
270
+ end
271
+
272
+ after do
273
+ # reload class
274
+ end
275
+ end
276
+
277
+
278
+ def formats
279
+ ValidatesTimeliness::Formats
280
+ end
281
+
282
+ def validate(time_string, type)
283
+ valid = false
284
+ formats.send("#{type}_expressions").each do |format, regexp, processor|
285
+ valid = true and break if /\A#{regexp}\Z/ =~ time_string
286
+ end
287
+ valid
288
+ end
289
+
290
+ def generate_regexp(format)
291
+ # wrap in line start and end anchors to emulate extract values method
292
+ /\A#{formats.send(:generate_format_expression, format)[0]}\Z/
293
+ end
294
+
295
+ def generate_regexp_str(format)
296
+ formats.send(:generate_format_expression, format)[0].inspect
297
+ end
298
+
299
+ def generate_proc(format)
300
+ formats.send(:generate_format_expression, format)[1]
301
+ end
302
+
303
+ def delete_format(type, format)
304
+ formats.send("#{type}_formats").delete(format)
305
+ end
306
+ 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
+ # gem install ginger
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', '2.3.3', '2.3.4', '2.3.5']
13
+
14
+ rails_versions.each do |v|
15
+ g = Ginger::Scenario.new("Rails #{v}")
16
+ g['rails'] = v
17
+ config.scenarios << g.dup
18
+ end
19
+ end
@@ -0,0 +1,61 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe ValidatesTimeliness::Parser do
4
+ attr_accessor :person
5
+
6
+ describe "parse" do
7
+ it "should return time object for valid time string" do
8
+ parse("2000-01-01 12:13:14", :datetime).should be_kind_of(Time)
9
+ end
10
+
11
+ it "should return nil for time string with invalid date part" do
12
+ parse("2000-02-30 12:13:14", :datetime).should be_nil
13
+ end
14
+
15
+ it "should return nil for time string with invalid time part" do
16
+ parse("2000-02-01 25:13:14", :datetime).should be_nil
17
+ end
18
+
19
+ it "should return Time object when passed a Time object" do
20
+ parse(Time.now, :datetime).should be_kind_of(Time)
21
+ end
22
+
23
+ if RAILS_VER >= '2.1'
24
+ it "should convert time string into current timezone" do
25
+ Time.zone = 'Melbourne'
26
+ time = parse("2000-01-01 12:13:14", :datetime)
27
+ Time.zone.utc_offset.should == 10.hours
28
+ end
29
+ end
30
+
31
+ it "should return nil for invalid date string" do
32
+ parse("2000-02-30", :date).should be_nil
33
+ end
34
+
35
+ def parse(*args)
36
+ ValidatesTimeliness::Parser.parse(*args)
37
+ end
38
+ end
39
+
40
+ describe "make_time" do
41
+
42
+ if RAILS_VER >= '2.1'
43
+
44
+ it "should create time using current timezone" do
45
+ Time.zone = 'Melbourne'
46
+ time = ValidatesTimeliness::Parser.make_time([2000,1,1,12,0,0])
47
+ time.zone.should == "EST"
48
+ end
49
+
50
+ else
51
+
52
+ it "should create time using default timezone" do
53
+ time = ValidatesTimeliness::Parser.make_time([2000,1,1,12,0,0])
54
+ time.zone.should == "UTC"
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+
61
+ 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,245 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
2
+ require 'validates_timeliness/matcher'
3
+
4
+ class NoValidation < Person
5
+ end
6
+
7
+ class WithValidation < Person
8
+ validates_date :birth_date,
9
+ :is_at => '2000-01-01',
10
+ :before => '2000-01-10',
11
+ :after => '2000-01-01',
12
+ :on_or_before => '2000-01-09',
13
+ :on_or_after => '2000-01-02',
14
+ :between => ['2000-01-01', '2000-01-03']
15
+
16
+ validates_time :birth_time,
17
+ :is_at => '09:00',
18
+ :before => '23:00',
19
+ :after => '09:00',
20
+ :on_or_before => '22:00',
21
+ :on_or_after => '10:00',
22
+ :between => ['09:00', '17:00']
23
+
24
+ validates_datetime :birth_date_and_time,
25
+ :is_at => '2000-01-01 09:00',
26
+ :before => '2000-01-10 23:00',
27
+ :after => '2000-01-01 09:00',
28
+ :on_or_before => '2000-01-09 23:00',
29
+ :on_or_after => '2000-01-02 09:00',
30
+ :between => ['2000-01-01 09:00', '2000-01-01 17:00']
31
+
32
+ end
33
+
34
+ class CustomMessages < Person
35
+ validates_date :birth_date,
36
+ :invalid_date_message => 'is not really a date',
37
+ :before => '2000-01-10',
38
+ :before_message => 'is too late',
39
+ :after => '2000-01-01',
40
+ :after_message => 'is too early',
41
+ :on_or_before => '2000-01-09',
42
+ :on_or_before_message => 'is just too late',
43
+ :on_or_after => '2000-01-02',
44
+ :on_or_after_message => 'is just too early'
45
+ end
46
+
47
+ describe "ValidateTimeliness matcher" do
48
+ attr_accessor :no_validation, :with_validation
49
+
50
+ @@attribute_for_type = { :date => :birth_date, :time => :birth_time, :datetime => :birth_date_and_time }
51
+
52
+ before do
53
+ @no_validation = NoValidation.new
54
+ @with_validation = WithValidation.new
55
+ end
56
+
57
+ [:date, :time, :datetime].each do |type|
58
+
59
+ it "should report that #{type} is validated" do
60
+ with_validation.should self.send("validate_#{type}", attribute_for_type(type))
61
+ end
62
+
63
+ it "should report that #{type} is not validated" do
64
+ no_validation.should_not self.send("validate_#{type}", attribute_for_type(type))
65
+ end
66
+ end
67
+
68
+ describe "with is_at option" do
69
+ test_values = {
70
+ :date => ['2000-01-01', '2000-01-02'],
71
+ :time => ['09:00', '09:01'],
72
+ :datetime => ['2000-01-01 09:00', '2000-01-01 09:01']
73
+ }
74
+
75
+ [:date, :time, :datetime].each do |type|
76
+
77
+ it "should report that #{type} is validated" do
78
+ with_validation.should self.send("validate_#{type}", attribute_for_type(type), :is_at => test_values[type][0])
79
+ end
80
+
81
+ it "should report that #{type} is not validated when option value is incorrect" do
82
+ with_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :is_at => test_values[type][1])
83
+ end
84
+
85
+ it "should report that #{type} is not validated with option" do
86
+ no_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :is_at => test_values[type][0])
87
+ end
88
+ end
89
+ end
90
+
91
+ describe "with before option" do
92
+ test_values = {
93
+ :date => ['2000-01-10', '2000-01-11'],
94
+ :time => ['23:00', '22:59'],
95
+ :datetime => ['2000-01-10 23:00', '2000-01-10 22:59']
96
+ }
97
+
98
+ [:date, :time, :datetime].each do |type|
99
+
100
+ it "should report that #{type} is validated" do
101
+ with_validation.should self.send("validate_#{type}", attribute_for_type(type), :before => test_values[type][0])
102
+ end
103
+
104
+ it "should report that #{type} is not validated when option value is incorrect" do
105
+ with_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :before => test_values[type][1])
106
+ end
107
+
108
+ it "should report that #{type} is not validated with option" do
109
+ no_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :before => test_values[type][0])
110
+ end
111
+ end
112
+ end
113
+
114
+ describe "with after option" do
115
+ test_values = {
116
+ :date => ['2000-01-01', '2000-01-02'],
117
+ :time => ['09:00', '09:01'],
118
+ :datetime => ['2000-01-01 09:00', '2000-01-01 09:01']
119
+ }
120
+
121
+ [:date, :time, :datetime].each do |type|
122
+
123
+ it "should report that #{type} is validated" do
124
+ with_validation.should self.send("validate_#{type}", attribute_for_type(type), :after => test_values[type][0])
125
+ end
126
+
127
+ it "should report that #{type} is not validated when option value is incorrect" do
128
+ with_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :after => test_values[type][1])
129
+ end
130
+
131
+ it "should report that #{type} is not validated with option" do
132
+ no_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :after => test_values[type][0])
133
+ end
134
+ end
135
+ end
136
+
137
+ describe "with on_or_before option" do
138
+ test_values = {
139
+ :date => ['2000-01-09', '2000-01-08'],
140
+ :time => ['22:00', '21:59'],
141
+ :datetime => ['2000-01-09 23:00', '2000-01-09 22:59']
142
+ }
143
+
144
+ [:date, :time, :datetime].each do |type|
145
+
146
+ it "should report that #{type} is validated" do
147
+ with_validation.should self.send("validate_#{type}", attribute_for_type(type), :on_or_before => test_values[type][0])
148
+ end
149
+
150
+ it "should report that #{type} is not validated when option value is incorrect" do
151
+ with_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :on_or_before => test_values[type][1])
152
+ end
153
+
154
+ it "should report that #{type} is not validated with option" do
155
+ no_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :on_or_before => test_values[type][0])
156
+ end
157
+ end
158
+ end
159
+
160
+ describe "with on_or_after option" do
161
+ test_values = {
162
+ :date => ['2000-01-02', '2000-01-03'],
163
+ :time => ['10:00', '10:01'],
164
+ :datetime => ['2000-01-02 09:00', '2000-01-02 09:01']
165
+ }
166
+
167
+ [:date, :time, :datetime].each do |type|
168
+
169
+ it "should report that #{type} is validated" do
170
+ with_validation.should self.send("validate_#{type}", attribute_for_type(type), :on_or_after => test_values[type][0])
171
+ end
172
+
173
+ it "should report that #{type} is not validated when option value is incorrect" do
174
+ with_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :on_or_after => test_values[type][1])
175
+ end
176
+
177
+ it "should report that #{type} is not validated with option" do
178
+ no_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :on_or_after => test_values[type][0])
179
+ end
180
+ end
181
+ end
182
+
183
+ describe "between option" do
184
+ test_values = {
185
+ :date => [ ['2000-01-01', '2000-01-03'], ['2000-01-01', '2000-01-04'] ],
186
+ :time => [ ['09:00', '17:00'], ['09:00', '17:01'] ],
187
+ :datetime => [ ['2000-01-01 09:00', '2000-01-01 17:00'], ['2000-01-01 09:00', '2000-01-01 17:01'] ]
188
+ }
189
+
190
+ [:date, :time, :datetime].each do |type|
191
+
192
+ it "should report that #{type} is validated" do
193
+ with_validation.should self.send("validate_#{type}", attribute_for_type(type), :between => test_values[type][0])
194
+ end
195
+
196
+ it "should report that #{type} is not validated when option value is incorrect" do
197
+ with_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :between => test_values[type][1])
198
+ end
199
+
200
+ it "should report that #{type} is not validated with option" do
201
+ no_validation.should_not self.send("validate_#{type}", attribute_for_type(type), :between => test_values[type][0])
202
+ end
203
+ end
204
+ end
205
+
206
+ describe "custom messages" do
207
+
208
+ before do
209
+ @person = CustomMessages.new
210
+ end
211
+
212
+ it "should match error message for invalid" do
213
+ @person.should validate_date(:birth_date, :invalid_date_message => 'is not really a date')
214
+ end
215
+
216
+ it "should match error message for before option" do
217
+ @person.should validate_date(:birth_date, :before => '2000-01-10',
218
+ :invalid_date_message => 'is not really a date',
219
+ :before_message => 'is too late')
220
+ end
221
+
222
+ it "should match error message for after option" do
223
+ @person.should validate_date(:birth_date, :after => '2000-01-01',
224
+ :invalid_date_message => 'is not really a date',
225
+ :after_message => 'is too early')
226
+ end
227
+
228
+ it "should match error message for on_or_before option" do
229
+ @person.should validate_date(:birth_date, :on_or_before => '2000-01-09',
230
+ :invalid_date_message => 'is not really a date',
231
+ :on_or_before_message => 'is just too late')
232
+ end
233
+
234
+ it "should match error message for on_or_after option" do
235
+ @person.should validate_date(:birth_date, :on_or_after => '2000-01-02',
236
+ :invalid_date_message => 'is not really a date',
237
+ :on_or_after_message => 'is just too early')
238
+ end
239
+
240
+ end
241
+
242
+ def attribute_for_type(type)
243
+ @@attribute_for_type[type.to_sym]
244
+ end
245
+ end