strelka 0.0.1.pre.203 → 0.0.1.pre.214

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