markos_validates_timeliness 2.3.2
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.
- data/CHANGELOG +121 -0
- data/LICENSE +20 -0
- data/README.rdoc +402 -0
- data/Rakefile +52 -0
- data/TODO +8 -0
- data/lib/validates_timeliness/action_view/instance_tag.rb +52 -0
- data/lib/validates_timeliness/active_record/attribute_methods.rb +77 -0
- data/lib/validates_timeliness/active_record/multiparameter_attributes.rb +69 -0
- data/lib/validates_timeliness/formats.rb +368 -0
- data/lib/validates_timeliness/locale/en.new.yml +18 -0
- data/lib/validates_timeliness/locale/en.old.yml +18 -0
- data/lib/validates_timeliness/matcher.rb +1 -0
- data/lib/validates_timeliness/parser.rb +44 -0
- data/lib/validates_timeliness/spec/rails/matchers/validate_timeliness.rb +162 -0
- data/lib/validates_timeliness/validation_methods.rb +46 -0
- data/lib/validates_timeliness/validator.rb +230 -0
- data/lib/validates_timeliness/version.rb +3 -0
- data/lib/validates_timeliness.rb +59 -0
- data/spec/action_view/instance_tag_spec.rb +194 -0
- data/spec/active_record/attribute_methods_spec.rb +157 -0
- data/spec/active_record/multiparameter_attributes_spec.rb +118 -0
- data/spec/formats_spec.rb +313 -0
- data/spec/ginger_scenarios.rb +19 -0
- data/spec/parser_spec.rb +65 -0
- data/spec/resources/application.rb +2 -0
- data/spec/resources/person.rb +3 -0
- data/spec/resources/schema.rb +10 -0
- data/spec/resources/sqlite_patch.rb +19 -0
- data/spec/spec/rails/matchers/validate_timeliness_spec.rb +245 -0
- data/spec/spec_helper.rb +58 -0
- data/spec/time_travel/MIT-LICENSE +20 -0
- data/spec/time_travel/time_extensions.rb +33 -0
- data/spec/time_travel/time_travel.rb +12 -0
- data/spec/validator_spec.rb +723 -0
- metadata +104 -0
@@ -0,0 +1,313 @@
|
|
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 nil if time hour is out of range for AM meridian" do
|
106
|
+
time_array = formats.parse('13:14 am', :time, :strict => true)
|
107
|
+
time_array.should == nil
|
108
|
+
time_array = formats.parse('00:14 am', :time, :strict => true)
|
109
|
+
time_array.should == nil
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should return date array from time string" do
|
113
|
+
time_array = formats.parse('2000-02-01', :date, :strict => true)
|
114
|
+
time_array.should == [2000,2,1,0,0,0,0]
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should return datetime array from string value" do
|
118
|
+
time_array = formats.parse('2000-02-01 12:13:14', :datetime, :strict => true)
|
119
|
+
time_array.should == [2000,2,1,12,13,14,0]
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should parse date string when type is datetime" do
|
123
|
+
time_array = formats.parse('2000-02-01', :datetime, :strict => false)
|
124
|
+
time_array.should == [2000,2,1,0,0,0,0]
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should ignore time when extracting date and strict is false" do
|
128
|
+
time_array = formats.parse('2000-02-01 12:13', :date, :strict => false)
|
129
|
+
time_array.should == [2000,2,1,0,0,0,0]
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should ignore time when extracting date from format with trailing year and strict is false" do
|
133
|
+
time_array = formats.parse('01-02-2000 12:13', :date, :strict => false)
|
134
|
+
time_array.should == [2000,2,1,0,0,0,0]
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should ignore date when extracting time and strict is false" do
|
138
|
+
time_array = formats.parse('2000-02-01 12:13', :time, :strict => false)
|
139
|
+
time_array.should == [2000,1,1,12,13,0,0]
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should return zone offset when :include_offset option is true" do
|
143
|
+
time_array = formats.parse('2000-02-01T12:13:14-10:30', :datetime, :include_offset => true)
|
144
|
+
time_array.should == [2000,2,1,12,13,14,0,-37800]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "parse with format option" do
|
149
|
+
it "should return values if string matches specified format" do
|
150
|
+
time_array = formats.parse('2000-02-01 12:13:14', :datetime, :format => 'yyyy-mm-dd hh:nn:ss')
|
151
|
+
time_array.should == [2000,2,1,12,13,14,0]
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should return nil if string does not match specified format" do
|
155
|
+
time_array = formats.parse('2000-02-01 12:13', :datetime, :format => 'yyyy-mm-dd hh:nn:ss')
|
156
|
+
time_array.should be_nil
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe "parsing date with ambiguous year" do
|
161
|
+
it "should return year in current century if year below threshold" do
|
162
|
+
time_array = formats.parse('01-02-29', :date)
|
163
|
+
time_array.should == [2029,2,1,0,0,0,0]
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should return year in last century if year at or above threshold" do
|
167
|
+
time_array = formats.parse('01-02-30', :date)
|
168
|
+
time_array.should == [1930,2,1,0,0,0,0]
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should allow custom threshold" do
|
172
|
+
default = ValidatesTimeliness::Formats.ambiguous_year_threshold
|
173
|
+
ValidatesTimeliness::Formats.ambiguous_year_threshold = 40
|
174
|
+
time_array = formats.parse('01-02-39', :date)
|
175
|
+
time_array.should == [2039,2,1,0,0,0,0]
|
176
|
+
time_array = formats.parse('01-02-40', :date)
|
177
|
+
time_array.should == [1940,2,1,0,0,0,0]
|
178
|
+
ValidatesTimeliness::Formats.ambiguous_year_threshold = default
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe "parse with custom dummy date values" do
|
183
|
+
before(:all) do
|
184
|
+
@old_dummy_date = formats.dummy_date_for_time_type
|
185
|
+
formats.dummy_date_for_time_type = [2009,1,1]
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should return time array with custom dummy date" do
|
189
|
+
time_array = formats.parse('12:13:14', :time, :strict => true)
|
190
|
+
time_array.should == [2009,1,1,12,13,14,0]
|
191
|
+
end
|
192
|
+
|
193
|
+
after(:all) do
|
194
|
+
formats.dummy_date_for_time_type = @old_dummy_date
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
describe "parse ISO8601 datetime" do
|
199
|
+
it "should return array without zone offset when no offset in string" do
|
200
|
+
time_array = formats.parse('2000-02-01T12:13:14Z', :datetime, :strict => true)
|
201
|
+
time_array.should == [2000,2,1,12,13,14,0]
|
202
|
+
end
|
203
|
+
|
204
|
+
it "should return array with zone offset when offset in string" do
|
205
|
+
time_array = formats.parse('2000-02-01T12:13:14+10:00', :datetime, :strict => true)
|
206
|
+
time_array.should == [2000,2,1,12,13,14,0,36000]
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe "removing formats" do
|
211
|
+
it "should remove format from format array" do
|
212
|
+
formats.remove_formats(:time, 'h.nn_ampm')
|
213
|
+
formats.time_formats.should_not include("h o'clock")
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should not match time after its format is removed" do
|
217
|
+
validate('2.12am', :time).should be_true
|
218
|
+
formats.remove_formats(:time, 'h.nn_ampm')
|
219
|
+
validate('2.12am', :time).should be_false
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should raise error if format does not exist" do
|
223
|
+
lambda { formats.remove_formats(:time, "ss:hh:nn") }.should raise_error()
|
224
|
+
end
|
225
|
+
|
226
|
+
after do
|
227
|
+
formats.time_formats << 'h.nn_ampm'
|
228
|
+
formats.compile_format_expressions
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe "adding formats" do
|
233
|
+
before do
|
234
|
+
formats.compile_format_expressions
|
235
|
+
end
|
236
|
+
|
237
|
+
it "should add format to format array" do
|
238
|
+
formats.add_formats(:time, "h o'clock")
|
239
|
+
formats.time_formats.should include("h o'clock")
|
240
|
+
end
|
241
|
+
|
242
|
+
it "should match new format after its added" do
|
243
|
+
validate("12 o'clock", :time).should be_false
|
244
|
+
formats.add_formats(:time, "h o'clock")
|
245
|
+
validate("12 o'clock", :time).should be_true
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should add format before specified format and be higher precedence" do
|
249
|
+
formats.add_formats(:time, "ss:hh:nn", :before => 'hh:nn:ss')
|
250
|
+
validate("59:23:58", :time).should be_true
|
251
|
+
time_array = formats.parse('59:23:58', :time)
|
252
|
+
time_array.should == [2000,1,1,23,58,59,0]
|
253
|
+
end
|
254
|
+
|
255
|
+
it "should raise error if format exists" do
|
256
|
+
lambda { formats.add_formats(:time, "hh:nn:ss") }.should raise_error()
|
257
|
+
end
|
258
|
+
|
259
|
+
it "should raise error if format exists" do
|
260
|
+
lambda { formats.add_formats(:time, "ss:hh:nn", :before => 'nn:hh:ss') }.should raise_error()
|
261
|
+
end
|
262
|
+
|
263
|
+
after do
|
264
|
+
formats.time_formats.delete("h o'clock")
|
265
|
+
formats.time_formats.delete("ss:hh:nn")
|
266
|
+
# reload class instead
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
describe "removing US formats" do
|
271
|
+
it "should validate a date as European format when US formats removed" do
|
272
|
+
time_array = formats.parse('01/02/2000', :date)
|
273
|
+
time_array.should == [2000, 1, 2,0,0,0,0]
|
274
|
+
formats.remove_us_formats
|
275
|
+
time_array = formats.parse('01/02/2000', :date)
|
276
|
+
time_array.should == [2000, 2, 1,0,0,0,0]
|
277
|
+
end
|
278
|
+
|
279
|
+
after do
|
280
|
+
# reload class
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
|
285
|
+
def formats
|
286
|
+
ValidatesTimeliness::Formats
|
287
|
+
end
|
288
|
+
|
289
|
+
def validate(time_string, type)
|
290
|
+
valid = false
|
291
|
+
formats.send("#{type}_expressions").each do |format, regexp, processor|
|
292
|
+
valid = true and break if /\A#{regexp}\Z/ =~ time_string
|
293
|
+
end
|
294
|
+
valid
|
295
|
+
end
|
296
|
+
|
297
|
+
def generate_regexp(format)
|
298
|
+
# wrap in line start and end anchors to emulate extract values method
|
299
|
+
/\A#{formats.send(:generate_format_expression, format)[0]}\Z/
|
300
|
+
end
|
301
|
+
|
302
|
+
def generate_regexp_str(format)
|
303
|
+
formats.send(:generate_format_expression, format)[0].inspect
|
304
|
+
end
|
305
|
+
|
306
|
+
def generate_proc(format)
|
307
|
+
formats.send(:generate_format_expression, format)[1]
|
308
|
+
end
|
309
|
+
|
310
|
+
def delete_format(type, format)
|
311
|
+
formats.send("#{type}_formats").delete(format)
|
312
|
+
end
|
313
|
+
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', '2.3.6', '2.3.9']
|
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
|
data/spec/parser_spec.rb
ADDED
@@ -0,0 +1,65 @@
|
|
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 Time object for ISO 8601 string with time zone" do
|
12
|
+
parse("2000-01-01T12:23:42+09:00", :datetime).should be_kind_of(Time)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return nil for time string with invalid date part" do
|
16
|
+
parse("2000-02-30 12:13:14", :datetime).should be_nil
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return nil for time string with invalid time part" do
|
20
|
+
parse("2000-02-01 25:13:14", :datetime).should be_nil
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return Time object when passed a Time object" do
|
24
|
+
parse(Time.now, :datetime).should be_kind_of(Time)
|
25
|
+
end
|
26
|
+
|
27
|
+
if RAILS_VER >= '2.1'
|
28
|
+
it "should convert time string into current timezone" do
|
29
|
+
Time.zone = 'Melbourne'
|
30
|
+
time = parse("2000-06-01 12:13:14", :datetime)
|
31
|
+
time.utc_offset.should == 10.hours
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return nil for invalid date string" do
|
36
|
+
parse("2000-02-30", :date).should be_nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def parse(*args)
|
40
|
+
ValidatesTimeliness::Parser.parse(*args)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "make_time" do
|
45
|
+
|
46
|
+
if RAILS_VER >= '2.1'
|
47
|
+
|
48
|
+
it "should create time using current timezone" do
|
49
|
+
Time.zone = 'Melbourne'
|
50
|
+
time = ValidatesTimeliness::Parser.make_time([2000,1,1,12,0,0])
|
51
|
+
time.zone.should == "EST"
|
52
|
+
end
|
53
|
+
|
54
|
+
else
|
55
|
+
|
56
|
+
it "should create time using default timezone" do
|
57
|
+
time = ValidatesTimeliness::Parser.make_time([2000,1,1,12,0,0])
|
58
|
+
time.zone.should == "UTC"
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
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
|