strelka 0.0.1pre4 → 0.0.1.pre129
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/History.rdoc +1 -1
- data/IDEAS.rdoc +62 -0
- data/Manifest.txt +38 -7
- data/README.rdoc +124 -5
- data/Rakefile +22 -6
- data/bin/leash +102 -157
- data/contrib/hoetemplate/.autotest.erb +23 -0
- data/contrib/hoetemplate/History.rdoc.erb +4 -0
- data/contrib/hoetemplate/Manifest.txt.erb +8 -0
- data/contrib/hoetemplate/README.rdoc.erb +17 -0
- data/contrib/hoetemplate/Rakefile.erb +24 -0
- data/contrib/hoetemplate/data/file_name/apps/file_name_app +36 -0
- data/contrib/hoetemplate/data/file_name/templates/layout.tmpl.erb +13 -0
- data/contrib/hoetemplate/data/file_name/templates/top.tmpl.erb +8 -0
- data/contrib/hoetemplate/lib/file_name.rb.erb +18 -0
- data/contrib/hoetemplate/spec/file_name_spec.rb.erb +21 -0
- data/data/strelka/apps/hello-world +30 -0
- data/lib/strelka/app/defaultrouter.rb +49 -30
- data/lib/strelka/app/errors.rb +121 -0
- data/lib/strelka/app/exclusiverouter.rb +40 -0
- data/lib/strelka/app/filters.rb +18 -7
- data/lib/strelka/app/negotiation.rb +122 -0
- data/lib/strelka/app/parameters.rb +171 -14
- data/lib/strelka/app/paramvalidator.rb +751 -0
- data/lib/strelka/app/plugins.rb +66 -46
- data/lib/strelka/app/restresources.rb +499 -0
- data/lib/strelka/app/router.rb +73 -0
- data/lib/strelka/app/routing.rb +140 -18
- data/lib/strelka/app/templating.rb +12 -3
- data/lib/strelka/app.rb +174 -24
- data/lib/strelka/constants.rb +0 -20
- data/lib/strelka/exceptions.rb +29 -0
- data/lib/strelka/httprequest/acceptparams.rb +377 -0
- data/lib/strelka/httprequest/negotiation.rb +257 -0
- data/lib/strelka/httprequest.rb +155 -7
- data/lib/strelka/httpresponse/negotiation.rb +579 -0
- data/lib/strelka/httpresponse.rb +140 -0
- data/lib/strelka/logging.rb +4 -1
- data/lib/strelka/mixins.rb +53 -0
- data/lib/strelka.rb +22 -1
- data/spec/data/error.tmpl +1 -0
- data/spec/lib/constants.rb +0 -1
- data/spec/lib/helpers.rb +21 -0
- data/spec/strelka/app/defaultrouter_spec.rb +41 -35
- data/spec/strelka/app/errors_spec.rb +212 -0
- data/spec/strelka/app/exclusiverouter_spec.rb +220 -0
- data/spec/strelka/app/filters_spec.rb +196 -0
- data/spec/strelka/app/negotiation_spec.rb +73 -0
- data/spec/strelka/app/parameters_spec.rb +149 -0
- data/spec/strelka/app/paramvalidator_spec.rb +1059 -0
- data/spec/strelka/app/plugins_spec.rb +26 -19
- data/spec/strelka/app/restresources_spec.rb +393 -0
- data/spec/strelka/app/router_spec.rb +63 -0
- data/spec/strelka/app/routing_spec.rb +183 -9
- data/spec/strelka/app/templating_spec.rb +1 -2
- data/spec/strelka/app_spec.rb +265 -32
- data/spec/strelka/exceptions_spec.rb +53 -0
- data/spec/strelka/httprequest/acceptparams_spec.rb +282 -0
- data/spec/strelka/httprequest/negotiation_spec.rb +246 -0
- data/spec/strelka/httprequest_spec.rb +204 -14
- data/spec/strelka/httpresponse/negotiation_spec.rb +464 -0
- data/spec/strelka/httpresponse_spec.rb +114 -0
- data/spec/strelka/mixins_spec.rb +99 -0
- data.tar.gz.sig +1 -0
- metadata +175 -79
- metadata.gz.sig +2 -0
- data/IDEAS.textile +0 -174
- data/data/strelka/apps/strelka-admin +0 -65
- data/data/strelka/apps/strelka-setup +0 -26
- data/data/strelka/bootstrap-config.rb +0 -34
- data/data/strelka/templates/admin/console.tmpl +0 -21
- data/data/strelka/templates/layout.tmpl +0 -30
- data/lib/strelka/process.rb +0 -19
@@ -0,0 +1,1059 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#encoding: utf-8
|
3
|
+
|
4
|
+
BEGIN {
|
5
|
+
require 'pathname'
|
6
|
+
basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
|
7
|
+
$LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
|
8
|
+
}
|
9
|
+
|
10
|
+
require 'date'
|
11
|
+
require 'rspec'
|
12
|
+
|
13
|
+
require 'spec/lib/helpers'
|
14
|
+
|
15
|
+
require 'strelka'
|
16
|
+
require 'strelka/app/paramvalidator'
|
17
|
+
|
18
|
+
|
19
|
+
#####################################################################
|
20
|
+
### C O N T E X T S
|
21
|
+
#####################################################################
|
22
|
+
describe Strelka::App::ParamValidator do
|
23
|
+
|
24
|
+
TEST_PROFILE = {
|
25
|
+
:required => [ :required ],
|
26
|
+
:optional => %w{
|
27
|
+
optional number int_constraint float_constraint bool_constraint email_constraint
|
28
|
+
host_constraint regexp_w_captures regexp_w_one_capture regexp_w_named_captures
|
29
|
+
alpha_constraint alphanumeric_constraint printable_constraint proc_constraint
|
30
|
+
uri_constraint word_constraint date_constraint
|
31
|
+
},
|
32
|
+
:constraints => {
|
33
|
+
:number => /^\d+$/,
|
34
|
+
:regexp_w_captures => /(\w+)(\S+)?/,
|
35
|
+
:regexp_w_one_capture => /(\w+)/,
|
36
|
+
:regexp_w_named_captures => /(?<category>[[:upper:]]{3})-(?<sku>\d{12})/,
|
37
|
+
:int_constraint => :integer,
|
38
|
+
:float_constraint => :float,
|
39
|
+
:bool_constraint => :boolean,
|
40
|
+
:email_constraint => :email,
|
41
|
+
:uri_constraint => :uri,
|
42
|
+
:host_constraint => :hostname,
|
43
|
+
:alpha_constraint => :alpha,
|
44
|
+
:alphanumeric_constraint => :alphanumeric,
|
45
|
+
:printable_constraint => :printable,
|
46
|
+
:word_constraint => :word,
|
47
|
+
:proc_constraint => Date.method( :parse ),
|
48
|
+
:date_constraint => :date,
|
49
|
+
},
|
50
|
+
}
|
51
|
+
|
52
|
+
|
53
|
+
before( :all ) do
|
54
|
+
setup_logging( :fatal )
|
55
|
+
end
|
56
|
+
|
57
|
+
before(:each) do
|
58
|
+
@validator = Strelka::App::ParamValidator.new( TEST_PROFILE )
|
59
|
+
end
|
60
|
+
|
61
|
+
after( :all ) do
|
62
|
+
reset_logging()
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
it "starts out empty" do
|
67
|
+
@validator.should be_empty()
|
68
|
+
@validator.should_not have_args()
|
69
|
+
end
|
70
|
+
|
71
|
+
it "is no longer empty if at least one set of parameters has been validated" do
|
72
|
+
@validator.validate( {'required' => "1"} )
|
73
|
+
|
74
|
+
@validator.should_not be_empty()
|
75
|
+
@validator.should have_args()
|
76
|
+
end
|
77
|
+
|
78
|
+
it "raises an exception on an unknown constraint type" do
|
79
|
+
pending "figure out why this isn't working" do
|
80
|
+
profile = {
|
81
|
+
required: [:required],
|
82
|
+
constraints: {
|
83
|
+
required: $stderr,
|
84
|
+
}
|
85
|
+
}
|
86
|
+
val = Strelka::App::ParamValidator.new( profile )
|
87
|
+
|
88
|
+
expect {
|
89
|
+
val.validate( required: '1' )
|
90
|
+
}.to raise_error( /unknown constraint type IO/ )
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Test index operator interface
|
95
|
+
it "provides read and write access to valid args via the index operator" do
|
96
|
+
rval = nil
|
97
|
+
|
98
|
+
@validator.validate( {'required' => "1"} )
|
99
|
+
@validator[:required].should == "1"
|
100
|
+
|
101
|
+
@validator[:required] = "bar"
|
102
|
+
@validator["required"].should == "bar"
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
it "untaints valid args if told to do so" do
|
107
|
+
rval = nil
|
108
|
+
tainted_one = "1"
|
109
|
+
tainted_one.taint
|
110
|
+
|
111
|
+
@validator.validate( {'required' => 1, 'number' => tainted_one},
|
112
|
+
:untaint_all_constraints => true )
|
113
|
+
|
114
|
+
Strelka.log.debug "Validator: %p" % [@validator]
|
115
|
+
|
116
|
+
@validator[:number].should == "1"
|
117
|
+
@validator[:number].tainted?.should be_false()
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
it "untaints field names" do
|
122
|
+
rval = nil
|
123
|
+
tainted_one = "1"
|
124
|
+
tainted_one.taint
|
125
|
+
|
126
|
+
@validator.validate( {'required' => 1, 'number' => tainted_one},
|
127
|
+
:untaint_all_constraints => true )
|
128
|
+
|
129
|
+
Strelka.log.debug "Validator: %p" % [@validator]
|
130
|
+
|
131
|
+
@validator[:number].should == "1"
|
132
|
+
@validator[:number].tainted?.should be_false()
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
it "returns the capture from a regexp constraint if it has only one" do
|
137
|
+
rval = nil
|
138
|
+
params = { 'required' => 1, 'regexp_w_one_capture' => " ygdrassil " }
|
139
|
+
|
140
|
+
@validator.validate( params, :untaint_all_constraints => true )
|
141
|
+
|
142
|
+
Strelka.log.debug "Validator: %p" % [@validator]
|
143
|
+
|
144
|
+
@validator[:regexp_w_one_capture].should == 'ygdrassil'
|
145
|
+
end
|
146
|
+
|
147
|
+
it "returns the captures from a regexp constraint as an array if it has more than one" do
|
148
|
+
rval = nil
|
149
|
+
params = { 'required' => 1, 'regexp_w_captures' => " the1tree(!) " }
|
150
|
+
|
151
|
+
@validator.validate( params, :untaint_all_constraints => true )
|
152
|
+
|
153
|
+
Strelka.log.debug "Validator: %p" % [@validator]
|
154
|
+
|
155
|
+
@validator[:regexp_w_captures].should == ['the1tree', '(!)']
|
156
|
+
end
|
157
|
+
|
158
|
+
it "returns the captures from a regexp constraint with named captures as a Hash" do
|
159
|
+
rval = nil
|
160
|
+
params = { 'required' => 1, 'regexp_w_named_captures' => " JVV-886451300133 ".taint }
|
161
|
+
|
162
|
+
@validator.validate( params, :untaint_all_constraints => true )
|
163
|
+
|
164
|
+
Strelka.log.debug "Validator: %p" % [@validator]
|
165
|
+
|
166
|
+
@validator[:regexp_w_named_captures].should == {:category => 'JVV', :sku => '886451300133'}
|
167
|
+
@validator[:regexp_w_named_captures][:category].should_not be_tainted()
|
168
|
+
@validator[:regexp_w_named_captures][:sku].should_not be_tainted()
|
169
|
+
end
|
170
|
+
|
171
|
+
it "returns the captures from a regexp constraint as an array " +
|
172
|
+
"even if an optional capture doesn't match anything" do
|
173
|
+
rval = nil
|
174
|
+
params = { 'required' => 1, 'regexp_w_captures' => " the1tree " }
|
175
|
+
|
176
|
+
@validator.validate( params, :untaint_all_constraints => true )
|
177
|
+
|
178
|
+
Strelka.log.debug "Validator: %p" % [@validator]
|
179
|
+
|
180
|
+
@validator[:regexp_w_captures].should == ['the1tree', nil]
|
181
|
+
end
|
182
|
+
|
183
|
+
it "knows the names of fields that were required but missing from the parameters" do
|
184
|
+
@validator.validate( {} )
|
185
|
+
|
186
|
+
@validator.should have_errors()
|
187
|
+
@validator.should_not be_okay()
|
188
|
+
|
189
|
+
@validator.missing.should have(1).members
|
190
|
+
@validator.missing.should == ['required']
|
191
|
+
end
|
192
|
+
|
193
|
+
it "knows the names of fields that did not meet their constraints" do
|
194
|
+
params = {'number' => 'rhinoceros'}
|
195
|
+
@validator.validate( params )
|
196
|
+
|
197
|
+
@validator.should have_errors()
|
198
|
+
@validator.should_not be_okay()
|
199
|
+
|
200
|
+
@validator.invalid.should have(1).keys
|
201
|
+
@validator.invalid.keys.should == ['number']
|
202
|
+
end
|
203
|
+
|
204
|
+
it "can return a combined list of all problem parameters, which includes " +
|
205
|
+
" both missing and invalid fields" do
|
206
|
+
params = {'number' => 'rhinoceros'}
|
207
|
+
@validator.validate( params )
|
208
|
+
|
209
|
+
@validator.should have_errors()
|
210
|
+
@validator.should_not be_okay()
|
211
|
+
|
212
|
+
@validator.error_fields.should have(2).members
|
213
|
+
@validator.error_fields.should include('number')
|
214
|
+
@validator.error_fields.should include('required')
|
215
|
+
end
|
216
|
+
|
217
|
+
it "can return human descriptions of validation errors" do
|
218
|
+
params = {'number' => 'rhinoceros', 'unknown' => "1"}
|
219
|
+
@validator.validate( params )
|
220
|
+
|
221
|
+
@validator.error_messages.should have(2).members
|
222
|
+
@validator.error_messages.should include("Missing value for 'Required'")
|
223
|
+
@validator.error_messages.should include("Invalid value for 'Number'")
|
224
|
+
end
|
225
|
+
|
226
|
+
it "can include unknown fields in its human descriptions of validation errors" do
|
227
|
+
params = {'number' => 'rhinoceros', 'unknown' => "1"}
|
228
|
+
@validator.validate( params )
|
229
|
+
|
230
|
+
@validator.error_messages(true).should have(3).members
|
231
|
+
@validator.error_messages(true).should include("Missing value for 'Required'")
|
232
|
+
@validator.error_messages(true).should include("Invalid value for 'Number'")
|
233
|
+
@validator.error_messages(true).should include("Unknown parameter 'Unknown'")
|
234
|
+
end
|
235
|
+
|
236
|
+
it "can use provided descriptions of parameters when constructing human " +
|
237
|
+
"validation error messages" do
|
238
|
+
descs = {
|
239
|
+
:number => "Numeral",
|
240
|
+
:required => "Test Name",
|
241
|
+
}
|
242
|
+
params = {'number' => 'rhinoceros', 'unknown' => "1"}
|
243
|
+
@validator.validate( params, :descriptions => descs )
|
244
|
+
|
245
|
+
@validator.error_messages.should have(2).members
|
246
|
+
@validator.error_messages.should include("Missing value for 'Test Name'")
|
247
|
+
@validator.error_messages.should include("Invalid value for 'Numeral'")
|
248
|
+
end
|
249
|
+
|
250
|
+
it "can get and set the profile's descriptions directly" do
|
251
|
+
params = {'number' => 'rhinoceros', 'unknown' => "1"}
|
252
|
+
|
253
|
+
@validator.descriptions = {
|
254
|
+
number: 'Numeral',
|
255
|
+
required: 'Test Name'
|
256
|
+
}
|
257
|
+
@validator.validate( params )
|
258
|
+
|
259
|
+
@validator.descriptions.should have( 2 ).members
|
260
|
+
@validator.error_messages.should have( 2 ).members
|
261
|
+
@validator.error_messages.should include("Missing value for 'Test Name'")
|
262
|
+
@validator.error_messages.should include("Invalid value for 'Numeral'")
|
263
|
+
end
|
264
|
+
|
265
|
+
it "capitalizes the names of simple fields for descriptions" do
|
266
|
+
@validator.get_description( "required" ).should == 'Required'
|
267
|
+
end
|
268
|
+
|
269
|
+
it "splits apart underbarred field names into capitalized words for descriptions" do
|
270
|
+
@validator.get_description( "rodent_size" ).should == 'Rodent Size'
|
271
|
+
end
|
272
|
+
|
273
|
+
it "uses the key for descriptions of hash fields" do
|
274
|
+
@validator.get_description( "rodent[size]" ).should == 'Size'
|
275
|
+
end
|
276
|
+
|
277
|
+
it "uses separate capitalized words for descriptions of hash fields with underbarred keys " do
|
278
|
+
@validator.get_description( "castle[baron_id]" ).should == 'Baron Id'
|
279
|
+
end
|
280
|
+
|
281
|
+
it "coalesces simple hash fields into a hash of validated values" do
|
282
|
+
@validator.validate( {'rodent[size]' => 'unusual'}, :optional => ['rodent[size]'] )
|
283
|
+
|
284
|
+
@validator.valid.should == {'rodent' => {'size' => 'unusual'}}
|
285
|
+
end
|
286
|
+
|
287
|
+
it "coalesces complex hash fields into a nested hash of validated values" do
|
288
|
+
profile = {
|
289
|
+
:optional => [
|
290
|
+
'recipe[ingredient][name]',
|
291
|
+
'recipe[ingredient][cost]',
|
292
|
+
'recipe[yield]'
|
293
|
+
]
|
294
|
+
}
|
295
|
+
args = {
|
296
|
+
'recipe[ingredient][name]' => 'nutmeg',
|
297
|
+
'recipe[ingredient][cost]' => '$0.18',
|
298
|
+
'recipe[yield]' => '2 loaves',
|
299
|
+
}
|
300
|
+
|
301
|
+
@validator.validate( args, profile )
|
302
|
+
@validator.valid.should == {
|
303
|
+
'recipe' => {
|
304
|
+
'ingredient' => { 'name' => 'nutmeg', 'cost' => '$0.18' },
|
305
|
+
'yield' => '2 loaves'
|
306
|
+
}
|
307
|
+
}
|
308
|
+
end
|
309
|
+
|
310
|
+
it "untaints both keys and values in complex hash fields if untainting is turned on" do
|
311
|
+
profile = {
|
312
|
+
:required => [
|
313
|
+
'recipe[ingredient][rarity]',
|
314
|
+
],
|
315
|
+
:optional => [
|
316
|
+
'recipe[ingredient][name]',
|
317
|
+
'recipe[ingredient][cost]',
|
318
|
+
'recipe[yield]'
|
319
|
+
],
|
320
|
+
:constraints => {
|
321
|
+
'recipe[ingredient][rarity]' => /^([\w\-]+)$/,
|
322
|
+
},
|
323
|
+
:untaint_all_constraints => true,
|
324
|
+
}
|
325
|
+
args = {
|
326
|
+
'recipe[ingredient][rarity]'.taint => 'super-rare'.taint,
|
327
|
+
'recipe[ingredient][name]'.taint => 'nutmeg'.taint,
|
328
|
+
'recipe[ingredient][cost]'.taint => '$0.18'.taint,
|
329
|
+
'recipe[yield]'.taint => '2 loaves'.taint,
|
330
|
+
}
|
331
|
+
|
332
|
+
@validator.validate( args, profile )
|
333
|
+
|
334
|
+
@validator.valid.should == {
|
335
|
+
'recipe' => {
|
336
|
+
'ingredient' => { 'name' => 'nutmeg', 'cost' => '$0.18', 'rarity' => 'super-rare' },
|
337
|
+
'yield' => '2 loaves'
|
338
|
+
}
|
339
|
+
}
|
340
|
+
|
341
|
+
@validator.valid.keys.all? {|key| key.should_not be_tainted() }
|
342
|
+
@validator.valid.values.all? {|key| key.should_not be_tainted() }
|
343
|
+
@validator.valid['recipe'].keys.all? {|key| key.should_not be_tainted() }
|
344
|
+
@validator.valid['recipe']['ingredient'].keys.all? {|key| key.should_not be_tainted() }
|
345
|
+
@validator.valid['recipe']['yield'].should_not be_tainted()
|
346
|
+
@validator.valid['recipe']['ingredient']['rarity'].should_not be_tainted()
|
347
|
+
@validator.valid['recipe']['ingredient']['name'].should_not be_tainted()
|
348
|
+
@validator.valid['recipe']['ingredient']['cost'].should_not be_tainted()
|
349
|
+
end
|
350
|
+
|
351
|
+
it "accepts the value 'true' for fields with boolean constraints" do
|
352
|
+
params = {'required' => '1', 'bool_constraint' => 'true'}
|
353
|
+
|
354
|
+
@validator.validate( params )
|
355
|
+
|
356
|
+
@validator.should be_okay()
|
357
|
+
@validator.should_not have_errors()
|
358
|
+
|
359
|
+
@validator[:bool_constraint].should be_true()
|
360
|
+
end
|
361
|
+
|
362
|
+
it "accepts the value 't' for fields with boolean constraints" do
|
363
|
+
params = {'required' => '1', 'bool_constraint' => 't'}
|
364
|
+
|
365
|
+
@validator.validate( params )
|
366
|
+
|
367
|
+
@validator.should be_okay()
|
368
|
+
@validator.should_not have_errors()
|
369
|
+
|
370
|
+
@validator[:bool_constraint].should be_true()
|
371
|
+
end
|
372
|
+
|
373
|
+
it "accepts the value 'yes' for fields with boolean constraints" do
|
374
|
+
params = {'required' => '1', 'bool_constraint' => 'yes'}
|
375
|
+
|
376
|
+
@validator.validate( params )
|
377
|
+
|
378
|
+
@validator.should be_okay()
|
379
|
+
@validator.should_not have_errors()
|
380
|
+
|
381
|
+
@validator[:bool_constraint].should be_true()
|
382
|
+
end
|
383
|
+
|
384
|
+
it "accepts the value 'y' for fields with boolean constraints" do
|
385
|
+
params = {'required' => '1', 'bool_constraint' => 'y'}
|
386
|
+
|
387
|
+
@validator.validate( params )
|
388
|
+
|
389
|
+
@validator.should be_okay()
|
390
|
+
@validator.should_not have_errors()
|
391
|
+
|
392
|
+
@validator[:bool_constraint].should be_true()
|
393
|
+
end
|
394
|
+
|
395
|
+
it "accepts the value '1' for fields with boolean constraints" do
|
396
|
+
params = {'required' => '1', 'bool_constraint' => '1'}
|
397
|
+
|
398
|
+
@validator.validate( params )
|
399
|
+
|
400
|
+
@validator.should be_okay()
|
401
|
+
@validator.should_not have_errors()
|
402
|
+
|
403
|
+
@validator[:bool_constraint].should be_true()
|
404
|
+
end
|
405
|
+
|
406
|
+
it "accepts the value 'false' for fields with boolean constraints" do
|
407
|
+
params = {'required' => '1', 'bool_constraint' => 'false'}
|
408
|
+
|
409
|
+
@validator.validate( params )
|
410
|
+
|
411
|
+
@validator.should be_okay()
|
412
|
+
@validator.should_not have_errors()
|
413
|
+
|
414
|
+
@validator[:bool_constraint].should be_false()
|
415
|
+
end
|
416
|
+
|
417
|
+
it "accepts the value 'f' for fields with boolean constraints" do
|
418
|
+
params = {'required' => '1', 'bool_constraint' => 'f'}
|
419
|
+
|
420
|
+
@validator.validate( params )
|
421
|
+
|
422
|
+
@validator.should be_okay()
|
423
|
+
@validator.should_not have_errors()
|
424
|
+
|
425
|
+
@validator[:bool_constraint].should be_false()
|
426
|
+
end
|
427
|
+
|
428
|
+
it "accepts the value 'no' for fields with boolean constraints" do
|
429
|
+
params = {'required' => '1', 'bool_constraint' => 'no'}
|
430
|
+
|
431
|
+
@validator.validate( params )
|
432
|
+
|
433
|
+
@validator.should be_okay()
|
434
|
+
@validator.should_not have_errors()
|
435
|
+
|
436
|
+
@validator[:bool_constraint].should be_false()
|
437
|
+
end
|
438
|
+
|
439
|
+
it "accepts the value 'n' for fields with boolean constraints" do
|
440
|
+
params = {'required' => '1', 'bool_constraint' => 'n'}
|
441
|
+
|
442
|
+
@validator.validate( params )
|
443
|
+
|
444
|
+
@validator.should be_okay()
|
445
|
+
@validator.should_not have_errors()
|
446
|
+
|
447
|
+
@validator[:bool_constraint].should be_false()
|
448
|
+
end
|
449
|
+
|
450
|
+
it "accepts the value '0' for fields with boolean constraints" do
|
451
|
+
params = {'required' => '1', 'bool_constraint' => '0'}
|
452
|
+
|
453
|
+
@validator.validate( params )
|
454
|
+
|
455
|
+
@validator.should be_okay()
|
456
|
+
@validator.should_not have_errors()
|
457
|
+
|
458
|
+
@validator[:bool_constraint].should be_false()
|
459
|
+
end
|
460
|
+
|
461
|
+
it "rejects non-boolean parameters for fields with boolean constraints" do
|
462
|
+
params = {'required' => '1', 'bool_constraint' => 'peanut'}
|
463
|
+
|
464
|
+
@validator.validate( params )
|
465
|
+
|
466
|
+
@validator.should_not be_okay()
|
467
|
+
@validator.should have_errors()
|
468
|
+
|
469
|
+
@validator[:bool_constraint].should be_nil()
|
470
|
+
end
|
471
|
+
|
472
|
+
it "accepts simple integers for fields with integer constraints" do
|
473
|
+
params = {'required' => '1', 'int_constraint' => '11'}
|
474
|
+
|
475
|
+
@validator.validate( params )
|
476
|
+
|
477
|
+
@validator.should be_okay()
|
478
|
+
@validator.should_not have_errors()
|
479
|
+
|
480
|
+
@validator[:int_constraint].should == 11
|
481
|
+
end
|
482
|
+
|
483
|
+
it "accepts '0' for fields with integer constraints" do
|
484
|
+
params = {'required' => '1', 'int_constraint' => '0'}
|
485
|
+
|
486
|
+
@validator.validate( params )
|
487
|
+
|
488
|
+
@validator.should be_okay()
|
489
|
+
@validator.should_not have_errors()
|
490
|
+
|
491
|
+
@validator[:int_constraint].should == 0
|
492
|
+
end
|
493
|
+
|
494
|
+
it "accepts negative integers for fields with integer constraints" do
|
495
|
+
params = {'required' => '1', 'int_constraint' => '-407'}
|
496
|
+
|
497
|
+
@validator.validate( params )
|
498
|
+
|
499
|
+
@validator.should be_okay()
|
500
|
+
@validator.should_not have_errors()
|
501
|
+
|
502
|
+
@validator[:int_constraint].should == -407
|
503
|
+
end
|
504
|
+
|
505
|
+
it "rejects non-integers for fields with integer constraints" do
|
506
|
+
params = {'required' => '1', 'int_constraint' => '11.1'}
|
507
|
+
|
508
|
+
@validator.validate( params )
|
509
|
+
|
510
|
+
@validator.should_not be_okay()
|
511
|
+
@validator.should have_errors()
|
512
|
+
|
513
|
+
@validator[:int_constraint].should be_nil()
|
514
|
+
end
|
515
|
+
|
516
|
+
it "rejects integer values with other cruft in them for fields with integer constraints" do
|
517
|
+
params = {'required' => '1', 'int_constraint' => '88licks'}
|
518
|
+
|
519
|
+
@validator.validate( params )
|
520
|
+
|
521
|
+
@validator.should_not be_okay()
|
522
|
+
@validator.should have_errors()
|
523
|
+
|
524
|
+
@validator[:int_constraint].should be_nil()
|
525
|
+
end
|
526
|
+
|
527
|
+
it "accepts simple floats for fields with float constraints" do
|
528
|
+
params = {'required' => '1', 'float_constraint' => '3.14'}
|
529
|
+
|
530
|
+
@validator.validate( params )
|
531
|
+
|
532
|
+
@validator.should be_okay()
|
533
|
+
@validator.should_not have_errors()
|
534
|
+
|
535
|
+
@validator[:float_constraint].should == 3.14
|
536
|
+
end
|
537
|
+
|
538
|
+
it "accepts negative floats for fields with float constraints" do
|
539
|
+
params = {'required' => '1', 'float_constraint' => '-3.14'}
|
540
|
+
|
541
|
+
@validator.validate( params )
|
542
|
+
|
543
|
+
@validator.should be_okay()
|
544
|
+
@validator.should_not have_errors()
|
545
|
+
|
546
|
+
@validator[:float_constraint].should == -3.14
|
547
|
+
end
|
548
|
+
|
549
|
+
it "accepts positive floats for fields with float constraints" do
|
550
|
+
params = {'required' => '1', 'float_constraint' => '+3.14'}
|
551
|
+
|
552
|
+
@validator.validate( params )
|
553
|
+
|
554
|
+
@validator.should be_okay()
|
555
|
+
@validator.should_not have_errors()
|
556
|
+
|
557
|
+
@validator[:float_constraint].should == 3.14
|
558
|
+
end
|
559
|
+
|
560
|
+
it "accepts floats that begin with '.' for fields with float constraints" do
|
561
|
+
params = {'required' => '1', 'float_constraint' => '.1418'}
|
562
|
+
|
563
|
+
@validator.validate( params )
|
564
|
+
|
565
|
+
@validator.should be_okay()
|
566
|
+
@validator.should_not have_errors()
|
567
|
+
|
568
|
+
@validator[:float_constraint].should == 0.1418
|
569
|
+
end
|
570
|
+
|
571
|
+
it "accepts negative floats that begin with '.' for fields with float constraints" do
|
572
|
+
params = {'required' => '1', 'float_constraint' => '-.171'}
|
573
|
+
|
574
|
+
@validator.validate( params )
|
575
|
+
|
576
|
+
@validator.should be_okay()
|
577
|
+
@validator.should_not have_errors()
|
578
|
+
|
579
|
+
@validator[:float_constraint].should == -0.171
|
580
|
+
end
|
581
|
+
|
582
|
+
it "accepts positive floats that begin with '.' for fields with float constraints" do
|
583
|
+
params = {'required' => '1', 'float_constraint' => '+.86668001'}
|
584
|
+
|
585
|
+
@validator.validate( params )
|
586
|
+
|
587
|
+
@validator.should be_okay()
|
588
|
+
@validator.should_not have_errors()
|
589
|
+
|
590
|
+
@validator[:float_constraint].should == 0.86668001
|
591
|
+
end
|
592
|
+
|
593
|
+
it "accepts floats in exponential notation for fields with float constraints" do
|
594
|
+
params = {'required' => '1', 'float_constraint' => '1756e-5'}
|
595
|
+
|
596
|
+
@validator.validate( params )
|
597
|
+
|
598
|
+
@validator.should be_okay()
|
599
|
+
@validator.should_not have_errors()
|
600
|
+
|
601
|
+
@validator[:float_constraint].should == 0.01756
|
602
|
+
end
|
603
|
+
|
604
|
+
it "accepts negative floats in exponential notation for fields with float constraints" do
|
605
|
+
params = {'required' => '1', 'float_constraint' => '-28e8'}
|
606
|
+
|
607
|
+
@validator.validate( params )
|
608
|
+
|
609
|
+
@validator.should be_okay()
|
610
|
+
@validator.should_not have_errors()
|
611
|
+
|
612
|
+
@validator[:float_constraint].should == -28e8
|
613
|
+
end
|
614
|
+
|
615
|
+
it "accepts floats that start with '.' in exponential notation for fields with float " +
|
616
|
+
"constraints" do
|
617
|
+
params = {'required' => '1', 'float_constraint' => '.5552e-10'}
|
618
|
+
|
619
|
+
@validator.validate( params )
|
620
|
+
|
621
|
+
@validator.should be_okay()
|
622
|
+
@validator.should_not have_errors()
|
623
|
+
|
624
|
+
@validator[:float_constraint].should == 0.5552e-10
|
625
|
+
end
|
626
|
+
|
627
|
+
it "accepts negative floats that start with '.' in exponential notation for fields with " +
|
628
|
+
"float constraints" do
|
629
|
+
params = {'required' => '1', 'float_constraint' => '-.288088e18'}
|
630
|
+
|
631
|
+
@validator.validate( params )
|
632
|
+
|
633
|
+
@validator.should be_okay()
|
634
|
+
@validator.should_not have_errors()
|
635
|
+
|
636
|
+
@validator[:float_constraint].should == -0.288088e18
|
637
|
+
end
|
638
|
+
|
639
|
+
it "accepts integers for fields with float constraints" do
|
640
|
+
params = {'required' => '1', 'float_constraint' => '288'}
|
641
|
+
|
642
|
+
@validator.validate( params )
|
643
|
+
|
644
|
+
@validator.should be_okay()
|
645
|
+
@validator.should_not have_errors()
|
646
|
+
|
647
|
+
@validator[:float_constraint].should == 288.0
|
648
|
+
end
|
649
|
+
|
650
|
+
it "accepts negative integers for fields with float constraints" do
|
651
|
+
params = {'required' => '1', 'float_constraint' => '-1606'}
|
652
|
+
|
653
|
+
@validator.validate( params )
|
654
|
+
|
655
|
+
@validator.should be_okay()
|
656
|
+
@validator.should_not have_errors()
|
657
|
+
|
658
|
+
@validator[:float_constraint].should == -1606.0
|
659
|
+
end
|
660
|
+
|
661
|
+
it "accepts positive integers for fields with float constraints" do
|
662
|
+
params = {'required' => '1', 'float_constraint' => '+2600'}
|
663
|
+
|
664
|
+
@validator.validate( params )
|
665
|
+
|
666
|
+
@validator.should be_okay()
|
667
|
+
@validator.should_not have_errors()
|
668
|
+
|
669
|
+
@validator[:float_constraint].should == 2600.0
|
670
|
+
end
|
671
|
+
|
672
|
+
it "accepts dates for fields with date constraints" do
|
673
|
+
params = {'required' => '1', 'date_constraint' => '2008-11-18'}
|
674
|
+
|
675
|
+
@validator.validate( params )
|
676
|
+
|
677
|
+
@validator.should be_okay()
|
678
|
+
@validator.should_not have_errors()
|
679
|
+
|
680
|
+
@validator[:date_constraint].should == Date.parse( '2008-11-18' )
|
681
|
+
end
|
682
|
+
|
683
|
+
|
684
|
+
VALID_URIS = %w{
|
685
|
+
http://127.0.0.1
|
686
|
+
http://127.0.0.1/
|
687
|
+
http://[127.0.0.1]/
|
688
|
+
http://ruby-lang.org/
|
689
|
+
http://www.rocketboom.com/vlog/rb_08_feb_01
|
690
|
+
http://del.icio.us/search/?fr=del_icio_us&p=ruby+arrow&type=all
|
691
|
+
http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:8080/index.html
|
692
|
+
http://[1080:0:0:0:8:800:200C:417A]/index.html
|
693
|
+
http://[3ffe:2a00:100:7031::1]
|
694
|
+
http://[1080::8:800:200C:417A]/foo
|
695
|
+
http://[::192.9.5.5]/ipng
|
696
|
+
http://[::FFFF:129.144.52.38]:3474/index.html
|
697
|
+
http://[2010:836B:4179::836B:4179]
|
698
|
+
|
699
|
+
https://mail.google.com/
|
700
|
+
https://127.0.0.1/
|
701
|
+
https://r4.com:8080/
|
702
|
+
|
703
|
+
ftp://ftp.ruby-lang.org/pub/ruby/1.0/ruby-0.49.tar.gz
|
704
|
+
ftp://crashoverride:god@gibson.ellingsonmineral.com/root/.workspace/.garbage.
|
705
|
+
|
706
|
+
ldap:/o=University%20of%20Michigan,c=US
|
707
|
+
ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US
|
708
|
+
ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US?postalAddress
|
709
|
+
ldap://host.com:6666/o=University%20of%20Michigan,c=US??sub?(cn=Babs%20Jensen)
|
710
|
+
ldap://ldap.itd.umich.edu/c=GB?objectClass?one
|
711
|
+
ldap://ldap.question.com/o=Question%3f,c=US?mail
|
712
|
+
ldap://ldap.netscape.com/o=Babsco,c=US??(int=%5c00%5c00%5c00%5c04)
|
713
|
+
ldap:/??sub??bindname=cn=Manager%2co=Foo
|
714
|
+
ldap:/??sub??!bindname=cn=Manager%2co=Foo
|
715
|
+
}
|
716
|
+
|
717
|
+
VALID_URIS.each do |uri_string|
|
718
|
+
it "accepts #{uri_string} for fields with URI constraints" do
|
719
|
+
params = {'required' => '1', 'uri_constraint' => uri_string}
|
720
|
+
|
721
|
+
@validator.validate( params )
|
722
|
+
|
723
|
+
@validator.should be_okay()
|
724
|
+
@validator.should_not have_errors()
|
725
|
+
|
726
|
+
@validator[:uri_constraint].should be_a_kind_of( URI::Generic )
|
727
|
+
@validator[:uri_constraint].to_s.should == uri_string
|
728
|
+
end
|
729
|
+
end
|
730
|
+
|
731
|
+
# :FIXME: I don't know LDAP uris very well, so I'm not sure how they're likely to
|
732
|
+
# be invalidly-occurring in the wild
|
733
|
+
INVALID_URIS = %W{
|
734
|
+
glark:
|
735
|
+
|
736
|
+
http:
|
737
|
+
http://
|
738
|
+
http://_com/vlog/rb_08_feb_01
|
739
|
+
http://del.icio.us/search/\x20\x14\x18
|
740
|
+
http://FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/index.html
|
741
|
+
http://1080:0:0:0:8:800:200C:417A/index.html
|
742
|
+
http://3ffe:2a00:100:7031::1
|
743
|
+
http://1080::8:800:200C:417A/foo
|
744
|
+
http://::192.9.5.5/ipng
|
745
|
+
http://::FFFF:129.144.52.38:80/index.html
|
746
|
+
http://2010:836B:4179::836B:4179
|
747
|
+
|
748
|
+
https:
|
749
|
+
https://user:pass@/
|
750
|
+
https://r4.com:nonnumericport/
|
751
|
+
|
752
|
+
ftp:
|
753
|
+
ftp:ruby-0.49.tar.gz
|
754
|
+
ftp://crashoverride:god@/root/.workspace/.garbage.
|
755
|
+
|
756
|
+
ldap:
|
757
|
+
ldap:/o=University\x20of\x20Michigan,c=US
|
758
|
+
ldap://ldap.itd.umich.edu/o=University+\x00of+Michigan
|
759
|
+
}
|
760
|
+
|
761
|
+
INVALID_URIS.each do |uri_string|
|
762
|
+
it "rejects #{uri_string} for fields with URI constraints" do
|
763
|
+
params = {'required' => '1', 'uri_constraint' => uri_string}
|
764
|
+
|
765
|
+
# lambda {
|
766
|
+
@validator.validate( params )
|
767
|
+
# }.should_not raise_error()
|
768
|
+
|
769
|
+
@validator.should_not be_okay()
|
770
|
+
@validator.should have_errors()
|
771
|
+
|
772
|
+
@validator[:uri_constraint].should be_nil()
|
773
|
+
end
|
774
|
+
end
|
775
|
+
|
776
|
+
it "accepts simple RFC822 addresses for fields with email constraints" do
|
777
|
+
params = {'required' => '1', 'email_constraint' => 'jrandom@hacker.ie'}
|
778
|
+
|
779
|
+
@validator.validate( params )
|
780
|
+
|
781
|
+
@validator.should be_okay()
|
782
|
+
@validator.should_not have_errors()
|
783
|
+
|
784
|
+
@validator[:email_constraint].should == 'jrandom@hacker.ie'
|
785
|
+
end
|
786
|
+
|
787
|
+
it "accepts hyphenated domains in RFC822 addresses for fields with email constraints" do
|
788
|
+
params = {'required' => '1', 'email_constraint' => 'jrandom@just-another-hacquer.fr'}
|
789
|
+
|
790
|
+
@validator.validate( params )
|
791
|
+
|
792
|
+
@validator.should be_okay()
|
793
|
+
@validator.should_not have_errors()
|
794
|
+
|
795
|
+
@validator[:email_constraint].should == 'jrandom@just-another-hacquer.fr'
|
796
|
+
end
|
797
|
+
|
798
|
+
COMPLEX_ADDRESSES = [
|
799
|
+
'ruby+hacker@random-example.org',
|
800
|
+
'"ruby hacker"@ph8675309.org',
|
801
|
+
'jrandom@[ruby hacquer].com',
|
802
|
+
'abcdefghijklmnopqrstuvwxyz@abcdefghijklmnopqrstuvwxyz',
|
803
|
+
]
|
804
|
+
COMPLEX_ADDRESSES.each do |addy|
|
805
|
+
it "accepts #{addy} for fields with email constraints" do
|
806
|
+
params = {'required' => '1', 'email_constraint' => addy}
|
807
|
+
|
808
|
+
@validator.validate( params )
|
809
|
+
|
810
|
+
@validator.should be_okay()
|
811
|
+
@validator.should_not have_errors()
|
812
|
+
|
813
|
+
@validator[:email_constraint].should == addy
|
814
|
+
end
|
815
|
+
end
|
816
|
+
|
817
|
+
|
818
|
+
BOGUS_ADDRESSES = [
|
819
|
+
'jrandom@hacquer com',
|
820
|
+
'jrandom@ruby hacquer.com',
|
821
|
+
'j random@rubyhacquer.com',
|
822
|
+
'j random@ruby|hacquer.com',
|
823
|
+
'j:random@rubyhacquer.com',
|
824
|
+
]
|
825
|
+
BOGUS_ADDRESSES.each do |addy|
|
826
|
+
it "rejects #{addy} for fields with email constraints" do
|
827
|
+
params = {'required' => '1', 'email_constraint' => addy}
|
828
|
+
|
829
|
+
@validator.validate( params )
|
830
|
+
|
831
|
+
@validator.should_not be_okay()
|
832
|
+
@validator.should have_errors()
|
833
|
+
|
834
|
+
@validator[:email_constraint].should be_nil()
|
835
|
+
end
|
836
|
+
end
|
837
|
+
|
838
|
+
it "accepts simple hosts for fields with host constraints" do
|
839
|
+
params = {'required' => '1', 'host_constraint' => 'deveiate.org'}
|
840
|
+
|
841
|
+
@validator.validate( params )
|
842
|
+
|
843
|
+
@validator.should be_okay()
|
844
|
+
@validator.should_not have_errors()
|
845
|
+
|
846
|
+
@validator[:host_constraint].should == 'deveiate.org'
|
847
|
+
end
|
848
|
+
|
849
|
+
it "accepts hyphenated hosts for fields with host constraints" do
|
850
|
+
params = {'required' => '1', 'host_constraint' => 'your-characters-can-fly.kr'}
|
851
|
+
|
852
|
+
@validator.validate( params )
|
853
|
+
|
854
|
+
@validator.should be_okay()
|
855
|
+
@validator.should_not have_errors()
|
856
|
+
|
857
|
+
@validator[:host_constraint].should == 'your-characters-can-fly.kr'
|
858
|
+
end
|
859
|
+
|
860
|
+
BOGUS_HOSTS = [
|
861
|
+
'.',
|
862
|
+
'glah ',
|
863
|
+
'glah[lock]',
|
864
|
+
'glah.be$',
|
865
|
+
'indus«tree».com',
|
866
|
+
]
|
867
|
+
|
868
|
+
BOGUS_HOSTS.each do |hostname|
|
869
|
+
it "rejects #{hostname} for fields with host constraints" do
|
870
|
+
params = {'required' => '1', 'host_constraint' => hostname}
|
871
|
+
|
872
|
+
@validator.validate( params )
|
873
|
+
|
874
|
+
@validator.should_not be_okay()
|
875
|
+
@validator.should have_errors()
|
876
|
+
|
877
|
+
@validator[:host_constraint].should be_nil()
|
878
|
+
end
|
879
|
+
end
|
880
|
+
|
881
|
+
it "accepts alpha characters for fields with alpha constraints" do
|
882
|
+
params = {'required' => '1', 'alpha_constraint' => 'abelincoln'}
|
883
|
+
|
884
|
+
@validator.validate( params )
|
885
|
+
|
886
|
+
@validator.should be_okay()
|
887
|
+
@validator.should_not have_errors()
|
888
|
+
|
889
|
+
@validator[:alpha_constraint].should == 'abelincoln'
|
890
|
+
end
|
891
|
+
|
892
|
+
it "rejects non-alpha characters for fields with alpha constraints" do
|
893
|
+
params = {'required' => '1', 'alpha_constraint' => 'duck45'}
|
894
|
+
|
895
|
+
@validator.validate( params )
|
896
|
+
|
897
|
+
@validator.should_not be_okay()
|
898
|
+
@validator.should have_errors()
|
899
|
+
|
900
|
+
@validator[:alpha_constraint].should be_nil()
|
901
|
+
end
|
902
|
+
|
903
|
+
### 'alphanumeric'
|
904
|
+
it "accepts alphanumeric characters for fields with alphanumeric constraints" do
|
905
|
+
params = {'required' => '1', 'alphanumeric_constraint' => 'zombieabe11'}
|
906
|
+
|
907
|
+
@validator.validate( params )
|
908
|
+
|
909
|
+
@validator.should be_okay()
|
910
|
+
@validator.should_not have_errors()
|
911
|
+
|
912
|
+
@validator[:alphanumeric_constraint].should == 'zombieabe11'
|
913
|
+
end
|
914
|
+
|
915
|
+
it "rejects non-alphanumeric characters for fields with alphanumeric constraints" do
|
916
|
+
params = {'required' => '1', 'alphanumeric_constraint' => 'duck!ling'}
|
917
|
+
|
918
|
+
@validator.validate( params )
|
919
|
+
|
920
|
+
@validator.should_not be_okay()
|
921
|
+
@validator.should have_errors()
|
922
|
+
|
923
|
+
@validator[:alphanumeric_constraint].should be_nil()
|
924
|
+
end
|
925
|
+
|
926
|
+
### 'printable'
|
927
|
+
it "accepts printable characters for fields with 'printable' constraints" do
|
928
|
+
test_content = <<-EOF
|
929
|
+
I saw you with some kind of medical apparatus strapped to your
|
930
|
+
spine. It was all glass and metal, a great crystaline hypodermic
|
931
|
+
spider, carrying you into the aether with a humming, crackling sound.
|
932
|
+
EOF
|
933
|
+
|
934
|
+
params = {
|
935
|
+
'required' => '1',
|
936
|
+
'printable_constraint' => test_content
|
937
|
+
}
|
938
|
+
|
939
|
+
@validator.validate( params )
|
940
|
+
|
941
|
+
@validator.should be_okay()
|
942
|
+
@validator[:printable_constraint].should == test_content
|
943
|
+
end
|
944
|
+
|
945
|
+
it "rejects non-printable characters for fields with 'printable' constraints" do
|
946
|
+
params = {'required' => '1', 'printable_constraint' => %{\0Something cold\0}}
|
947
|
+
|
948
|
+
@validator.validate( params )
|
949
|
+
|
950
|
+
@validator.should_not be_okay()
|
951
|
+
@validator.should have_errors()
|
952
|
+
|
953
|
+
@validator[:printable_constraint].should be_nil()
|
954
|
+
end
|
955
|
+
|
956
|
+
|
957
|
+
it "accepts any word characters for fields with 'word' constraints" do
|
958
|
+
params = {
|
959
|
+
'required' => '1',
|
960
|
+
'word_constraint' => "Собака"
|
961
|
+
}
|
962
|
+
|
963
|
+
@validator.validate( params )
|
964
|
+
|
965
|
+
@validator.should_not have_errors()
|
966
|
+
@validator.should be_okay()
|
967
|
+
|
968
|
+
@validator[:word_constraint].should == params['word_constraint']
|
969
|
+
end
|
970
|
+
|
971
|
+
it "accepts parameters for fields with Proc constraints if the Proc returns a true value" do
|
972
|
+
test_date = '2007-07-17'
|
973
|
+
params = {'required' => '1', 'proc_constraint' => test_date}
|
974
|
+
|
975
|
+
@validator.validate( params )
|
976
|
+
|
977
|
+
@validator.should be_okay()
|
978
|
+
@validator.should_not have_errors()
|
979
|
+
|
980
|
+
@validator[:proc_constraint].should == Date.parse( test_date )
|
981
|
+
end
|
982
|
+
|
983
|
+
it "rejects parameters for fields with Proc constraints if the Proc returns a false value" do
|
984
|
+
params = {'required' => '1', 'proc_constraint' => %{::::}}
|
985
|
+
|
986
|
+
@validator.validate( params )
|
987
|
+
|
988
|
+
@validator.should_not be_okay()
|
989
|
+
@validator.should have_errors()
|
990
|
+
|
991
|
+
@validator[:proc_constraint].should be_nil()
|
992
|
+
end
|
993
|
+
|
994
|
+
it "can be merged with another set of parameters" do
|
995
|
+
params = {}
|
996
|
+
@validator.validate( params )
|
997
|
+
newval = @validator.merge( 'required' => '1' )
|
998
|
+
|
999
|
+
newval.should_not equal( @validator )
|
1000
|
+
|
1001
|
+
@validator.should_not be_okay()
|
1002
|
+
@validator.should have_errors()
|
1003
|
+
newval.should be_okay()
|
1004
|
+
newval.should_not have_errors()
|
1005
|
+
|
1006
|
+
@validator[:required].should == nil
|
1007
|
+
newval[:required].should == '1'
|
1008
|
+
end
|
1009
|
+
|
1010
|
+
it "can have required parameters merged into it after the initial validation" do
|
1011
|
+
params = {}
|
1012
|
+
@validator.validate( params )
|
1013
|
+
@validator.merge!( 'required' => '1' )
|
1014
|
+
|
1015
|
+
@validator.should be_okay()
|
1016
|
+
@validator.should_not have_errors()
|
1017
|
+
|
1018
|
+
@validator[:required].should == '1'
|
1019
|
+
end
|
1020
|
+
|
1021
|
+
it "can have optional parameters merged into it after the initial validation" do
|
1022
|
+
params = { 'required' => '1' }
|
1023
|
+
@validator.validate( params )
|
1024
|
+
@validator.merge!( 'optional' => 'yep.' )
|
1025
|
+
|
1026
|
+
@validator.should be_okay()
|
1027
|
+
@validator.should_not have_errors()
|
1028
|
+
|
1029
|
+
@validator[:optional].should == 'yep.'
|
1030
|
+
end
|
1031
|
+
|
1032
|
+
it "rejects invalid parameters when they're merged after initial validation" do
|
1033
|
+
params = { 'required' => '1', 'number' => '88' }
|
1034
|
+
@validator.validate( params )
|
1035
|
+
@validator.merge!( 'number' => 'buckwheat noodles' )
|
1036
|
+
|
1037
|
+
@validator.should_not be_okay()
|
1038
|
+
@validator.should have_errors()
|
1039
|
+
|
1040
|
+
@validator[:number].should be_nil()
|
1041
|
+
end
|
1042
|
+
|
1043
|
+
it "allows valid parameters to be fetched en masse" do
|
1044
|
+
params = { 'required' => '1', 'number' => '88' }
|
1045
|
+
@validator.validate( params )
|
1046
|
+
@validator.values_at( :required, :number ).should == [ '1', '88' ]
|
1047
|
+
end
|
1048
|
+
|
1049
|
+
it "treats ArgumentErrors in builtin constraints as validation failures" do
|
1050
|
+
params = { 'required' => '1', 'number' => 'jalopy' }
|
1051
|
+
@validator.validate( params )
|
1052
|
+
@validator.should_not be_okay()
|
1053
|
+
@validator.should have_errors()
|
1054
|
+
@validator.error_messages.should == ["Invalid value for 'Number'"]
|
1055
|
+
@validator[:number].should == nil
|
1056
|
+
end
|
1057
|
+
|
1058
|
+
end
|
1059
|
+
|