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
@@ -40,7 +40,10 @@ module Strelka::Logging
40
40
  end
41
41
 
42
42
  mod.default_logger = mod.logger = Logger.new( $stderr )
43
- mod.default_logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
43
+ mod.default_logger.level = case
44
+ when $DEBUG then Logger::DEBUG
45
+ when $VERBOSE then Logger::INFO
46
+ else Logger::WARN end
44
47
  mod.default_log_formatter = Strelka::Logging::Formatter.new( mod.default_logger )
45
48
  end
46
49
 
@@ -137,6 +137,59 @@ module Strelka
137
137
 
138
138
  end # module ANSIColorUtilities
139
139
 
140
+
141
+ # Hides your class's ::new method and adds a +pure_virtual+ method generator for
142
+ # defining API methods. If subclasses of your class don't provide implementations of
143
+ # "pure_virtual" methods, NotImplementedErrors will be raised if they are called.
144
+ #
145
+ # # AbstractClass
146
+ # class MyBaseClass
147
+ # include Strelka::AbstractClass
148
+ #
149
+ # # Define a method that will raise a NotImplementedError if called
150
+ # pure_virtual :api_method
151
+ # end
152
+ #
153
+ module AbstractClass
154
+
155
+ ### Methods to be added to including classes
156
+ module ClassMethods
157
+
158
+ ### Define one or more "virtual" methods which will raise
159
+ ### NotImplementedErrors when called via a concrete subclass.
160
+ def pure_virtual( *syms )
161
+ syms.each do |sym|
162
+ define_method( sym ) do |*args|
163
+ raise ::NotImplementedError,
164
+ "%p does not provide an implementation of #%s" % [ self.class, sym ],
165
+ caller(1)
166
+ end
167
+ end
168
+ end
169
+
170
+
171
+ ### Turn subclasses' new methods back to public.
172
+ def inherited( subclass )
173
+ subclass.module_eval { public_class_method :new }
174
+ super
175
+ end
176
+
177
+ end # module ClassMethods
178
+
179
+
180
+ ### Inclusion callback
181
+ def self::included( mod )
182
+ super
183
+ if mod.respond_to?( :new )
184
+ mod.extend( ClassMethods )
185
+ mod.module_eval { private_class_method :new }
186
+ end
187
+ end
188
+
189
+
190
+ end # module AbstractClass
191
+
192
+
140
193
  end # module Strelka
141
194
 
142
195
  # vim: set nosta noet ts=4 sw=4:
data/lib/strelka.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'mongrel2'
4
4
  require 'configurability'
5
+ require 'configurability/config'
5
6
 
6
7
  # An application framework for Ruby-mongrel2
7
8
  #
@@ -15,15 +16,21 @@ module Strelka
15
16
  VERSION = '0.0.1'
16
17
 
17
18
  # Version-control revision constant
18
- REVISION = %q$Revision: 1e34f33f76af $
19
+ REVISION = %q$Revision: dd54849bf817 $
19
20
 
20
21
 
21
22
  require 'strelka/logging'
22
23
  extend Strelka::Logging
23
24
 
25
+ # Combine Strelka, Mongrel2, and Configurability logging
26
+ Mongrel2.logger = Strelka.logger
27
+ Configurability.logger = Strelka.logger
28
+
24
29
  require 'strelka/constants'
25
30
  include Strelka::Constants
26
31
 
32
+ require 'strelka/exceptions'
33
+
27
34
 
28
35
  ### Get the library version. If +include_buildnum+ is true, the version string will
29
36
  ### include the VCS rev ID.
@@ -36,5 +43,19 @@ module Strelka
36
43
  require 'strelka/app'
37
44
  require 'strelka/httprequest'
38
45
 
46
+
47
+ # The installed Configurability::Config object
48
+ @config = nil
49
+ class << self; attr_accessor :config; end
50
+
51
+
52
+ ### Convenience method -- Load the Configurability::Config from +configfile+
53
+ ### and install it.
54
+ def self::load_config( configfile, defaults={} )
55
+ Strelka.log.info "Loading universal config from %p" % [ configfile ]
56
+ self.config = Configurability::Config.load( configfile, defaults )
57
+ self.config.install
58
+ end
59
+
39
60
  end # module Strelka
40
61
 
@@ -0,0 +1 @@
1
+ This is an error-handler template. The request is: <?pp request ?>.
@@ -20,7 +20,6 @@ module Strelka::TestConstants # :nodoc:all
20
20
  TEST_RECV_SPEC = 'tcp://127.0.0.1:9997'
21
21
 
22
22
 
23
-
24
23
  # Freeze all testing constants
25
24
  constants.each do |cname|
26
25
  const_get(cname).freeze
data/spec/lib/helpers.rb CHANGED
@@ -112,6 +112,27 @@ module Strelka::SpecHelpers
112
112
  end
113
113
  end
114
114
 
115
+ ### Set up a Mongrel2 configuration database according to the specified +dbspec+.
116
+ def setup_config_db( dbspec=':memory:' )
117
+ Mongrel2::Config.configure( :configdb => dbspec ) unless
118
+ Mongrel2::Config.db.uri[ %r{sqlite:/(.*)}, 1 ] == dbspec
119
+ Mongrel2::Config.init_database
120
+ Mongrel2::Config.db.tables.collect {|t| Mongrel2::Config.db[t] }.each( &:truncate )
121
+ end
122
+
123
+
124
+ # Helper method
125
+ def route( name )
126
+ return {:action => name.to_sym}
127
+ end
128
+
129
+ # Route matcher
130
+ RSpec::Matchers.define( :match_route ) do |routename|
131
+ match do |route|
132
+ route[:action] == routename
133
+ end
134
+ end
135
+
115
136
  end
116
137
 
117
138
 
@@ -26,33 +26,34 @@ describe Strelka::App::DefaultRouter do
26
26
  end
27
27
 
28
28
  before( :each ) do
29
- @router = Strelka::App::DefaultRouter.new
29
+ @router = Strelka::App::Router.create( 'default' )
30
30
  end
31
31
 
32
32
  after( :all ) do
33
33
  reset_logging()
34
34
  end
35
35
 
36
+
36
37
  context "a router with routes for 'foo', 'foo/bar'" do
37
38
 
38
39
  before( :each ) do
39
- @router.add_route( :GET, ['foo'], :the_foo_action )
40
- @router.add_route( :GET, ['foo','bar'], :the_foo_bar_action )
40
+ @router.add_route( :GET, ['foo'], route(:foo) )
41
+ @router.add_route( :GET, ['foo','bar'], route(:foo_bar) )
41
42
  end
42
43
 
43
44
  it "routes /user/foo/bar/baz to the foo/bar action" do
44
45
  req = @request_factory.get( '/user/foo/bar/baz' )
45
- @router.route_request( req ).should == :the_foo_bar_action
46
+ @router.route_request( req ).should match_route( :foo_bar )
46
47
  end
47
48
 
48
49
  it "routes /user/foo/bar to the foo/bar action" do
49
50
  req = @request_factory.get( '/user/foo/bar' )
50
- @router.route_request( req ).should == :the_foo_bar_action
51
+ @router.route_request( req ).should match_route( :foo_bar )
51
52
  end
52
53
 
53
54
  it "routes /user/foo to the foo action" do
54
55
  req = @request_factory.get( '/user/foo' )
55
- @router.route_request( req ).should == :the_foo_action
56
+ @router.route_request( req ).should match_route( :foo )
56
57
  end
57
58
 
58
59
  it "doesn't route /user" do
@@ -60,6 +61,11 @@ describe Strelka::App::DefaultRouter do
60
61
  @router.route_request( req ).should be_nil()
61
62
  end
62
63
 
64
+ it "doesn't route /user/something/foo/bar" do
65
+ req = @request_factory.get( '/user/something/foo/bar' )
66
+ @router.route_request( req ).should be_nil()
67
+ end
68
+
63
69
  it "doesn't route /user/other" do
64
70
  req = @request_factory.get( '/user/other' )
65
71
  @router.route_request( req ).should be_nil()
@@ -70,34 +76,34 @@ describe Strelka::App::DefaultRouter do
70
76
  context "a router with routes for 'foo', 'foo/bar', and a fallback action" do
71
77
 
72
78
  before( :each ) do
73
- @router.add_route( :GET, [], :the_fallback_action )
74
- @router.add_route( :GET, ['foo'], :the_foo_action )
75
- @router.add_route( :GET, ['foo','bar'], :the_foo_bar_action )
79
+ @router.add_route( :GET, [], route(:fallback) )
80
+ @router.add_route( :GET, ['foo'], route(:foo) )
81
+ @router.add_route( :GET, ['foo','bar'], route(:foo_bar) )
76
82
  end
77
83
 
78
84
  it "routes /user/foo/bar/baz to the foo/bar action" do
79
85
  req = @request_factory.get( '/user/foo/bar/baz' )
80
- @router.route_request( req ).should == :the_foo_bar_action
86
+ @router.route_request( req ).should match_route( :foo_bar )
81
87
  end
82
88
 
83
89
  it "routes /user/foo/bar to the foo/bar action" do
84
90
  req = @request_factory.get( '/user/foo/bar' )
85
- @router.route_request( req ).should == :the_foo_bar_action
91
+ @router.route_request( req ).should match_route( :foo_bar )
86
92
  end
87
93
 
88
94
  it "routes /user/foo to the foo action" do
89
95
  req = @request_factory.get( '/user/foo' )
90
- @router.route_request( req ).should == :the_foo_action
96
+ @router.route_request( req ).should match_route( :foo )
91
97
  end
92
98
 
93
99
  it "routes /user to the fallback action" do
94
100
  req = @request_factory.get( '/user' )
95
- @router.route_request( req ).should == :the_fallback_action
101
+ @router.route_request( req ).should match_route( :fallback )
96
102
  end
97
103
 
98
104
  it "routes /user/other to the fallback action" do
99
105
  req = @request_factory.get( '/user/other' )
100
- @router.route_request( req ).should == :the_fallback_action
106
+ @router.route_request( req ).should match_route( :fallback )
101
107
  end
102
108
 
103
109
  end
@@ -105,34 +111,34 @@ describe Strelka::App::DefaultRouter do
105
111
  context "a router with routes for 'foo', 'foo/\w{3}', and 'foo/\w{6}'" do
106
112
 
107
113
  before( :each ) do
108
- @router.add_route( :GET, ['foo'], :the_foo_action )
109
- @router.add_route( :GET, ['foo',/\w{3}/], :the_foo_threeaction )
110
- @router.add_route( :GET, ['foo',/\w{6}/], :the_foo_sixaction )
114
+ @router.add_route( :GET, ['foo'], route(:foo) )
115
+ @router.add_route( :GET, ['foo',/\w{3}/], route(:foo_three) )
116
+ @router.add_route( :GET, ['foo',/\w{6}/], route(:foo_six) )
111
117
  end
112
118
 
113
119
  it "routes /user/foo/barbim/baz to the foo/\w{6} action" do
114
120
  req = @request_factory.get( '/user/foo/barbim/baz' )
115
- @router.route_request( req ).should == :the_foo_sixaction
121
+ @router.route_request( req ).should match_route( :foo_six )
116
122
  end
117
123
 
118
124
  it "routes /user/foo/barbat to the foo/\w{6} action" do
119
125
  req = @request_factory.get( '/user/foo/barbat' )
120
- @router.route_request( req ).should == :the_foo_sixaction
126
+ @router.route_request( req ).should match_route( :foo_six )
121
127
  end
122
128
 
123
129
  it "routes /user/foo/bar/baz to the foo/\w{3} action" do
124
130
  req = @request_factory.get( '/user/foo/bar/baz' )
125
- @router.route_request( req ).should == :the_foo_threeaction
131
+ @router.route_request( req ).should match_route( :foo_three )
126
132
  end
127
133
 
128
134
  it "routes /user/foo/bar to the foo/\w{3} action" do
129
135
  req = @request_factory.get( '/user/foo/bar' )
130
- @router.route_request( req ).should == :the_foo_threeaction
136
+ @router.route_request( req ).should match_route( :foo_three )
131
137
  end
132
138
 
133
139
  it "routes /user/foo to the foo action" do
134
140
  req = @request_factory.get( '/user/foo' )
135
- @router.route_request( req ).should == :the_foo_action
141
+ @router.route_request( req ).should match_route( :foo )
136
142
  end
137
143
 
138
144
  it "doesn't route /user" do
@@ -148,33 +154,33 @@ describe Strelka::App::DefaultRouter do
148
154
  end
149
155
 
150
156
  # get '/foo/\w{3}'
151
- # get '/foo/\d+'
157
+ # get '/foo/\d+'
152
158
 
153
159
  context "a router with routes for: 'foo/\w{3}', then 'foo/\d+'" do
154
160
 
155
161
  before( :each ) do
156
- @router.add_route( :GET, ['foo',/\w{3}/], :the_foo_threeaction )
157
- @router.add_route( :GET, ['foo',/\d+/], :the_foo_digitaction )
162
+ @router.add_route( :GET, ['foo',/\w{3}/], route(:foo_three) )
163
+ @router.add_route( :GET, ['foo',/\d+/], route(:foo_digit) )
158
164
  end
159
165
 
160
166
  it "routes /user/foo/1 to the foo/\d+ action" do
161
167
  req = @request_factory.get( '/user/foo/1' )
162
- @router.route_request( req ).should == :the_foo_digitaction
168
+ @router.route_request( req ).should match_route( :foo_digit )
163
169
  end
164
170
 
165
171
  it "routes /user/foo/12 to the foo/\d+ action" do
166
172
  req = @request_factory.get( '/user/foo/12' )
167
- @router.route_request( req ).should == :the_foo_digitaction
173
+ @router.route_request( req ).should match_route( :foo_digit )
168
174
  end
169
175
 
170
176
  it "routes /user/foo/123 to the foo/\w{3} action" do
171
177
  req = @request_factory.get( '/user/foo/123' )
172
- @router.route_request( req ).should == :the_foo_threeaction
178
+ @router.route_request( req ).should match_route( :foo_three )
173
179
  end
174
180
 
175
181
  it "routes /user/foo/1234 to the foo/\d+ action" do
176
182
  req = @request_factory.get( '/user/foo/1234' )
177
- @router.route_request( req ).should == :the_foo_digitaction
183
+ @router.route_request( req ).should match_route( :foo_digit )
178
184
  end
179
185
 
180
186
  end
@@ -185,28 +191,28 @@ describe Strelka::App::DefaultRouter do
185
191
  context "a router with routes for: 'foo/\d+', then 'foo/\w{3}'" do
186
192
 
187
193
  before( :each ) do
188
- @router.add_route( :GET, ['foo',/\d+/], :the_foo_digitaction )
189
- @router.add_route( :GET, ['foo',/\w{3}/], :the_foo_threeaction )
194
+ @router.add_route( :GET, ['foo',/\d+/], route(:foo_digit) )
195
+ @router.add_route( :GET, ['foo',/\w{3}/], route(:foo_three) )
190
196
  end
191
197
 
192
198
  it "routes /user/foo/1 to the foo/\d+ action" do
193
199
  req = @request_factory.get( '/user/foo/1' )
194
- @router.route_request( req ).should == :the_foo_digitaction
200
+ @router.route_request( req ).should match_route( :foo_digit )
195
201
  end
196
202
 
197
203
  it "routes /user/foo/12 to the foo/\d+ action" do
198
204
  req = @request_factory.get( '/user/foo/12' )
199
- @router.route_request( req ).should == :the_foo_digitaction
205
+ @router.route_request( req ).should match_route( :foo_digit )
200
206
  end
201
207
 
202
208
  it "routes /user/foo/123 to the foo/\d+ action" do
203
209
  req = @request_factory.get( '/user/foo/123' )
204
- @router.route_request( req ).should == :the_foo_digitaction
210
+ @router.route_request( req ).should match_route( :foo_digit )
205
211
  end
206
212
 
207
213
  it "routes /user/foo/1234 to the foo/\d+ action" do
208
214
  req = @request_factory.get( '/user/foo/1234' )
209
- @router.route_request( req ).should == :the_foo_digitaction
215
+ @router.route_request( req ).should match_route( :foo_digit )
210
216
  end
211
217
 
212
218
  end
@@ -0,0 +1,212 @@
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
+ require 'inversion'
11
+
12
+ require 'spec/lib/helpers'
13
+
14
+ require 'strelka'
15
+ require 'strelka/app/plugins'
16
+ require 'strelka/app/errors'
17
+
18
+ require 'strelka/behavior/plugin'
19
+
20
+
21
+ #####################################################################
22
+ ### C O N T E X T S
23
+ #####################################################################
24
+
25
+ describe Strelka::App::Errors do
26
+
27
+ before( :all ) do
28
+ setup_logging( :fatal )
29
+ @request_factory = Mongrel2::RequestFactory.new( route: '' )
30
+ end
31
+
32
+ after( :all ) do
33
+ reset_logging()
34
+ end
35
+
36
+
37
+ it_should_behave_like( "A Strelka::App Plugin" )
38
+
39
+
40
+ describe "an including App" do
41
+
42
+ before( :each ) do
43
+ Strelka.log.debug "Creating a new Strelka::App"
44
+ @app = Class.new( Strelka::App ) do
45
+ plugin :errors, :routing
46
+ def initialize( appid='params-test', sspec=TEST_SEND_SPEC, rspec=TEST_RECV_SPEC )
47
+ super
48
+ end
49
+ end
50
+ Strelka.log.debug " new instance is: %p" % [ @app ]
51
+ end
52
+
53
+ it "doesn't alter normal responses" do
54
+ @app.class_eval do
55
+ get do |req|
56
+ res = req.response
57
+ res.puts "Oh yeah! Kool-Aid!"
58
+ res.status = HTTP::OK
59
+ return res
60
+ end
61
+ end
62
+
63
+ req = @request_factory.get( '/koolaid' )
64
+ res = @app.new.handle( req )
65
+
66
+ res.status.should == HTTP::OK
67
+ res.body.should == "Oh yeah! Kool-Aid!\n"
68
+ end
69
+
70
+ it "raises an error if a handler is declared with both a template and a block" do
71
+ expect {
72
+ @app.class_eval do
73
+ on_status 404, :a_template do |*|
74
+ # Wait, what am I DOING?!?!
75
+ end
76
+ end
77
+ }.to raise_error( ArgumentError, /don't take a block/i )
78
+ end
79
+
80
+
81
+ it "raises an error if a template handler is declared but the templating plugin isn't loaded" do
82
+ expect {
83
+ @app.class_eval do
84
+ on_status 404, :a_template
85
+ end
86
+ }.to raise_error( ScriptError, /require the :templating plugin/i )
87
+ end
88
+
89
+ it "uses the fallback status handler if an error is encountered in a custom error handler" do
90
+ @app.class_eval do
91
+ on_status 404 do |*|
92
+ raise "A problem with the custom error-handler"
93
+ end
94
+ end
95
+
96
+ req = @request_factory.get( '/foom' )
97
+ res = @app.new.handle( req )
98
+
99
+ res.body.should =~ /internal server error/i
100
+ end
101
+
102
+ context "instance with a callback-style handler for all error statuses" do
103
+
104
+ before( :each ) do
105
+ @app.class_eval do
106
+ on_status do |res, _|
107
+ res.body = 'Filthy banana'
108
+ return res
109
+ end
110
+
111
+ get do |req|
112
+ finish_with HTTP::BAD_REQUEST, "Your sandwich is missing something."
113
+ end
114
+ end
115
+ end
116
+
117
+
118
+ it "calls the appropriate callback when the response is an error status" do
119
+ req = @request_factory.get( '/foom' )
120
+ res = @app.new.handle( req )
121
+
122
+ res.status.should == HTTP::BAD_REQUEST
123
+ res.body.should == 'Filthy banana'
124
+ end
125
+
126
+ end
127
+
128
+
129
+ context "instance with a callback-style handler for NOT_FOUND" do
130
+
131
+ before( :each ) do
132
+ @app.class_eval do
133
+ on_status HTTP::NOT_FOUND do |res, _|
134
+ res.body = 'NOPE!'
135
+ return res
136
+ end
137
+ end
138
+ end
139
+
140
+
141
+ it "calls the appropriate callback when the response is of the associated status" do
142
+ req = @request_factory.get( '/foom' )
143
+ res = @app.new.handle( req )
144
+
145
+ res.body.should == 'NOPE!'
146
+ end
147
+
148
+ end
149
+
150
+
151
+ context "instance with a callback-style handler for all 400-level statuses" do
152
+
153
+ before( :each ) do
154
+ @app.class_eval do
155
+ on_status 400..499 do |res, _|
156
+ res.body = 'Error: JAMBA'
157
+ return res
158
+ end
159
+ end
160
+ end
161
+
162
+
163
+ it "calls the appropriate callback when the response is of the associated status" do
164
+ req = @request_factory.get( '/foom' )
165
+ res = @app.new.handle( req )
166
+
167
+ res.body.should == 'Error: JAMBA'
168
+ end
169
+
170
+ end
171
+
172
+
173
+ context "instance with a template-style handler for SERVER_ERROR" do
174
+
175
+
176
+ before( :all ) do
177
+ basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
178
+ specdir = basedir + 'spec'
179
+ specdata = specdir + 'data'
180
+
181
+ tmpl_paths = [ specdata ]
182
+ Inversion::Template.configure( :template_paths => tmpl_paths )
183
+ end
184
+
185
+ before( :each ) do
186
+ @app.class_eval do
187
+ plugins :templating, :routing
188
+ templates jamba: 'error.tmpl'
189
+ on_status 500, :jamba
190
+
191
+ get do |req|
192
+ finish_with HTTP::SERVER_ERROR, "I knitted an extra arm for his hopes and dreams."
193
+ end
194
+ end
195
+ end
196
+
197
+
198
+ it "renders the response body using the templating plugin" do
199
+ req = @request_factory.get( '/foom' )
200
+ res = @app.new.handle( req )
201
+
202
+ res.body.should =~ /error-handler template/i
203
+ end
204
+ end
205
+
206
+ end
207
+
208
+
209
+ end
210
+
211
+
212
+