sinatra-sinatra 0.9.1.2 → 0.9.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -115,6 +115,22 @@ module Sinatra
115
115
  halt data
116
116
  end
117
117
 
118
+ # The :views_directory, :options, :haml, and :sass options are deprecated.
119
+ def render(engine, template, options={}, locals={}, &bk)
120
+ if options.key?(:views_directory)
121
+ sinatra_warn "The :views_directory option is deprecated; use :views instead."
122
+ options[:views] = options.delete(:views_directory)
123
+ end
124
+ [:options, engine.to_sym].each do |key|
125
+ if options.key?(key)
126
+ sinatra_warn "Passing :#{key} => {} to #{engine} is deprecated; " +
127
+ "merge options directly into hash instead."
128
+ options.merge! options.delete(key)
129
+ end
130
+ end
131
+ super(engine, template, options, locals, &bk)
132
+ end
133
+
118
134
  # Throwing halt with a Symbol and the to_result convention are
119
135
  # deprecated. Override the invoke method to detect those types of return
120
136
  # values.
@@ -0,0 +1,303 @@
1
+ require 'rack/showexceptions'
2
+
3
+ module Sinatra
4
+ class ShowExceptions < Rack::ShowExceptions
5
+ def initialize(app)
6
+ @app = app
7
+ @template = ERB.new(TEMPLATE)
8
+ end
9
+
10
+ def frame_class(frame)
11
+ if frame.filename =~ /lib\/sinatra.*\.rb/
12
+ "framework"
13
+ elsif (defined?(Gem) && frame.filename.include?(Gem.dir)) ||
14
+ frame.filename =~ /\/bin\/(\w+)$/
15
+ "system"
16
+ else
17
+ "app"
18
+ end
19
+ end
20
+
21
+ TEMPLATE = <<HTML
22
+ <!DOCTYPE html>
23
+ <html>
24
+ <head>
25
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
26
+ <title><%=h exception.class %> at <%=h path %></title>
27
+
28
+ <script type="text/javascript">
29
+ //<!--
30
+ function toggle(id) {
31
+ var pre = document.getElementById("pre-" + id);
32
+ var post = document.getElementById("post-" + id);
33
+ var context = document.getElementById("context-" + id);
34
+
35
+ if (pre.style.display == 'block') {
36
+ pre.style.display = 'none';
37
+ post.style.display = 'none';
38
+ context.style.background = "none";
39
+ } else {
40
+ pre.style.display = 'block';
41
+ post.style.display = 'block';
42
+ context.style.background = "#fffed9";
43
+ }
44
+ }
45
+
46
+ function toggleBacktrace(){
47
+ var bt = document.getElementById("backtrace");
48
+ var toggler = document.getElementById("expando");
49
+
50
+ if (bt.className == 'condensed') {
51
+ bt.className = 'expanded';
52
+ toggler.innerHTML = "(condense)";
53
+ } else {
54
+ bt.className = 'condensed';
55
+ toggler.innerHTML = "(expand)";
56
+ }
57
+ }
58
+ //-->
59
+ </script>
60
+
61
+ <style type="text/css" media="screen">
62
+ * {margin: 0; padding: 0; border: 0; outline: 0;}
63
+ div.clear {clear: both;}
64
+ body {background: #EEEEEE; margin: 0; padding: 0;
65
+ font-family: 'Lucida Grande', 'Lucida Sans Unicode',
66
+ 'Garuda';}
67
+ code {font-family: 'Lucida Console', monospace;
68
+ font-size: 12px;}
69
+ li {height: 18px;}
70
+ ul {list-style: none; margin: 0; padding: 0;}
71
+ ol:hover {cursor: pointer;}
72
+ ol li {white-space: pre;}
73
+ #explanation {font-size: 12px; color: #666666;
74
+ margin: 20px 0 0 100px;}
75
+ /* WRAP */
76
+ #wrap {width: 860px; background: #FFFFFF; margin: 0 auto;
77
+ padding: 30px 50px 20px 50px;
78
+ border-left: 1px solid #DDDDDD;
79
+ border-right: 1px solid #DDDDDD;}
80
+ /* HEADER */
81
+ #header {margin: 0 auto 25px auto;}
82
+ #header img {float: left;}
83
+ #header #summary {float: left; margin: 12px 0 0 20px; width:520px;
84
+ font-family: 'Lucida Grande', 'Lucida Sans Unicode';}
85
+ h1 {margin: 0; font-size: 36px; color: #981919;}
86
+ h2 {margin: 0; font-size: 22px; color: #333333;}
87
+ #header ul {margin: 0; font-size: 12px; color: #666666;}
88
+ #header ul li strong{color: #444444;}
89
+ #header ul li {display: inline; padding: 0 10px;}
90
+ #header ul li.first {padding-left: 0;}
91
+ #header ul li.last {border: 0; padding-right: 0;}
92
+ /* BODY */
93
+ #backtrace,
94
+ #get,
95
+ #post,
96
+ #cookies,
97
+ #rack {width: 860px; margin: 0 auto 10px auto;}
98
+ p#nav {float: right; font-size: 14px;}
99
+ /* BACKTRACE */
100
+ a#expando {float: left; padding-left: 5px; color: #666666;
101
+ font-size: 14px; text-decoration: none; cursor: pointer;}
102
+ a#expando:hover {text-decoration: underline;}
103
+ h3 {float: left; width: 100px; margin-bottom: 10px;
104
+ color: #981919; font-size: 14px; font-weight: bold;}
105
+ #nav a {color: #666666; text-decoration: none; padding: 0 5px;}
106
+ #backtrace li.frame-info {background: #f7f7f7; padding-left: 10px;
107
+ font-size: 12px; color: #333333;}
108
+ #backtrace ul {list-style-position: outside; border: 1px solid #E9E9E9;
109
+ border-bottom: 0;}
110
+ #backtrace ol {width: 808px; margin-left: 50px;
111
+ font: 10px 'Lucida Console', monospace; color: #666666;}
112
+ #backtrace ol li {border: 0; border-left: 1px solid #E9E9E9;
113
+ padding: 2px 0;}
114
+ #backtrace ol code {font-size: 10px; color: #555555; padding-left: 5px;}
115
+ #backtrace-ul li {border-bottom: 1px solid #E9E9E9; height: auto;
116
+ padding: 3px 0;}
117
+ #backtrace-ul .code {padding: 6px 0 4px 0;}
118
+ #backtrace.condensed .system,
119
+ #backtrace.condensed .framework {display:none;}
120
+ /* REQUEST DATA */
121
+ p.no-data {padding-top: 2px; font-size: 12px; color: #666666;}
122
+ table.req {width: 760px; text-align: left; font-size: 12px;
123
+ color: #666666; padding: 0; border-spacing: 0;
124
+ border: 1px solid #EEEEEE; border-bottom: 0;
125
+ border-left: 0;}
126
+ table.req tr th {padding: 2px 10px; font-weight: bold;
127
+ background: #F7F7F7; border-bottom: 1px solid #EEEEEE;
128
+ border-left: 1px solid #EEEEEE;}
129
+ table.req tr td {padding: 2px 20px 2px 10px;
130
+ border-bottom: 1px solid #EEEEEE;
131
+ border-left: 1px solid #EEEEEE;}
132
+ /* HIDE PRE/POST CODE AT START */
133
+ .pre-context,
134
+ .post-context {display: none;}
135
+ </style>
136
+ </head>
137
+ <body>
138
+ <div id="wrap">
139
+ <div id="header">
140
+ <img src="/__sinatra__/500.png" alt="application error" />
141
+ <div id="summary">
142
+ <h1><strong><%=h exception.class %></strong> at <strong><%=h path %>
143
+ </strong></h1>
144
+ <h2><%=h exception.message %></h2>
145
+ <ul>
146
+ <li class="first"><strong>file:</strong> <code>
147
+ <%=h frames.first.filename.split("/").last %></code></li>
148
+ <li><strong>location:</strong> <code><%=h frames.first.function %>
149
+ </code></li>
150
+ <li class="last"><strong>line:
151
+ </strong> <%=h frames.first.lineno %></li>
152
+ </ul>
153
+ </div>
154
+ <div class="clear"></div>
155
+ </div>
156
+
157
+ <div id="backtrace" class='condensed'>
158
+ <h3>BACKTRACE</h3>
159
+ <p><a href="#" id="expando"
160
+ onclick="toggleBacktrace(); return false">(expand)</a></p>
161
+ <p id="nav"><strong>JUMP TO:</strong>
162
+ <a href="#get-info">GET</a>
163
+ <a href="#post-info">POST</a>
164
+ <a href="#cookie-info">COOKIES</a>
165
+ <a href="#env-info">ENV</a>
166
+ </p>
167
+ <div class="clear"></div>
168
+
169
+ <ul id="backtrace-ul">
170
+
171
+ <% id = 1 %>
172
+ <% frames.each do |frame| %>
173
+ <% if frame.context_line && frame.context_line != "#" %>
174
+
175
+ <li class="frame-info <%= frame_class(frame) %>">
176
+ <code><%=h frame.filename %></code> in
177
+ <code><strong><%=h frame.function %></strong></code>
178
+ </li>
179
+
180
+ <li class="code <%= frame_class(frame) %>">
181
+ <% if frame.pre_context %>
182
+ <ol start="<%=h frame.pre_context_lineno + 1 %>"
183
+ class="pre-context" id="pre-<%= id %>"
184
+ onclick="toggle(<%= id %>);">
185
+ <% frame.pre_context.each do |line| %>
186
+ <li class="pre-context-line"><code><%=h line %></code></li>
187
+ <% end %>
188
+ </ol>
189
+ <% end %>
190
+
191
+ <ol start="<%= frame.lineno %>" class="context" id="<%= id %>"
192
+ onclick="toggle(<%= id %>);">
193
+ <li class="context-line" id="context-<%= id %>"><code><%=
194
+ h frame.context_line %></code></li>
195
+ </ol>
196
+
197
+ <% if frame.post_context %>
198
+ <ol start="<%=h frame.lineno + 1 %>" class="post-context"
199
+ id="post-<%= id %>" onclick="toggle(<%= id %>);">
200
+ <% frame.post_context.each do |line| %>
201
+ <li class="post-context-line"><code><%=h line %></code></li>
202
+ <% end %>
203
+ </ol>
204
+ <% end %>
205
+ <div class="clear"></div>
206
+ </li>
207
+
208
+ <% end %>
209
+
210
+ <% id += 1 %>
211
+ <% end %>
212
+
213
+ </ul>
214
+ </div> <!-- /BACKTRACE -->
215
+
216
+ <div id="get">
217
+ <h3 id="get-info">GET</h3>
218
+ <% unless req.GET.empty? %>
219
+ <table class="req">
220
+ <tr>
221
+ <th>Variable</th>
222
+ <th>Value</th>
223
+ </tr>
224
+ <% req.GET.sort_by { |k, v| k.to_s }.each { |key, val| %>
225
+ <tr>
226
+ <td><%=h key %></td>
227
+ <td class="code"><div><%=h val.inspect %></div></td>
228
+ </tr>
229
+ <% } %>
230
+ </table>
231
+ <% else %>
232
+ <p class="no-data">No GET data.</p>
233
+ <% end %>
234
+ <div class="clear"></div>
235
+ </div> <!-- /GET -->
236
+
237
+ <div id="post">
238
+ <h3 id="post-info">POST</h3>
239
+ <% unless req.POST.empty? %>
240
+ <table class="req">
241
+ <tr>
242
+ <th>Variable</th>
243
+ <th>Value</th>
244
+ </tr>
245
+ <% req.POST.sort_by { |k, v| k.to_s }.each { |key, val| %>
246
+ <tr>
247
+ <td><%=h key %></td>
248
+ <td class="code"><div><%=h val.inspect %></div></td>
249
+ </tr>
250
+ <% } %>
251
+ </table>
252
+ <% else %>
253
+ <p class="no-data">No POST data.</p>
254
+ <% end %>
255
+ <div class="clear"></div>
256
+ </div> <!-- /POST -->
257
+
258
+ <div id="cookies">
259
+ <h3 id="cookie-info">COOKIES</h3>
260
+ <% unless req.cookies.empty? %>
261
+ <table class="req">
262
+ <tr>
263
+ <th>Variable</th>
264
+ <th>Value</th>
265
+ </tr>
266
+ <% req.cookies.each { |key, val| %>
267
+ <tr>
268
+ <td><%=h key %></td>
269
+ <td class="code"><div><%=h val.inspect %></div></td>
270
+ </tr>
271
+ <% } %>
272
+ </table>
273
+ <% else %>
274
+ <p class="no-data">No cookie data.</p>
275
+ <% end %>
276
+ <div class="clear"></div>
277
+ </div> <!-- /COOKIES -->
278
+
279
+ <div id="rack">
280
+ <h3 id="env-info">Rack ENV</h3>
281
+ <table class="req">
282
+ <tr>
283
+ <th>Variable</th>
284
+ <th>Value</th>
285
+ </tr>
286
+ <% env.sort_by { |k, v| k.to_s }.each { |key, val| %>
287
+ <tr>
288
+ <td><%=h key %></td>
289
+ <td class="code"><div><%=h val %></div></td>
290
+ </tr>
291
+ <% } %>
292
+ </table>
293
+ <div class="clear"></div>
294
+ </div> <!-- /RACK ENV -->
295
+
296
+ <p id="explanation">You're seeing this error because you use you have
297
+ enabled the <code>show_exceptions</code> option.</p>
298
+ </div> <!-- /WRAP -->
299
+ </body>
300
+ </html>
301
+ HTML
302
+ end
303
+ end
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
3
3
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
4
 
5
5
  s.name = 'sinatra'
6
- s.version = '0.9.1.2'
7
- s.date = '2009-03-24'
6
+ s.version = '0.9.1.3'
7
+ s.date = '2009-04-25'
8
8
 
9
9
  s.description = "Classy web-development dressed in a DSL"
10
10
  s.summary = "Classy web-development dressed in a DSL"
@@ -60,6 +60,7 @@ Gem::Specification.new do |s|
60
60
  lib/sinatra/images/404.png
61
61
  lib/sinatra/images/500.png
62
62
  lib/sinatra/main.rb
63
+ lib/sinatra/showexceptions.rb
63
64
  lib/sinatra/test.rb
64
65
  lib/sinatra/test/bacon.rb
65
66
  lib/sinatra/test/rspec.rb
@@ -68,6 +69,7 @@ Gem::Specification.new do |s|
68
69
  sinatra.gemspec
69
70
  test/base_test.rb
70
71
  test/builder_test.rb
72
+ test/contest.rb
71
73
  test/data/reload_app_file.rb
72
74
  test/erb_test.rb
73
75
  test/extensions_test.rb
@@ -78,9 +80,11 @@ Gem::Specification.new do |s|
78
80
  test/mapped_error_test.rb
79
81
  test/middleware_test.rb
80
82
  test/options_test.rb
83
+ test/render_backtrace_test.rb
81
84
  test/request_test.rb
82
85
  test/response_test.rb
83
86
  test/result_test.rb
87
+ test/route_added_hook_test.rb
84
88
  test/routing_test.rb
85
89
  test/sass_test.rb
86
90
  test/server_test.rb
@@ -88,6 +92,10 @@ Gem::Specification.new do |s|
88
92
  test/static_test.rb
89
93
  test/templates_test.rb
90
94
  test/test_test.rb
95
+ test/views/error.builder
96
+ test/views/error.erb
97
+ test/views/error.haml
98
+ test/views/error.sass
91
99
  test/views/hello.builder
92
100
  test/views/hello.erb
93
101
  test/views/hello.haml
@@ -103,7 +111,7 @@ Gem::Specification.new do |s|
103
111
  s.test_files = s.files.select {|path| path =~ /^test\/.*_test.rb/}
104
112
 
105
113
  s.extra_rdoc_files = %w[README.rdoc LICENSE]
106
- s.add_dependency 'rack', '>= 0.9.1', '< 1.0'
114
+ s.add_dependency 'rack', '>= 0.9.1'
107
115
  s.add_development_dependency 'shotgun', '>= 0.2', '< 1.0'
108
116
 
109
117
  s.has_rdoc = true
@@ -1,139 +1,155 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
2
 
3
- describe 'Sinatra::Base subclasses' do
3
+ class BaseTest < Test::Unit::TestCase
4
+ describe 'Sinatra::Base subclasses' do
5
+ class TestApp < Sinatra::Base
6
+ get '/' do
7
+ 'Hello World'
8
+ end
9
+ end
4
10
 
5
- class TestApp < Sinatra::Base
6
- get '/' do
7
- 'Hello World'
11
+ it 'include Rack::Utils' do
12
+ assert TestApp.included_modules.include?(Rack::Utils)
8
13
  end
9
- end
10
14
 
11
- it 'include Rack::Utils' do
12
- assert TestApp.included_modules.include?(Rack::Utils)
13
- end
15
+ it 'processes requests with #call' do
16
+ assert TestApp.respond_to?(:call)
14
17
 
15
- it 'processes requests with #call' do
16
- assert TestApp.respond_to?(:call)
18
+ request = Rack::MockRequest.new(TestApp)
19
+ response = request.get('/')
20
+ assert response.ok?
21
+ assert_equal 'Hello World', response.body
22
+ end
17
23
 
18
- request = Rack::MockRequest.new(TestApp)
19
- response = request.get('/')
20
- assert response.ok?
21
- assert_equal 'Hello World', response.body
22
- end
24
+ class TestApp < Sinatra::Base
25
+ get '/state' do
26
+ body = "Foo: #{@foo}"
27
+ @foo = 'discard'
28
+ body
29
+ end
30
+ end
23
31
 
24
- class TestApp < Sinatra::Base
25
- get '/state' do
26
- body = "Foo: #{@foo}"
27
- @foo = 'discard'
28
- body
32
+ it 'does not maintain state between requests' do
33
+ request = Rack::MockRequest.new(TestApp)
34
+ 2.times do
35
+ response = request.get('/state')
36
+ assert response.ok?
37
+ assert_equal 'Foo: ', response.body
38
+ end
29
39
  end
30
- end
31
40
 
32
- it 'does not maintain state between requests' do
33
- request = Rack::MockRequest.new(TestApp)
34
- 2.times do
35
- response = request.get('/state')
36
- assert response.ok?
37
- assert_equal 'Foo: ', response.body
41
+ it "passes the subclass to configure blocks" do
42
+ ref = nil
43
+ TestApp.configure { |app| ref = app }
44
+ assert_equal TestApp, ref
45
+ end
46
+
47
+ it "allows the configure block arg to be omitted and does not change context" do
48
+ context = nil
49
+ TestApp.configure { context = self }
50
+ assert_equal self, context
38
51
  end
39
52
  end
40
- end
41
53
 
42
- describe "Sinatra::Base as Rack middleware" do
54
+ describe "Sinatra::Base as Rack middleware" do
55
+ app = lambda { |env|
56
+ headers = {'X-Downstream' => 'true'}
57
+ headers['X-Route-Missing'] = env['sinatra.route-missing'] || ''
58
+ [210, headers, ['Hello from downstream']] }
43
59
 
44
- app = lambda { |env|
45
- [210, {'X-Downstream' => 'true', 'X-Bypass-Test' => '1' || ''}, ['Hello from downstream']] }
60
+ class TestMiddleware < Sinatra::Base
61
+ end
46
62
 
47
- class TestMiddleware < Sinatra::Base
48
- end
63
+ it 'creates a middleware that responds to #call with .new' do
64
+ middleware = TestMiddleware.new(app)
65
+ assert middleware.respond_to?(:call)
66
+ end
49
67
 
50
- it 'creates a middleware that responds to #call with .new' do
51
- middleware = TestMiddleware.new(app)
52
- assert middleware.respond_to?(:call)
53
- end
68
+ it 'exposes the downstream app' do
69
+ middleware = TestMiddleware.new(app)
70
+ assert_same app, middleware.app
71
+ end
54
72
 
55
- it 'exposes the downstream app' do
56
- middleware = TestMiddleware.new(app)
57
- assert_same app, middleware.app
58
- end
73
+ class TestMiddleware < Sinatra::Base
74
+ def route_missing
75
+ env['sinatra.route-missing'] = '1'
76
+ super
77
+ end
59
78
 
60
- class TestMiddleware < Sinatra::Base
61
- def bypassed
62
- env['X-Bypass-Test'] = '1'
79
+ get '/' do
80
+ 'Hello from middleware'
81
+ end
63
82
  end
64
83
 
65
- get '/' do
66
- 'Hello from middleware'
67
- end
68
- end
84
+ middleware = TestMiddleware.new(app)
85
+ request = Rack::MockRequest.new(middleware)
69
86
 
70
- middleware = TestMiddleware.new(app)
71
- request = Rack::MockRequest.new(middleware)
87
+ it 'intercepts requests' do
88
+ response = request.get('/')
89
+ assert response.ok?
90
+ assert_equal 'Hello from middleware', response.body
91
+ end
72
92
 
73
- it 'intercepts requests' do
74
- response = request.get('/')
75
- assert response.ok?
76
- assert_equal 'Hello from middleware', response.body
77
- end
93
+ it 'automatically forwards requests downstream when no matching route found' do
94
+ response = request.get('/missing')
95
+ assert_equal 210, response.status
96
+ assert_equal 'Hello from downstream', response.body
97
+ end
78
98
 
79
- it 'automatically forwards requests downstream when no matching route found' do
80
- response = request.get('/missing')
81
- assert_equal 210, response.status
82
- assert_equal 'Hello from downstream', response.body
83
- end
99
+ it 'calls #route_missing before forwarding downstream' do
100
+ response = request.get('/missing')
101
+ assert_equal '1', response['X-Route-Missing']
102
+ end
84
103
 
85
- it 'calls #bypassed before forwarding downstream' do
86
- response = request.get('/missing')
87
- assert_equal '1', response['X-Bypass-Test']
88
- end
104
+ class TestMiddleware < Sinatra::Base
105
+ get '/low-level-forward' do
106
+ app.call(env)
107
+ end
108
+ end
89
109
 
90
- class TestMiddleware < Sinatra::Base
91
- get '/low-level-forward' do
92
- app.call(env)
110
+ it 'can call the downstream app directly and return result' do
111
+ response = request.get('/low-level-forward')
112
+ assert_equal 210, response.status
113
+ assert_equal 'true', response['X-Downstream']
114
+ assert_equal 'Hello from downstream', response.body
93
115
  end
94
- end
95
116
 
96
- it 'can call the downstream app directly and return result' do
97
- response = request.get('/low-level-forward')
98
- assert_equal 210, response.status
99
- assert_equal 'true', response['X-Downstream']
100
- assert_equal 'Hello from downstream', response.body
101
- end
117
+ class TestMiddleware < Sinatra::Base
118
+ get '/explicit-forward' do
119
+ response['X-Middleware'] = 'true'
120
+ res = forward
121
+ assert_nil res
122
+ assert_equal 210, response.status
123
+ assert_equal 'true', response['X-Downstream']
124
+ assert_equal ['Hello from downstream'], response.body
125
+ 'Hello after explicit forward'
126
+ end
127
+ end
102
128
 
103
- class TestMiddleware < Sinatra::Base
104
- get '/explicit-forward' do
105
- response['X-Middleware'] = 'true'
106
- res = forward
107
- assert_nil res
129
+ it 'forwards the request downstream and integrates the response into the current context' do
130
+ response = request.get('/explicit-forward')
108
131
  assert_equal 210, response.status
109
132
  assert_equal 'true', response['X-Downstream']
110
- assert_equal ['Hello from downstream'], response.body
111
- 'Hello after explicit forward'
133
+ assert_equal 'Hello after explicit forward', response.body
134
+ assert_equal '28', response['Content-Length']
112
135
  end
113
- end
114
136
 
115
- it 'forwards the request downstream and integrates the response into the current context' do
116
- response = request.get('/explicit-forward')
117
- assert_equal 210, response.status
118
- assert_equal 'true', response['X-Downstream']
119
- assert_equal 'Hello after explicit forward', response.body
120
- assert_equal '28', response['Content-Length']
121
- end
137
+ app_content_length = lambda {|env|
138
+ [200, {'Content-Length' => '16'}, 'From downstream!']}
122
139
 
123
- app_content_length = lambda {|env|
124
- [200, {'Content-Length' => '16'}, 'From downstream!']}
125
- class TestMiddlewareContentLength < Sinatra::Base
126
- get '/forward' do
127
- res = forward
128
- 'From after explicit forward!'
140
+ class TestMiddlewareContentLength < Sinatra::Base
141
+ get '/forward' do
142
+ res = forward
143
+ 'From after explicit forward!'
144
+ end
129
145
  end
130
- end
131
146
 
132
- middleware_content_length = TestMiddlewareContentLength.new(app_content_length)
133
- request_content_length = Rack::MockRequest.new(middleware_content_length)
147
+ middleware_content_length = TestMiddlewareContentLength.new(app_content_length)
148
+ request_content_length = Rack::MockRequest.new(middleware_content_length)
134
149
 
135
- it "sets content length for last response" do
136
- response = request_content_length.get('/forward')
137
- assert_equal '28', response['Content-Length']
150
+ it "sets content length for last response" do
151
+ response = request_content_length.get('/forward')
152
+ assert_equal '28', response['Content-Length']
153
+ end
138
154
  end
139
155
  end