strelka 0.0.1pre4 → 0.0.1.pre129

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/History.rdoc +1 -1
  2. data/IDEAS.rdoc +62 -0
  3. data/Manifest.txt +38 -7
  4. data/README.rdoc +124 -5
  5. data/Rakefile +22 -6
  6. data/bin/leash +102 -157
  7. data/contrib/hoetemplate/.autotest.erb +23 -0
  8. data/contrib/hoetemplate/History.rdoc.erb +4 -0
  9. data/contrib/hoetemplate/Manifest.txt.erb +8 -0
  10. data/contrib/hoetemplate/README.rdoc.erb +17 -0
  11. data/contrib/hoetemplate/Rakefile.erb +24 -0
  12. data/contrib/hoetemplate/data/file_name/apps/file_name_app +36 -0
  13. data/contrib/hoetemplate/data/file_name/templates/layout.tmpl.erb +13 -0
  14. data/contrib/hoetemplate/data/file_name/templates/top.tmpl.erb +8 -0
  15. data/contrib/hoetemplate/lib/file_name.rb.erb +18 -0
  16. data/contrib/hoetemplate/spec/file_name_spec.rb.erb +21 -0
  17. data/data/strelka/apps/hello-world +30 -0
  18. data/lib/strelka/app/defaultrouter.rb +49 -30
  19. data/lib/strelka/app/errors.rb +121 -0
  20. data/lib/strelka/app/exclusiverouter.rb +40 -0
  21. data/lib/strelka/app/filters.rb +18 -7
  22. data/lib/strelka/app/negotiation.rb +122 -0
  23. data/lib/strelka/app/parameters.rb +171 -14
  24. data/lib/strelka/app/paramvalidator.rb +751 -0
  25. data/lib/strelka/app/plugins.rb +66 -46
  26. data/lib/strelka/app/restresources.rb +499 -0
  27. data/lib/strelka/app/router.rb +73 -0
  28. data/lib/strelka/app/routing.rb +140 -18
  29. data/lib/strelka/app/templating.rb +12 -3
  30. data/lib/strelka/app.rb +174 -24
  31. data/lib/strelka/constants.rb +0 -20
  32. data/lib/strelka/exceptions.rb +29 -0
  33. data/lib/strelka/httprequest/acceptparams.rb +377 -0
  34. data/lib/strelka/httprequest/negotiation.rb +257 -0
  35. data/lib/strelka/httprequest.rb +155 -7
  36. data/lib/strelka/httpresponse/negotiation.rb +579 -0
  37. data/lib/strelka/httpresponse.rb +140 -0
  38. data/lib/strelka/logging.rb +4 -1
  39. data/lib/strelka/mixins.rb +53 -0
  40. data/lib/strelka.rb +22 -1
  41. data/spec/data/error.tmpl +1 -0
  42. data/spec/lib/constants.rb +0 -1
  43. data/spec/lib/helpers.rb +21 -0
  44. data/spec/strelka/app/defaultrouter_spec.rb +41 -35
  45. data/spec/strelka/app/errors_spec.rb +212 -0
  46. data/spec/strelka/app/exclusiverouter_spec.rb +220 -0
  47. data/spec/strelka/app/filters_spec.rb +196 -0
  48. data/spec/strelka/app/negotiation_spec.rb +73 -0
  49. data/spec/strelka/app/parameters_spec.rb +149 -0
  50. data/spec/strelka/app/paramvalidator_spec.rb +1059 -0
  51. data/spec/strelka/app/plugins_spec.rb +26 -19
  52. data/spec/strelka/app/restresources_spec.rb +393 -0
  53. data/spec/strelka/app/router_spec.rb +63 -0
  54. data/spec/strelka/app/routing_spec.rb +183 -9
  55. data/spec/strelka/app/templating_spec.rb +1 -2
  56. data/spec/strelka/app_spec.rb +265 -32
  57. data/spec/strelka/exceptions_spec.rb +53 -0
  58. data/spec/strelka/httprequest/acceptparams_spec.rb +282 -0
  59. data/spec/strelka/httprequest/negotiation_spec.rb +246 -0
  60. data/spec/strelka/httprequest_spec.rb +204 -14
  61. data/spec/strelka/httpresponse/negotiation_spec.rb +464 -0
  62. data/spec/strelka/httpresponse_spec.rb +114 -0
  63. data/spec/strelka/mixins_spec.rb +99 -0
  64. data.tar.gz.sig +1 -0
  65. metadata +175 -79
  66. metadata.gz.sig +2 -0
  67. data/IDEAS.textile +0 -174
  68. data/data/strelka/apps/strelka-admin +0 -65
  69. data/data/strelka/apps/strelka-setup +0 -26
  70. data/data/strelka/bootstrap-config.rb +0 -34
  71. data/data/strelka/templates/admin/console.tmpl +0 -21
  72. data/data/strelka/templates/layout.tmpl +0 -30
  73. data/lib/strelka/process.rb +0 -19
@@ -0,0 +1,220 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ BEGIN {
4
+ require 'pathname'
5
+ basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
6
+ $LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
7
+ }
8
+
9
+ require 'rspec'
10
+
11
+ require 'spec/lib/helpers'
12
+
13
+ require 'strelka'
14
+ require 'strelka/app/exclusiverouter'
15
+
16
+
17
+ #####################################################################
18
+ ### C O N T E X T S
19
+ #####################################################################
20
+
21
+ describe Strelka::App::ExclusiveRouter do
22
+
23
+ before( :all ) do
24
+ setup_logging( :fatal )
25
+ @request_factory = Mongrel2::RequestFactory.new( route: '/user' )
26
+ end
27
+
28
+ before( :each ) do
29
+ @router = Strelka::App::ExclusiveRouter.new
30
+ end
31
+
32
+ after( :all ) do
33
+ reset_logging()
34
+ end
35
+
36
+ context "a router with routes for 'foo', 'foo/bar'" do
37
+
38
+ before( :each ) do
39
+ @router.add_route( :GET, ['foo'], route(:foo) )
40
+ @router.add_route( :GET, ['foo','bar'], route(:foo_bar) )
41
+ end
42
+
43
+ it "doesn't route /user/foo/bar/baz" do
44
+ req = @request_factory.get( '/user/foo/bar/baz' )
45
+ @router.route_request( req ).should be_nil()
46
+ end
47
+
48
+ it "routes /user/foo/bar to the foo/bar action" do
49
+ req = @request_factory.get( '/user/foo/bar' )
50
+ @router.route_request( req ).should match_route( :foo_bar )
51
+ end
52
+
53
+ it "routes /user/foo/bar?limit=10 to the foo/bar action" do
54
+ req = @request_factory.get( '/user/foo/bar?limit=10' )
55
+ @router.route_request( req ).should match_route( :foo_bar )
56
+ end
57
+
58
+ it "routes /user/foo to the foo action" do
59
+ req = @request_factory.get( '/user/foo' )
60
+ @router.route_request( req ).should match_route( :foo )
61
+ end
62
+
63
+ it "doesn't route /user" do
64
+ req = @request_factory.get( '/user' )
65
+ @router.route_request( req ).should be_nil()
66
+ end
67
+
68
+ it "doesn't route /user/other" do
69
+ req = @request_factory.get( '/user/other' )
70
+ @router.route_request( req ).should be_nil()
71
+ end
72
+
73
+ end
74
+
75
+ context "a router with routes for 'foo', 'foo/bar', and a fallback action" do
76
+
77
+ before( :each ) do
78
+ @router.add_route( :GET, [], route(:fallback) )
79
+ @router.add_route( :GET, ['foo'], route(:foo) )
80
+ @router.add_route( :GET, ['foo','bar'], route(:foo_bar) )
81
+ end
82
+
83
+ it "doesn't route /user/foo/bar/baz" do
84
+ req = @request_factory.get( '/user/foo/bar/baz' )
85
+ @router.route_request( req ).should be_nil()
86
+ end
87
+
88
+ it "routes /user/foo/bar to the foo/bar action" do
89
+ req = @request_factory.get( '/user/foo/bar' )
90
+ @router.route_request( req ).should match_route( :foo_bar )
91
+ end
92
+
93
+ it "routes /user/foo to the foo action" do
94
+ req = @request_factory.get( '/user/foo' )
95
+ @router.route_request( req ).should match_route( :foo )
96
+ end
97
+
98
+ it "routes /user to the fallback action" do
99
+ req = @request_factory.get( '/user' )
100
+ @router.route_request( req ).should match_route( :fallback )
101
+ end
102
+
103
+ it "doesn't route /user/other" do
104
+ req = @request_factory.get( '/user/other' )
105
+ @router.route_request( req ).should be_nil()
106
+ end
107
+
108
+ end
109
+
110
+ context "a router with routes for 'foo', 'foo/\w{3}', and 'foo/\w{6}'" do
111
+
112
+ before( :each ) do
113
+ @router.add_route( :GET, ['foo'], route(:foo) )
114
+ @router.add_route( :GET, ['foo',/\w{3}/], route(:foo_three) )
115
+ @router.add_route( :GET, ['foo',/\w{6}/], route(:foo_six) )
116
+ end
117
+
118
+ it "doesn't route /user/foo/barbim/baz" do
119
+ req = @request_factory.get( '/user/foo/barbim/baz' )
120
+ @router.route_request( req ).should be_nil()
121
+ end
122
+
123
+ it "routes /user/foo/barbat to the foo/\w{6} action" do
124
+ req = @request_factory.get( '/user/foo/barbat' )
125
+ @router.route_request( req ).should match_route( :foo_six )
126
+ end
127
+
128
+ it "doesn't route /user/foo/bar/baz" do
129
+ req = @request_factory.get( '/user/foo/bar/baz' )
130
+ @router.route_request( req ).should be_nil()
131
+ end
132
+
133
+ it "routes /user/foo/bar to the foo/\w{3} action" do
134
+ req = @request_factory.get( '/user/foo/bar' )
135
+ @router.route_request( req ).should match_route( :foo_three )
136
+ end
137
+
138
+ it "routes /user/foo to the foo action" do
139
+ req = @request_factory.get( '/user/foo' )
140
+ @router.route_request( req ).should match_route( :foo )
141
+ end
142
+
143
+ it "doesn't route /user" do
144
+ req = @request_factory.get( '/user' )
145
+ @router.route_request( req ).should be_nil()
146
+ end
147
+
148
+ it "doesn't route /user/other" do
149
+ req = @request_factory.get( '/user/other' )
150
+ @router.route_request( req ).should be_nil()
151
+ end
152
+
153
+ end
154
+
155
+ # get '/foo/\w{3}'
156
+ # get '/foo/\d+'
157
+
158
+ context "a router with routes for: 'foo/\w{3}', then 'foo/\d+'" do
159
+
160
+ before( :each ) do
161
+ @router.add_route( :GET, ['foo',/\w{3}/], route(:foo_three) )
162
+ @router.add_route( :GET, ['foo',/\d+/], route(:foo_digit) )
163
+ end
164
+
165
+ it "routes /user/foo/1 to the foo/\d+ action" do
166
+ req = @request_factory.get( '/user/foo/1' )
167
+ @router.route_request( req ).should match_route( :foo_digit )
168
+ end
169
+
170
+ it "routes /user/foo/12 to the foo/\d+ action" do
171
+ req = @request_factory.get( '/user/foo/12' )
172
+ @router.route_request( req ).should match_route( :foo_digit )
173
+ end
174
+
175
+ it "routes /user/foo/123 to the foo/\w{3} action" do
176
+ req = @request_factory.get( '/user/foo/123' )
177
+ @router.route_request( req ).should match_route( :foo_three )
178
+ end
179
+
180
+ it "routes /user/foo/1234 to the foo/\d+ action" do
181
+ req = @request_factory.get( '/user/foo/1234' )
182
+ @router.route_request( req ).should match_route( :foo_digit )
183
+ end
184
+
185
+ end
186
+
187
+ # get '/foo/\d+'
188
+ # get '/foo/\w{3}'
189
+
190
+ context "a router with routes for: 'foo/\d+', then 'foo/\w{3}'" do
191
+
192
+ before( :each ) do
193
+ @router.add_route( :GET, ['foo',/\d+/], route(:foo_digit) )
194
+ @router.add_route( :GET, ['foo',/\w{3}/], route(:foo_three) )
195
+ end
196
+
197
+ it "routes /user/foo/1 to the foo/\d+ action" do
198
+ req = @request_factory.get( '/user/foo/1' )
199
+ @router.route_request( req ).should match_route( :foo_digit )
200
+ end
201
+
202
+ it "routes /user/foo/12 to the foo/\d+ action" do
203
+ req = @request_factory.get( '/user/foo/12' )
204
+ @router.route_request( req ).should match_route( :foo_digit )
205
+ end
206
+
207
+ it "routes /user/foo/123 to the foo/\d+ action" do
208
+ req = @request_factory.get( '/user/foo/123' )
209
+ @router.route_request( req ).should match_route( :foo_digit )
210
+ end
211
+
212
+ it "routes /user/foo/1234 to the foo/\d+ action" do
213
+ req = @request_factory.get( '/user/foo/1234' )
214
+ @router.route_request( req ).should match_route( :foo_digit )
215
+ end
216
+
217
+ end
218
+
219
+ end
220
+
@@ -0,0 +1,196 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ BEGIN {
4
+ require 'pathname'
5
+ basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
6
+ $LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
7
+ }
8
+
9
+ require 'rspec'
10
+
11
+ require 'spec/lib/helpers'
12
+
13
+ require 'strelka'
14
+ require 'strelka/app/plugins'
15
+ require 'strelka/app/filters'
16
+
17
+ require 'strelka/behavior/plugin'
18
+
19
+
20
+ #####################################################################
21
+ ### C O N T E X T S
22
+ #####################################################################
23
+
24
+ describe Strelka::App::Filters do
25
+
26
+ before( :all ) do
27
+ setup_logging( :fatal )
28
+ @request_factory = Mongrel2::RequestFactory.new( route: '' )
29
+ end
30
+
31
+ after( :all ) do
32
+ reset_logging()
33
+ end
34
+
35
+
36
+ it_should_behave_like( "A Strelka::App Plugin" )
37
+
38
+
39
+ describe "an including App" do
40
+
41
+ before( :each ) do
42
+ Strelka.log.debug "Creating a new Strelka::App"
43
+ @app = Class.new( Strelka::App ) do
44
+ plugin :filters
45
+ def initialize( appid='params-test', sspec=TEST_SEND_SPEC, rspec=TEST_RECV_SPEC )
46
+ super
47
+ end
48
+ end
49
+ Strelka.log.debug " new instance is: %p, filters array: 0x%016x" %
50
+ [ @app, @app.filters.object_id * 2 ]
51
+ end
52
+
53
+
54
+ it "has a Hash of filters" do
55
+ @app.filters.should be_a( Hash )
56
+ end
57
+
58
+
59
+ describe "that doesn't declare any filters" do
60
+
61
+ it "doesn't have any request filters" do
62
+ @app.request_filters.should be_empty()
63
+ end
64
+
65
+ it "doesn't have any response filters" do
66
+ @app.response_filters.should be_empty()
67
+ end
68
+
69
+ end
70
+
71
+
72
+ describe "that declares a filter without a phase" do
73
+
74
+ before( :each ) do
75
+ @app.class_eval do
76
+ filter do |reqres|
77
+ if reqres.respond_to?( :notes )
78
+ reqres.notes[:test] = 'filtered notes'
79
+ else
80
+ reqres.body = 'filtered body'
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ after( :each ) do
87
+ @app.filters[:request].clear
88
+ @app.filters[:response].clear
89
+ @app.filters[:both].clear
90
+ end
91
+
92
+
93
+ it "has a single request filter" do
94
+ @app.request_filters.should have(1).member
95
+ end
96
+
97
+ it "has a single response filter" do
98
+ @app.response_filters.should have(1).member
99
+ end
100
+
101
+ it "passes both the request and the response through it" do
102
+ req = @request_factory.get( '/account/118811' )
103
+
104
+ res = @app.new.handle( req )
105
+
106
+ req.notes[:test].should == 'filtered notes'
107
+ res.body.should == 'filtered body'
108
+ end
109
+
110
+ end
111
+
112
+ describe "that declares a request filter" do
113
+
114
+ before( :each ) do
115
+ @app.class_eval do
116
+ filter( :request ) do |reqres|
117
+ if reqres.respond_to?( :notes )
118
+ reqres.notes[:test] = 'filtered notes'
119
+ else
120
+ reqres.body = 'filtered body'
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ after( :each ) do
127
+ @app.filters[:request].clear
128
+ @app.filters[:response].clear
129
+ @app.filters[:both].clear
130
+ end
131
+
132
+
133
+ it "has a single request filter" do
134
+ @app.request_filters.should have(1).member
135
+ end
136
+
137
+ it "has no response filters" do
138
+ @app.response_filters.should be_empty()
139
+ end
140
+
141
+ it "passes just the request through it" do
142
+ req = @request_factory.get( '/account/118811' )
143
+
144
+ res = @app.new.handle( req )
145
+
146
+ req.notes[:test].should == 'filtered notes'
147
+ res.body.should_not == 'filtered body'
148
+ end
149
+
150
+ end
151
+
152
+ describe "that declares a response filter" do
153
+
154
+ before( :each ) do
155
+ @app.class_eval do
156
+ filter( :response ) do |reqres|
157
+ if reqres.respond_to?( :notes )
158
+ reqres.notes[:test] = 'filtered notes'
159
+ else
160
+ reqres.body = 'filtered body'
161
+ end
162
+ end
163
+ end
164
+ end
165
+
166
+ after( :each ) do
167
+ @app.filters[:request].clear
168
+ @app.filters[:response].clear
169
+ @app.filters[:both].clear
170
+ end
171
+
172
+
173
+ it "has no request filters" do
174
+ @app.request_filters.should be_empty()
175
+ end
176
+
177
+ it "has no response filters" do
178
+ @app.response_filters.should have(1).member
179
+ end
180
+
181
+ it "passes just the response through it" do
182
+ req = @request_factory.get( '/account/118811' )
183
+
184
+ res = @app.new.handle( req )
185
+
186
+ req.notes[:test].should == {}
187
+ res.body.should == 'filtered body'
188
+ end
189
+
190
+ end
191
+
192
+ end
193
+
194
+
195
+ end
196
+
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ BEGIN {
4
+ require 'pathname'
5
+ basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
6
+ $LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
7
+ }
8
+
9
+ require 'rspec'
10
+
11
+ require 'spec/lib/helpers'
12
+
13
+ require 'strelka'
14
+ require 'strelka/app/plugins'
15
+ require 'strelka/app/negotiation'
16
+ require 'strelka/behavior/plugin'
17
+
18
+
19
+ #####################################################################
20
+ ### C O N T E X T S
21
+ #####################################################################
22
+
23
+ describe Strelka::App::Negotiation do
24
+
25
+
26
+ before( :all ) do
27
+ setup_logging( :fatal )
28
+ @request_factory = Mongrel2::RequestFactory.new( route: '/service/user' )
29
+ end
30
+
31
+ after( :all ) do
32
+ reset_logging()
33
+ end
34
+
35
+
36
+ it_should_behave_like( "A Strelka::App Plugin" )
37
+
38
+
39
+ describe "an including App" do
40
+
41
+ before( :each ) do
42
+ @app = Class.new( Strelka::App ) do
43
+ plugin :negotiation
44
+ def initialize( appid='conneg-test', sspec=TEST_SEND_SPEC, rspec=TEST_RECV_SPEC )
45
+ super
46
+ end
47
+ end
48
+ end
49
+
50
+ after( :each ) do
51
+ @app = nil
52
+ end
53
+
54
+
55
+ it "gets requests that have been extended with content-negotiation" do
56
+ req = @request_factory.get( '/service/user/estark' )
57
+ @app.new.handle( req )
58
+ req.singleton_class.included_modules.
59
+ should include( Strelka::HTTPRequest::Negotiation )
60
+ end
61
+
62
+ it "gets responses that have been extended with content-negotiation" do
63
+ req = @request_factory.get( '/service/user/estark' )
64
+ res = @app.new.handle( req )
65
+ res.singleton_class.included_modules.
66
+ should include( Strelka::HTTPResponse::Negotiation )
67
+ end
68
+
69
+ end
70
+
71
+
72
+ end
73
+
@@ -24,6 +24,7 @@ describe Strelka::App::Parameters do
24
24
 
25
25
  before( :all ) do
26
26
  setup_logging( :fatal )
27
+ @request_factory = Mongrel2::RequestFactory.new( route: '/user' )
27
28
  end
28
29
 
29
30
  after( :all ) do
@@ -39,9 +40,16 @@ describe Strelka::App::Parameters do
39
40
  before( :each ) do
40
41
  @app = Class.new( Strelka::App ) do
41
42
  plugin :parameters
43
+ def initialize( appid='params-test', sspec=TEST_SEND_SPEC, rspec=TEST_RECV_SPEC )
44
+ super
45
+ end
42
46
  end
43
47
  end
44
48
 
49
+ after( :each ) do
50
+ @app = nil
51
+ end
52
+
45
53
  it "has a parameters Hash" do
46
54
  @app.parameters.should be_a( Hash )
47
55
  end
@@ -56,6 +64,91 @@ describe Strelka::App::Parameters do
56
64
  should include( :constraint => /(?<username>(?i-mx:\w+))/ )
57
65
  end
58
66
 
67
+ it "can declare a parameter with an Array validation" do
68
+ @app.class_eval do
69
+ param :username, [:printable, lambda {|str| str.length <= 16 }]
70
+ end
71
+
72
+ @app.parameters.should have( 1 ).member
73
+ @app.parameters[:username][:constraint][0].should == :printable
74
+ @app.parameters[:username][:constraint][1].should be_an_instance_of( Proc )
75
+ end
76
+
77
+ it "can declare a parameter with a Hash validation" do
78
+ @app.class_eval do
79
+ param :username, {'ambrel' => 'A. Hotchgah'}
80
+ end
81
+
82
+ @app.parameters.should have( 1 ).member
83
+ @app.parameters[ :username ].
84
+ should include( :constraint => {'ambrel' => 'A. Hotchgah'} )
85
+ end
86
+
87
+ it "can declare a parameter with a matcher validation" do
88
+ @app.class_eval do
89
+ param :host, :hostname
90
+ end
91
+
92
+ @app.parameters.should have( 1 ).member
93
+ @app.parameters[ :host ].should include( :constraint => :hostname )
94
+ end
95
+
96
+ it "can declare a parameter with a validation pattern and a description" do
97
+ @app.class_eval do
98
+ param :username, /\w+/i, "The user's login"
99
+ end
100
+
101
+ @app.parameters.should have( 1 ).member
102
+ @app.parameters[ :username ].should include( :required => false )
103
+ @app.parameters[ :username ].should include( :constraint => /(?<username>(?i-mx:\w+))/ )
104
+ @app.parameters[ :username ].should include( :description => "The user's login" )
105
+ end
106
+
107
+ it "can declare a parameter with an Array validation and a description" do
108
+ @app.class_eval do
109
+ param :username, ['johnny5', 'ariel', 'hotah'], "The user's login"
110
+ end
111
+
112
+ @app.parameters.should have( 1 ).member
113
+ @app.parameters[ :username ].
114
+ should include( :constraint => ['johnny5', 'ariel', 'hotah'] )
115
+ @app.parameters[ :username ].should include( :description => "The user's login" )
116
+ end
117
+
118
+ it "can declare a parameter with just a description" do
119
+ @app.class_eval do
120
+ param :uuid, "UUID string"
121
+ end
122
+
123
+ @app.parameters.should have( 1 ).member
124
+ @app.parameters[ :uuid ].should include( :description => "UUID string" )
125
+ @app.parameters[ :uuid ].should include( :constraint => :uuid )
126
+ end
127
+
128
+ it "can declare a parameter with a validation pattern and a flag" do
129
+ @app.class_eval do
130
+ param :username, /\w+/i, :untaint
131
+ end
132
+
133
+ @app.parameters.should have( 1 ).member
134
+ @app.parameters[ :username ].should include( :required => false )
135
+ @app.parameters[ :username ].should include( :untaint => true )
136
+ @app.parameters[ :username ].should include( :constraint => /(?<username>(?i-mx:\w+))/ )
137
+ @app.parameters[ :username ].should include( :description => nil )
138
+ end
139
+
140
+ it "can declare a parameter with a validation Array and a flag" do
141
+ @app.class_eval do
142
+ param :username, ['amhel', 'hotah', 'aurelii'], :required
143
+ end
144
+
145
+ @app.parameters.should have( 1 ).member
146
+ @app.parameters[ :username ].should include( :required => true )
147
+ @app.parameters[ :username ].
148
+ should include( :constraint => ['amhel', 'hotah', 'aurelii'] )
149
+ @app.parameters[ :username ].should include( :description => nil )
150
+ end
151
+
59
152
  it "inherits parameters from its superclass" do
60
153
  @app.class_eval do
61
154
  param :username, /\w+/i
@@ -67,6 +160,62 @@ describe Strelka::App::Parameters do
67
160
  should include( :constraint => /(?<username>(?i-mx:\w+))/ )
68
161
  end
69
162
 
163
+ describe "instance" do
164
+
165
+ before( :each ) do
166
+ @app.class_eval do
167
+ param :username, /\w+/, :required
168
+ param :id, /\d+/
169
+ end
170
+ end
171
+
172
+ it "gets requests that have had their parameters replaced with a validator" do
173
+ req = @request_factory.get( '/user/search' )
174
+ @app.new.handle( req )
175
+
176
+ req.params.should be_a( Strelka::App::ParamValidator )
177
+ req.params.should have_errors()
178
+ req.params.error_messages.should == ["Missing value for 'Username'"]
179
+ end
180
+
181
+ it "validates parameters from the request" do
182
+ req = @request_factory.get( '/user/search?username=anheptoh'.taint )
183
+ @app.new.handle( req )
184
+
185
+ req.params.should be_a( Strelka::App::ParamValidator )
186
+ req.params.should be_okay()
187
+ req.params.should_not have_errors()
188
+ req.params[:username].should == 'anheptoh'
189
+ req.params[:username].should be_tainted()
190
+ end
191
+
192
+ it "untaints all parameters if global untainting is enabled" do
193
+ @app.class_eval do
194
+ untaint_all_constraints true
195
+ end
196
+
197
+ @app.untaint_all_constraints.should be_true()
198
+ req = @request_factory.get( '/user/search?username=shereshnaheth'.taint )
199
+ @app.new.handle( req )
200
+
201
+ req.params[:username].should == 'shereshnaheth'
202
+ req.params[:username].should_not be_tainted()
203
+ end
204
+
205
+ it "untaints parameters flagged for untainting" do
206
+ @app.class_eval do
207
+ param :message, :printable, :untaint
208
+ end
209
+
210
+ req = @request_factory.get( '/user/search?message=I+love+the+circus.'.taint )
211
+ @app.new.handle( req )
212
+
213
+ req.params[:message].should_not be_tainted()
214
+ req.params[:message].should == 'I love the circus.'
215
+ end
216
+
217
+ end
218
+
70
219
  end
71
220
 
72
221