scorched 0.22 → 0.23
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.
- checksums.yaml +4 -4
- data/CHANGES.md +8 -4
- data/Gemfile +1 -1
- data/LICENSE +0 -0
- data/TODO.md +1 -1
- data/examples/restful_controller.ru +51 -0
- data/examples/simple.ru +3 -3
- data/lib/scorched.rb +2 -1
- data/lib/scorched/controller.rb +66 -61
- data/lib/scorched/dynamic_delegate.rb +0 -0
- data/lib/scorched/error.rb +0 -0
- data/lib/scorched/version.rb +2 -2
- data/scorched.gemspec +4 -3
- data/spec/controller_spec.rb +151 -154
- data/spec/options_spec.rb +0 -0
- data/spec/public/static.txt +0 -0
- data/spec/request_spec.rb +0 -0
- data/spec/views/composer.erb +0 -0
- data/spec/views/layout.erb +0 -0
- data/spec/views/main.erb +0 -0
- data/spec/views/other.str +0 -0
- data/spec/views/partial.erb +0 -0
- metadata +35 -21
- data/examples/rails_style_routing.ru +0 -48
File without changes
|
data/lib/scorched/error.rb
CHANGED
File without changes
|
data/lib/scorched/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Scorched
|
2
|
-
VERSION = '0.
|
3
|
-
end
|
2
|
+
VERSION = '0.23'
|
3
|
+
end
|
data/scorched.gemspec
CHANGED
@@ -15,9 +15,10 @@ Gem::Specification.new 'scorched', Scorched::VERSION do |s|
|
|
15
15
|
s.required_ruby_version = '>= 2.0.0'
|
16
16
|
|
17
17
|
s.add_dependency 'rack', '~> 1.4'
|
18
|
-
s.add_dependency 'rack-accept', '~> 0.4'
|
18
|
+
s.add_dependency 'rack-accept', '~> 0.4' # Used for Accept-Charset, Accept-Encoding and Accept-Language headers.
|
19
|
+
s.add_dependency 'scorched-accept', '~> 0.1' # Used for Accept header.
|
19
20
|
s.add_dependency 'tilt', '~> 1.4'
|
20
21
|
s.add_development_dependency 'rack-test', '~> 0.6'
|
21
22
|
s.add_development_dependency 'rspec', '~> 2.9'
|
22
|
-
s.add_development_dependency 'rake', '
|
23
|
-
end
|
23
|
+
s.add_development_dependency 'rake', '~> 10.4'
|
24
|
+
end
|
data/spec/controller_spec.rb
CHANGED
@@ -5,30 +5,30 @@ module Scorched
|
|
5
5
|
let(:generic_handler) do
|
6
6
|
proc { |env| [200, {}, ['ok']] }
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
it "contains a default set of configuration options" do
|
10
10
|
app.config.should be_a(Options)
|
11
11
|
app.config.length.should > 0
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
it "contains a set of default conditions" do
|
15
15
|
app.conditions.should be_a(Options)
|
16
16
|
app.conditions.length.should > 0
|
17
17
|
app.conditions[:method].should be_a(Proc)
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
describe "basic route handling" do
|
21
21
|
it "gracefully handles 404 errors" do
|
22
22
|
response = rt.get '/'
|
23
23
|
response.status.should == 404
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
it "handles a root rack call correctly" do
|
27
27
|
app << {pattern: '/$', target: generic_handler}
|
28
28
|
response = rt.get '/'
|
29
29
|
response.status.should == 200
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
it "does not maintain state between requests" do
|
33
33
|
app << {pattern: '/state', target: proc { |env| [200, {}, [@state = 1 + @state.to_i]] }}
|
34
34
|
response = rt.get '/state'
|
@@ -36,7 +36,7 @@ module Scorched
|
|
36
36
|
response = rt.get '/state'
|
37
37
|
response.body.should == '1'
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
it "raises exception when invalid mapping hash given" do
|
41
41
|
expect {
|
42
42
|
app << {pattern: '/'}
|
@@ -46,14 +46,14 @@ module Scorched
|
|
46
46
|
}.to raise_error(ArgumentError)
|
47
47
|
end
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
describe "URL matching" do
|
51
51
|
it 'always matches from the beginning of the URL' do
|
52
52
|
app << {pattern: 'about', target: generic_handler}
|
53
53
|
response = rt.get '/about'
|
54
54
|
response.status.should == 404
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
it "matches eagerly by default" do
|
58
58
|
req = nil
|
59
59
|
app << {pattern: '/*', target: proc do |env|
|
@@ -62,7 +62,7 @@ module Scorched
|
|
62
62
|
response = rt.get '/about'
|
63
63
|
req.captures.should == ['about']
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
it "can be forced to match end of URL" do
|
67
67
|
app << {pattern: '/about$', target: generic_handler}
|
68
68
|
response = rt.get '/about/us'
|
@@ -71,7 +71,7 @@ module Scorched
|
|
71
71
|
response = rt.get '/about/us'
|
72
72
|
response.status.should == 200
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
it "unescapes all characters except for the forward-slash and percent sign" do
|
76
76
|
app << {pattern: '/a (quite) big fish', target: generic_handler}
|
77
77
|
rt.get('/a%20%28quite%29%20big%20fish').status.should == 200
|
@@ -81,7 +81,7 @@ module Scorched
|
|
81
81
|
rt.get('/page%2Fabout').status.should == 200
|
82
82
|
rt.get('/page/about').status.should == 404
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
it "unmatched path doesn't always begin with a forward slash" do
|
86
86
|
gh = generic_handler
|
87
87
|
app << {pattern: '/ab', target: Class.new(Scorched::Controller) do
|
@@ -91,7 +91,7 @@ module Scorched
|
|
91
91
|
resp.status.should == 200
|
92
92
|
resp.body.should == "ok"
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
it "unmatched path begins with forward slash if last match was up to or included a forward slash" do
|
96
96
|
gh = generic_handler
|
97
97
|
app << {pattern: '/about/', target: Class.new(Scorched::Controller) do
|
@@ -103,7 +103,7 @@ module Scorched
|
|
103
103
|
rt.get('/about/us').body.should == "ok"
|
104
104
|
rt.get('/contact/us').body.should == "ok"
|
105
105
|
end
|
106
|
-
|
106
|
+
|
107
107
|
it "can match anonymous wildcards" do
|
108
108
|
req = nil
|
109
109
|
app << {pattern: '/anon/*/**', target: proc do |env|
|
@@ -112,7 +112,7 @@ module Scorched
|
|
112
112
|
response = rt.get '/anon/jeff/has/crabs'
|
113
113
|
req.captures.should == ['jeff', 'has/crabs']
|
114
114
|
end
|
115
|
-
|
115
|
+
|
116
116
|
it "can match named wildcards (ignoring anonymous captures)" do
|
117
117
|
req = nil
|
118
118
|
app << {pattern: '/anon/:name/*/::infliction', target: proc do |env|
|
@@ -121,7 +121,7 @@ module Scorched
|
|
121
121
|
response = rt.get '/anon/jeff/smith/has/crabs'
|
122
122
|
req.captures.should == {name: 'jeff', infliction: 'has/crabs'}
|
123
123
|
end
|
124
|
-
|
124
|
+
|
125
125
|
example "wildcards match one or more characters" do
|
126
126
|
app << {pattern: '/*', target: proc { |env| [200, {}, ['ok']] }}
|
127
127
|
rt.get('/').status.should == 404
|
@@ -139,7 +139,7 @@ module Scorched
|
|
139
139
|
rt.get('/').status.should == 404
|
140
140
|
rt.get('/dog/cat').status.should == 200
|
141
141
|
end
|
142
|
-
|
142
|
+
|
143
143
|
example "wildcards can optionally match zero or more characters" do
|
144
144
|
app << {pattern: '/*?', target: proc { |env| [200, {}, ['ok']] }}
|
145
145
|
rt.get('/').status.should == 200
|
@@ -157,7 +157,7 @@ module Scorched
|
|
157
157
|
rt.get('/').status.should == 200
|
158
158
|
rt.get('/dog/cat').status.should == 200
|
159
159
|
end
|
160
|
-
|
160
|
+
|
161
161
|
it "can match regex and preserve anonymous captures" do
|
162
162
|
req = nil
|
163
163
|
app << {pattern: %r{/anon/([^/]+)/(.+)}, target: proc do |env|
|
@@ -166,7 +166,7 @@ module Scorched
|
|
166
166
|
response = rt.get '/anon/jeff/has/crabs'
|
167
167
|
req.captures.should == ['jeff', 'has/crabs']
|
168
168
|
end
|
169
|
-
|
169
|
+
|
170
170
|
it "can match regex and preserve named captures (ignoring anonymous captures)" do
|
171
171
|
req = nil
|
172
172
|
app << {pattern: %r{/anon/(?<name>[^/]+)/([^/]+)/(?<infliction>.+)}, target: proc do |env|
|
@@ -175,7 +175,7 @@ module Scorched
|
|
175
175
|
response = rt.get '/anon/jeff/smith/has/crabs'
|
176
176
|
req.captures.should == {name: 'jeff', infliction: 'has/crabs'}
|
177
177
|
end
|
178
|
-
|
178
|
+
|
179
179
|
it "matches routes based on priority, otherwise giving precedence to those defined first" do
|
180
180
|
order = []
|
181
181
|
app << {pattern: '/', priority: -1, target: proc { |env| order << 'four'; [200, {}, ['ok']] }}
|
@@ -185,38 +185,35 @@ module Scorched
|
|
185
185
|
rt.get('/').body.should == 'ok'
|
186
186
|
order.should == %w{one two three four}
|
187
187
|
end
|
188
|
-
|
189
|
-
it "finds the best match for media type whilst respecting priority and definition order" do
|
190
|
-
app << {pattern: '/',
|
191
|
-
|
192
|
-
}}
|
193
|
-
app << {pattern: '/',
|
194
|
-
|
195
|
-
}}
|
196
|
-
app << {pattern: '/', priority: 1, target: proc { |env|
|
197
|
-
[200, {}, ['anything']]
|
198
|
-
}}
|
199
|
-
rt.get('/', media_type: 'application/json, */*;q=0.5').body.should == 'anything'
|
188
|
+
|
189
|
+
it "finds the best match for the media type whilst respecting priority and definition order" do
|
190
|
+
app << {pattern: '/', target: proc { |env| [200, {}, ['anything']] }}
|
191
|
+
app << {pattern: '/', conditions: {media_type: 'application/json'}, target: proc { |env| [200, {}, ['application/json']] }}
|
192
|
+
app << {pattern: '/', conditions: {media_type: 'text/html'}, target: proc { |env| [200, {}, ['text/html']] }}
|
193
|
+
app << {pattern: '/', priority: 1, target: proc { |env| [200, {}, ['anything_high_priority']] }}
|
194
|
+
rt.get('/', {}, 'HTTP_ACCEPT' => 'application/json, */*;q=0.5').body.should == 'anything_high_priority'
|
200
195
|
app.mappings.pop
|
201
|
-
rt.get('/', {}, 'HTTP_ACCEPT' => '
|
202
|
-
rt.get('/', {}, 'HTTP_ACCEPT' => '
|
196
|
+
rt.get('/', {}, 'HTTP_ACCEPT' => 'application/json;q=0.5, text/html').body.should == 'text/html'
|
197
|
+
rt.get('/', {}, 'HTTP_ACCEPT' => 'application/json, */*').body.should == 'application/json'
|
198
|
+
rt.get('/', {}, 'HTTP_ACCEPT' => '*/*, text/*').body.should == 'text/html'
|
199
|
+
rt.get('/', {}, 'HTTP_ACCEPT' => '*/*').body.should == 'anything'
|
203
200
|
end
|
204
201
|
end
|
205
|
-
|
202
|
+
|
206
203
|
describe "conditions" do
|
207
204
|
it "contains a default set of conditions" do
|
208
205
|
app.conditions.should be_a(Options)
|
209
206
|
app.conditions.should include(:method, :media_type)
|
210
207
|
app.conditions.each { |k,v| v.should be_a(Proc) }
|
211
208
|
end
|
212
|
-
|
209
|
+
|
213
210
|
it "executes route only if all conditions return true" do
|
214
211
|
app << {pattern: '/$', conditions: {method: 'POST'}, target: generic_handler}
|
215
212
|
response = rt.get "/"
|
216
213
|
response.status.should be_between(400, 499)
|
217
214
|
response = rt.post "/"
|
218
215
|
response.status.should == 200
|
219
|
-
|
216
|
+
|
220
217
|
app.conditions[:has_name] = proc { |name| request.GET['name'] }
|
221
218
|
app << {pattern: '/about', conditions: {method: ['GET', 'POST'], has_name: 'Ronald'}, target: generic_handler}
|
222
219
|
response = rt.get "/about"
|
@@ -224,28 +221,28 @@ module Scorched
|
|
224
221
|
response = rt.get "/about", name: 'Ronald'
|
225
222
|
response.status.should == 200
|
226
223
|
end
|
227
|
-
|
224
|
+
|
228
225
|
it "raises exception when condition doesn't exist or is invalid" do
|
229
226
|
app << {pattern: '/', conditions: {surprise_christmas_turkey: true}, target: generic_handler}
|
230
227
|
expect {
|
231
228
|
rt.get "/"
|
232
229
|
}.to raise_error(Scorched::Error)
|
233
230
|
end
|
234
|
-
|
231
|
+
|
235
232
|
it "falls through to next route when conditions are not met" do
|
236
233
|
app << {pattern: '/', conditions: {method: 'POST'}, target: proc { |env| [200, {}, ['post']] }}
|
237
234
|
app << {pattern: '/', conditions: {method: 'GET'}, target: proc { |env| [200, {}, ['get']] }}
|
238
235
|
rt.get("/").body.should == 'get'
|
239
236
|
rt.post("/").body.should == 'post'
|
240
237
|
end
|
241
|
-
|
238
|
+
|
242
239
|
it "inverts the conditions if it's referenced with a trailing exclamation mark" do
|
243
240
|
app << {pattern: '/', conditions: {method!: 'GET'}, target: proc { |env| [200, {}, ['ok']] }}
|
244
241
|
rt.get("/").status.should == 405
|
245
242
|
rt.post("/").status.should == 200
|
246
243
|
end
|
247
244
|
end
|
248
|
-
|
245
|
+
|
249
246
|
describe "route helpers" do
|
250
247
|
it "allows end points to be defined more succinctly" do
|
251
248
|
route_proc = app.route('/*', 2, method: 'GET') { |capture| capture }
|
@@ -253,7 +250,7 @@ module Scorched
|
|
253
250
|
mapping.should == {pattern: mapping[:pattern], priority: 2, conditions: {method: 'GET'}, target: route_proc}
|
254
251
|
rt.get('/about').body.should == 'about'
|
255
252
|
end
|
256
|
-
|
253
|
+
|
257
254
|
it "can provide a mapping proc without mapping it" do
|
258
255
|
block = proc { |capture| capture }
|
259
256
|
wrapped_block = app.route(&block)
|
@@ -262,32 +259,32 @@ module Scorched
|
|
262
259
|
app << {pattern: '/*', target: wrapped_block}
|
263
260
|
rt.get('/turkey').body.should == 'turkey'
|
264
261
|
end
|
265
|
-
|
262
|
+
|
266
263
|
it "provides a method for every HTTP method" do
|
267
264
|
[:get, :post, :put, :delete, :options, :head, :patch].each do |m|
|
268
265
|
app.send(m, '/say_cool') { 'cool' }
|
269
266
|
rt.send(m, '/say_cool').body.should == (m == :head ? '' : 'cool')
|
270
267
|
end
|
271
268
|
end
|
272
|
-
|
269
|
+
|
273
270
|
it "provides wildcard captures as arguments" do
|
274
271
|
app.get('/*/**') { |a,b| "#{a} #{b}" }
|
275
272
|
rt.get('/hello/there/dude').body.should == 'hello there/dude'
|
276
273
|
end
|
277
|
-
|
274
|
+
|
278
275
|
it "provides named captures as individual arguments for each value" do
|
279
276
|
app.get('/:given_name') { |a| a }
|
280
277
|
app.get('/:given_name/::surname') { |a,b| "#{a} #{b}" }
|
281
278
|
rt.get('/bob').body.should == 'bob'
|
282
279
|
rt.get('/bob/smith').body.should == 'bob smith'
|
283
280
|
end
|
284
|
-
|
281
|
+
|
285
282
|
it "always matches to the end of the URL (implied $)" do
|
286
283
|
app.get('/') { 'awesome '}
|
287
284
|
rt.get('/dog').status.should == 404
|
288
285
|
rt.get('/').status.should == 200
|
289
286
|
end
|
290
|
-
|
287
|
+
|
291
288
|
it "leaves body empty if nil is returned" do
|
292
289
|
app.get('/') { }
|
293
290
|
app.after do
|
@@ -295,7 +292,7 @@ module Scorched
|
|
295
292
|
end
|
296
293
|
rt.get('/')
|
297
294
|
end
|
298
|
-
|
295
|
+
|
299
296
|
it "can take an array of patterns" do
|
300
297
|
app.get(['/', '/dog']) { 'rad' }
|
301
298
|
rt.get('/dog').status.should == 200
|
@@ -303,7 +300,7 @@ module Scorched
|
|
303
300
|
rt.get('/cat').status.should == 404
|
304
301
|
end
|
305
302
|
end
|
306
|
-
|
303
|
+
|
307
304
|
describe "sub-controllers" do
|
308
305
|
it "should ignore the already matched portions of the path" do
|
309
306
|
app << {pattern: '/article', target: Class.new(Scorched::Controller) do
|
@@ -321,7 +318,7 @@ module Scorched
|
|
321
318
|
'hello'
|
322
319
|
end
|
323
320
|
end
|
324
|
-
|
321
|
+
|
325
322
|
resp = rt.get('/article/name')
|
326
323
|
resp.status.should == 200
|
327
324
|
outer_env['SCRIPT_NAME'].should == ''
|
@@ -329,7 +326,7 @@ module Scorched
|
|
329
326
|
inner_env['SCRIPT_NAME'].should == '/article'
|
330
327
|
inner_env['PATH_INFO'].should == '/name'
|
331
328
|
end
|
332
|
-
|
329
|
+
|
333
330
|
example "PATH_INFO and SCRIPT_NAME joined, should produce a full path" do
|
334
331
|
app.controller '/article/' do
|
335
332
|
get '/name' do
|
@@ -354,7 +351,7 @@ module Scorched
|
|
354
351
|
response.status.should == 200
|
355
352
|
response.body.should == 'hello'
|
356
353
|
end
|
357
|
-
|
354
|
+
|
358
355
|
it "can be given a pattern" do
|
359
356
|
app.controller '/dog' do
|
360
357
|
get('/') { 'roof' }
|
@@ -363,12 +360,12 @@ module Scorched
|
|
363
360
|
response.status.should == 200
|
364
361
|
response.body.should == 'roof'
|
365
362
|
end
|
366
|
-
|
363
|
+
|
367
364
|
it "inherits from parent class, or otherwise the specified class" do
|
368
365
|
app.controller{}.superclass.should == app
|
369
366
|
app.controller('/', String){}.superclass.should == String
|
370
367
|
end
|
371
|
-
|
368
|
+
|
372
369
|
it "can take mapping options" do
|
373
370
|
app.controller priority: -1, conditions: {method: 'POST'} do
|
374
371
|
route('/') { 'ok' }
|
@@ -377,7 +374,7 @@ module Scorched
|
|
377
374
|
rt.get('/').status.should be_between(400, 499)
|
378
375
|
rt.post('/').body.should == 'ok'
|
379
376
|
end
|
380
|
-
|
377
|
+
|
381
378
|
it "automatically passes to the outer controller when no match" do
|
382
379
|
filters_run = 0
|
383
380
|
app.controller do
|
@@ -389,7 +386,7 @@ module Scorched
|
|
389
386
|
rt.get('/').body.should == 'hello'
|
390
387
|
filters_run.should == 0
|
391
388
|
end
|
392
|
-
|
389
|
+
|
393
390
|
it "can be used to map a predefined controller" do
|
394
391
|
person_controller = Class.new(Scorched::Controller) do
|
395
392
|
get('/name') { 'George' }
|
@@ -399,7 +396,7 @@ module Scorched
|
|
399
396
|
end
|
400
397
|
end
|
401
398
|
end
|
402
|
-
|
399
|
+
|
403
400
|
describe "before/after filters" do
|
404
401
|
they "run directly before and after the target action" do
|
405
402
|
order = []
|
@@ -409,7 +406,7 @@ module Scorched
|
|
409
406
|
rt.get('/')
|
410
407
|
order.should == [:before, :action, :after]
|
411
408
|
end
|
412
|
-
|
409
|
+
|
413
410
|
they "run in the context of the controller (same as the route)" do
|
414
411
|
route_instance = nil
|
415
412
|
before_instance = nil
|
@@ -421,7 +418,7 @@ module Scorched
|
|
421
418
|
route_instance.should == before_instance
|
422
419
|
route_instance.should == after_instance
|
423
420
|
end
|
424
|
-
|
421
|
+
|
425
422
|
they "should run even if no route matches" do
|
426
423
|
counter = 0
|
427
424
|
app.before { counter += 1 }
|
@@ -429,7 +426,7 @@ module Scorched
|
|
429
426
|
rt.delete('/').status.should == 404
|
430
427
|
counter.should == 2
|
431
428
|
end
|
432
|
-
|
429
|
+
|
433
430
|
they "can take an optional set of conditions" do
|
434
431
|
counter = 0
|
435
432
|
app.before(method: ['GET', 'PUT']) { counter += 1 }
|
@@ -439,7 +436,7 @@ module Scorched
|
|
439
436
|
rt.put('/')
|
440
437
|
counter.should == 4
|
441
438
|
end
|
442
|
-
|
439
|
+
|
443
440
|
they "execute in the order they're defined" do
|
444
441
|
order = []
|
445
442
|
app.before { order << :first }
|
@@ -449,7 +446,7 @@ module Scorched
|
|
449
446
|
rt.get('/')
|
450
447
|
order.should == %i{first second third fourth}
|
451
448
|
end
|
452
|
-
|
449
|
+
|
453
450
|
describe "nesting" do
|
454
451
|
example "filters inherit but only run once" do
|
455
452
|
before_counter, after_counter = 0, 0
|
@@ -458,18 +455,18 @@ module Scorched
|
|
458
455
|
subcontroller = app.controller { get('/') { 'wow' } }
|
459
456
|
subcontroller.filters[:before].should == app.filters[:before]
|
460
457
|
subcontroller.filters[:after].should == app.filters[:after]
|
461
|
-
|
458
|
+
|
462
459
|
rt.get('/')
|
463
460
|
before_counter.should == 1
|
464
461
|
after_counter.should == 1
|
465
|
-
|
462
|
+
|
466
463
|
# Hitting the subcontroller directly should yield the same results.
|
467
464
|
before_counter, after_counter = 0, 0
|
468
465
|
Rack::Test::Session.new(subcontroller).get('/')
|
469
466
|
before_counter.should == 1
|
470
467
|
after_counter.should == 1
|
471
468
|
end
|
472
|
-
|
469
|
+
|
473
470
|
example "before filters run from outermost to innermost" do
|
474
471
|
order = []
|
475
472
|
app.before { order << :outer }
|
@@ -482,7 +479,7 @@ module Scorched
|
|
482
479
|
rt.get('/')
|
483
480
|
order.should == %i{outer outer2 inner inner2}
|
484
481
|
end
|
485
|
-
|
482
|
+
|
486
483
|
example "after filters run from innermost to outermost" do
|
487
484
|
order = []
|
488
485
|
app.after { order << :outer }
|
@@ -495,7 +492,7 @@ module Scorched
|
|
495
492
|
rt.get('/')
|
496
493
|
order.should == %i{inner inner2 outer outer2}
|
497
494
|
end
|
498
|
-
|
495
|
+
|
499
496
|
example "inherited filters which fail to satisfy their conditions are re-evaluated at every level" do
|
500
497
|
order = []
|
501
498
|
sub_class = app.controller do
|
@@ -518,7 +515,7 @@ module Scorched
|
|
518
515
|
end
|
519
516
|
end
|
520
517
|
end
|
521
|
-
|
518
|
+
|
522
519
|
describe "error filters" do
|
523
520
|
let(:app) do
|
524
521
|
Class.new(Scorched::Controller) do
|
@@ -527,26 +524,26 @@ module Scorched
|
|
527
524
|
end
|
528
525
|
end
|
529
526
|
end
|
530
|
-
|
527
|
+
|
531
528
|
they "catch exceptions" do
|
532
529
|
app.error { response.status = 500 }
|
533
530
|
rt.get('/').status.should == 500
|
534
531
|
end
|
535
|
-
|
532
|
+
|
536
533
|
they "receive the exception object as their first argument" do
|
537
534
|
error = nil
|
538
535
|
app.error { |e| error = e }
|
539
536
|
rt.get('/')
|
540
537
|
error.should be_a(StandardError)
|
541
538
|
end
|
542
|
-
|
539
|
+
|
543
540
|
they "try the next handler if the previous handler returns false" do
|
544
541
|
handlers_called = 0
|
545
542
|
app.error { handlers_called += 1 }
|
546
543
|
app.error { handlers_called += 1 }
|
547
544
|
rt.get '/'
|
548
545
|
handlers_called.should == 1
|
549
|
-
|
546
|
+
|
550
547
|
app.error_filters.clear
|
551
548
|
handlers_called = 0
|
552
549
|
app.error { handlers_called += 1; false }
|
@@ -554,45 +551,45 @@ module Scorched
|
|
554
551
|
rt.get '/'
|
555
552
|
handlers_called.should == 2
|
556
553
|
end
|
557
|
-
|
554
|
+
|
558
555
|
they "still runs after filters if route error is handled" do
|
559
556
|
app.after { response.status = 111 }
|
560
557
|
app.error { true }
|
561
558
|
rt.get('/').status.should == 111
|
562
559
|
end
|
563
|
-
|
560
|
+
|
564
561
|
they "can handle exceptions in before/after filters" do
|
565
562
|
app.error { |e| response.write e.class.name }
|
566
563
|
app.after { raise ArgumentError }
|
567
564
|
rt.get('/').body.should == 'StandardErrorArgumentError'
|
568
565
|
end
|
569
|
-
|
566
|
+
|
570
567
|
they "swallow halts when executed in an outer context" do
|
571
568
|
app.before { raise "Big bad error" }
|
572
569
|
app.error { throw :halt }
|
573
570
|
rt.get('/') # Would otherwise bomb out with uncaught throw.
|
574
571
|
end
|
575
|
-
|
572
|
+
|
576
573
|
they "only get called once per error" do
|
577
574
|
times_called = 0
|
578
575
|
app.error { times_called += 1 }
|
579
576
|
rt.get '/'
|
580
577
|
times_called.should == 1
|
581
578
|
end
|
582
|
-
|
579
|
+
|
583
580
|
they "fall through when unhandled" do
|
584
581
|
expect {
|
585
582
|
rt.get '/'
|
586
583
|
}.to raise_error(StandardError)
|
587
584
|
end
|
588
|
-
|
585
|
+
|
589
586
|
they "can optionally filter on one or more exception types" do
|
590
587
|
app.get('/arg_error') { raise ArgumentError }
|
591
|
-
|
588
|
+
|
592
589
|
app.error(StandardError, ArgumentError) { true }
|
593
590
|
rt.get '/'
|
594
591
|
rt.get '/arg_error'
|
595
|
-
|
592
|
+
|
596
593
|
app.error_filters.clear
|
597
594
|
app.error(ArgumentError) { true }
|
598
595
|
expect {
|
@@ -600,7 +597,7 @@ module Scorched
|
|
600
597
|
}.to raise_error(StandardError)
|
601
598
|
rt.get '/arg_error'
|
602
599
|
end
|
603
|
-
|
600
|
+
|
604
601
|
they "can take an optional set of conditions" do
|
605
602
|
app.error(method: ['GET', 'PUT']) { true }
|
606
603
|
expect {
|
@@ -610,7 +607,7 @@ module Scorched
|
|
610
607
|
rt.put('/')
|
611
608
|
end
|
612
609
|
end
|
613
|
-
|
610
|
+
|
614
611
|
describe "middleware" do
|
615
612
|
let(:app) do
|
616
613
|
Class.new(Scorched::Controller) do
|
@@ -625,56 +622,56 @@ module Scorched
|
|
625
622
|
end
|
626
623
|
end
|
627
624
|
end
|
628
|
-
|
625
|
+
|
629
626
|
it "is only included once by default" do
|
630
627
|
rt.get('/').body.should == '1'
|
631
628
|
rt.get('/sub_controller').body.should == '1'
|
632
629
|
end
|
633
|
-
|
630
|
+
|
634
631
|
it "can be explicitly included more than once in sub-controllers" do
|
635
632
|
app.mappings[-1][:target].middleware << proc { use Scorched::SimpleCounter }
|
636
633
|
rt.get('/').body.should == '1'
|
637
634
|
rt.get('/sub_controller').body.should == '2'
|
638
635
|
end
|
639
636
|
end
|
640
|
-
|
637
|
+
|
641
638
|
describe "halting" do
|
642
639
|
it "short circuits current request" do
|
643
640
|
has_run = false
|
644
641
|
app.get('/') { halt; has_run = true }
|
645
642
|
rt.get '/'
|
646
|
-
has_run.should
|
643
|
+
has_run.should be_falsey
|
647
644
|
end
|
648
|
-
|
645
|
+
|
649
646
|
it "takes an optional status" do
|
650
647
|
app.get('/') { halt 600 }
|
651
648
|
rt.get('/').status.should == 600
|
652
649
|
end
|
653
|
-
|
650
|
+
|
654
651
|
it "takes an optional response body" do
|
655
652
|
app.get('/') { halt 'cool' }
|
656
653
|
rt.get('/').body.should == 'cool'
|
657
654
|
end
|
658
|
-
|
655
|
+
|
659
656
|
it "can take a status and a response body" do
|
660
657
|
app.get('/') { halt 600, 'cool' }
|
661
658
|
rt.get('/').status.should == 600
|
662
659
|
rt.get('/').body.should == 'cool'
|
663
660
|
end
|
664
|
-
|
661
|
+
|
665
662
|
it "still processes filters" do
|
666
663
|
app.after { response.status = 600 }
|
667
664
|
app.get('/') { halt }
|
668
665
|
rt.get('/').status.should == 600
|
669
666
|
end
|
670
|
-
|
667
|
+
|
671
668
|
describe "within filters" do
|
672
669
|
it "short circuits filters if halted within filter" do
|
673
670
|
app.before { halt }
|
674
671
|
app.after { response.status = 600 }
|
675
672
|
rt.get('/').status.should_not == 600
|
676
673
|
end
|
677
|
-
|
674
|
+
|
678
675
|
it "forced filters are always run" do
|
679
676
|
app.before { halt }
|
680
677
|
app.after(force: true) { response.status = 600 }
|
@@ -682,7 +679,7 @@ module Scorched
|
|
682
679
|
app.get('/') { 'hello' }
|
683
680
|
rt.get('/').status.should == 600
|
684
681
|
end
|
685
|
-
|
682
|
+
|
686
683
|
it "halting within a forced filter still runs other forced filters" do
|
687
684
|
app.before { halt }
|
688
685
|
app.before(force: true) { halt }
|
@@ -694,7 +691,7 @@ module Scorched
|
|
694
691
|
end
|
695
692
|
end
|
696
693
|
end
|
697
|
-
|
694
|
+
|
698
695
|
describe 'redirecting' do
|
699
696
|
it "redirects using 303 or 302 by default, depending on HTTP version" do
|
700
697
|
app.get('/cat') { redirect '/dog' }
|
@@ -705,12 +702,12 @@ module Scorched
|
|
705
702
|
response.status.should == 302
|
706
703
|
response.location.should == '/dog'
|
707
704
|
end
|
708
|
-
|
705
|
+
|
709
706
|
it "allows the HTTP status to be overridden" do
|
710
707
|
app.get('/') { redirect '/somewhere', 308 }
|
711
708
|
rt.get('/').status.should == 308
|
712
709
|
end
|
713
|
-
|
710
|
+
|
714
711
|
it "halts the request after redirect" do
|
715
712
|
var = false
|
716
713
|
app.get('/') do
|
@@ -720,7 +717,7 @@ module Scorched
|
|
720
717
|
rt.get('/')
|
721
718
|
var.should == false
|
722
719
|
end
|
723
|
-
|
720
|
+
|
724
721
|
it "works in filters" do
|
725
722
|
app.error { redirect '/somewhere' }
|
726
723
|
app.get('/') { raise "Some error" }
|
@@ -729,7 +726,7 @@ module Scorched
|
|
729
726
|
rt.get('/').location.should == '/somewhere_else'
|
730
727
|
end
|
731
728
|
end
|
732
|
-
|
729
|
+
|
733
730
|
describe "passing" do
|
734
731
|
it "invokes the next match" do
|
735
732
|
app.get('/') { response.body << 'hello'; pass }
|
@@ -738,7 +735,7 @@ module Scorched
|
|
738
735
|
app.get('/') { response.body << '!' } # Shouldn't be hit
|
739
736
|
rt.get('/').body.should == 'hello there sir'
|
740
737
|
end
|
741
|
-
|
738
|
+
|
742
739
|
it "invokes the next match in parent controller if passed from filter" do
|
743
740
|
effects = []
|
744
741
|
app.controller '/sub' do
|
@@ -756,7 +753,7 @@ module Scorched
|
|
756
753
|
rt.get('/sub').body.should == 'y'
|
757
754
|
effects.should == [1, 2]
|
758
755
|
end
|
759
|
-
|
756
|
+
|
760
757
|
it "results in uncaught symbol if passing within filter of root controller " do
|
761
758
|
app.before { pass }
|
762
759
|
expect {
|
@@ -764,36 +761,36 @@ module Scorched
|
|
764
761
|
rt.get('/')
|
765
762
|
}.to raise_error(ArgumentError)
|
766
763
|
end
|
767
|
-
|
764
|
+
|
768
765
|
it "is not considered a match if a mapping passes the request" do
|
769
766
|
app.get('/*') { pass }
|
770
767
|
app.get('/nopass') { }
|
771
768
|
handled = nil
|
772
769
|
app.after { handled = @_handled }
|
773
770
|
rt.get('/').status.should == 404 # 404 if matched, but passed
|
774
|
-
handled.
|
771
|
+
handled.should be_falsey
|
775
772
|
rt.get('/nopass').status.should == 200
|
776
|
-
handled.should
|
773
|
+
handled.should be_truthy
|
777
774
|
end
|
778
775
|
end
|
779
|
-
|
776
|
+
|
780
777
|
describe "status codes" do
|
781
778
|
it "returns 405 when :method condition fails" do
|
782
779
|
app.get('/') { }
|
783
780
|
rt.post('/').status.should == 405
|
784
781
|
end
|
785
|
-
|
782
|
+
|
786
783
|
it "returns 404 when :host condition fails" do
|
787
784
|
app.get('/', host: 'somehost') { }
|
788
785
|
rt.get('/').status.should == 404
|
789
786
|
end
|
790
|
-
|
787
|
+
|
791
788
|
it "returns 406 when accept-related conditions fail" do
|
792
789
|
app.get('/media_type', media_type: 'application/json') { }
|
793
790
|
app.get('/charset', charset: 'iso-8859-5') { }
|
794
791
|
app.get('/encoding', encoding: 'gzip') { }
|
795
792
|
app.get('/language', language: 'en') { }
|
796
|
-
|
793
|
+
|
797
794
|
rt.get('/media_type', {}, 'HTTP_ACCEPT' => 'application/json').status.should == 200
|
798
795
|
rt.get('/media_type', {}, 'HTTP_ACCEPT' => 'text/html').status.should == 406
|
799
796
|
rt.get('/charset', {}, 'HTTP_ACCEPT_CHARSET' => 'iso-8859-5').status.should == 200
|
@@ -804,7 +801,7 @@ module Scorched
|
|
804
801
|
rt.get('/language', {}, 'HTTP_ACCEPT_LANGUAGE' => 'da').status.should == 406
|
805
802
|
end
|
806
803
|
end
|
807
|
-
|
804
|
+
|
808
805
|
describe "configuration" do
|
809
806
|
describe :strip_trailing_slash do
|
810
807
|
it "can be set to strip trailing slash and redirect" do
|
@@ -814,7 +811,7 @@ module Scorched
|
|
814
811
|
response.status.should == 307
|
815
812
|
response['Location'].should == '/test'
|
816
813
|
end
|
817
|
-
|
814
|
+
|
818
815
|
it "can be set to ignore trailing slash while pattern matching" do
|
819
816
|
app.config[:strip_trailing_slash] = :ignore
|
820
817
|
hit = false
|
@@ -822,17 +819,17 @@ module Scorched
|
|
822
819
|
rt.get('/test/').status.should == 200
|
823
820
|
hit.should == true
|
824
821
|
end
|
825
|
-
|
822
|
+
|
826
823
|
it "can be set not do nothing with a trailing slash" do
|
827
824
|
app.config[:strip_trailing_slash] = false
|
828
825
|
app.get('/test') { }
|
829
826
|
rt.get('/test/').status.should == 404
|
830
|
-
|
827
|
+
|
831
828
|
app.get('/test/') { }
|
832
829
|
rt.get('/test/').status.should == 200
|
833
830
|
end
|
834
831
|
end
|
835
|
-
|
832
|
+
|
836
833
|
describe :static_dir do
|
837
834
|
it "can serve static file from the specific directory" do
|
838
835
|
app.config[:static_dir] = 'public'
|
@@ -840,23 +837,23 @@ module Scorched
|
|
840
837
|
response.status.should == 200
|
841
838
|
response.body.should == 'My static file!'
|
842
839
|
end
|
843
|
-
|
840
|
+
|
844
841
|
it "can be disabled" do
|
845
842
|
app.config[:static_dir] = false
|
846
843
|
response = rt.get('/static.txt')
|
847
844
|
response.status.should == 404
|
848
845
|
end
|
849
846
|
end
|
850
|
-
|
847
|
+
|
851
848
|
describe :show_exceptions do
|
852
849
|
it "shows debug-friendly error page for unhandled exceptions" do
|
853
850
|
app.config[:show_exceptions] = true
|
854
851
|
app.get('/') { raise RuntimeError, "Kablamo!" }
|
855
|
-
response = rt.get('/')
|
852
|
+
response = rt.get('/', {}, 'HTTP_ACCEPT' => 'text/html')
|
856
853
|
response.status.should == 500
|
857
854
|
response.body.should include('Rack::ShowExceptions')
|
858
855
|
end
|
859
|
-
|
856
|
+
|
860
857
|
it "can be disabled" do
|
861
858
|
app.config[:show_exceptions] = false
|
862
859
|
app.get('/') { raise RuntimeError, "Kablamo!" }
|
@@ -865,7 +862,7 @@ module Scorched
|
|
865
862
|
}.to raise_error(RuntimeError)
|
866
863
|
end
|
867
864
|
end
|
868
|
-
|
865
|
+
|
869
866
|
describe :show_http_error_pages do
|
870
867
|
it "shows HTTP error pages for errors 400 to 599" do
|
871
868
|
app.config[:show_http_error_pages] = true
|
@@ -875,7 +872,7 @@ module Scorched
|
|
875
872
|
rt.post('/').body.should include('405 Method Not Allowed')
|
876
873
|
rt.get('/unknown').body.should include('480 ')
|
877
874
|
end
|
878
|
-
|
875
|
+
|
879
876
|
it "can be disabled" do
|
880
877
|
app.config[:show_http_error_pages] = false
|
881
878
|
app.get('/') { response.status = 501; '' }
|
@@ -885,7 +882,7 @@ module Scorched
|
|
885
882
|
rt.post('/unknown').body.should_not include('408 ')
|
886
883
|
end
|
887
884
|
end
|
888
|
-
|
885
|
+
|
889
886
|
describe :auto_pass do
|
890
887
|
it "passes to the outer controller without running any filters, if no match" do
|
891
888
|
sub = Class.new(Scorched::Controller) do
|
@@ -900,22 +897,22 @@ module Scorched
|
|
900
897
|
rt.get('/').status.should == 200
|
901
898
|
rt.get('/hello').body.should == 'hello'
|
902
899
|
rt.get('/hello').status.should == 600
|
903
|
-
|
900
|
+
|
904
901
|
sub.config[:auto_pass] = false
|
905
902
|
rt.get('/').body.should == ''
|
906
903
|
rt.get('/').status.should == 600
|
907
904
|
end
|
908
905
|
end
|
909
|
-
|
906
|
+
|
910
907
|
describe :cache_templates do
|
911
908
|
before(:each) do
|
912
909
|
File.open('views/temp.str', 'w') { |f| f.write 'hello world' }
|
913
910
|
end
|
914
|
-
|
911
|
+
|
915
912
|
after(:all) {
|
916
913
|
File.unlink 'views/temp.str'
|
917
914
|
}
|
918
|
-
|
915
|
+
|
919
916
|
it "can cache templates" do
|
920
917
|
app.config[:cache_templates] = true
|
921
918
|
app.get('/') { render :'temp.str' }
|
@@ -923,7 +920,7 @@ module Scorched
|
|
923
920
|
File.open('views/temp.str', 'a') { |f| f.write '!!!' }
|
924
921
|
rt.get('/').body.should == 'hello world'
|
925
922
|
end
|
926
|
-
|
923
|
+
|
927
924
|
it "can be set not to cache templates" do
|
928
925
|
app.config[:cache_templates] = false
|
929
926
|
app.get('/') { render :'temp.str' }
|
@@ -933,7 +930,7 @@ module Scorched
|
|
933
930
|
end
|
934
931
|
end
|
935
932
|
end
|
936
|
-
|
933
|
+
|
937
934
|
describe "sessions" do
|
938
935
|
it "provides convenience method for accessing the Rack session" do
|
939
936
|
rack_session = nil
|
@@ -944,49 +941,49 @@ module Scorched
|
|
944
941
|
rt.get('/')
|
945
942
|
rack_session.should be_a(Rack::Session::Abstract::SessionHash)
|
946
943
|
end
|
947
|
-
|
944
|
+
|
948
945
|
describe "flash" do
|
949
946
|
before(:each) do
|
950
947
|
app.middleware << proc { use Rack::Session::Cookie, secret: 'test' }
|
951
948
|
end
|
952
|
-
|
949
|
+
|
953
950
|
it "keeps session variables that live for one page load" do
|
954
951
|
app.get('/set') { flash[:cat] = 'meow' }
|
955
952
|
app.get('/get') { flash[:cat] }
|
956
|
-
|
953
|
+
|
957
954
|
rt.get('/set')
|
958
955
|
rt.get('/get').body.should == 'meow'
|
959
956
|
rt.get('/get').body.should == ''
|
960
957
|
end
|
961
|
-
|
958
|
+
|
962
959
|
it "always reads from the original request flash" do
|
963
960
|
app.get('/') do
|
964
961
|
flash[:counter] = flash[:counter] ? flash[:counter] + 1 : 0
|
965
962
|
flash[:counter].to_s
|
966
963
|
end
|
967
|
-
|
964
|
+
|
968
965
|
rt.get('/').body.should == ''
|
969
966
|
rt.get('/').body.should == '0'
|
970
967
|
rt.get('/').body.should == '1'
|
971
968
|
end
|
972
|
-
|
969
|
+
|
973
970
|
it "can only remove flash variables if the flash object is accessed" do
|
974
971
|
app.get('/set') { flash[:cat] = 'meow' }
|
975
972
|
app.get('/get') { flash[:cat] }
|
976
973
|
app.get('/null') { }
|
977
|
-
|
974
|
+
|
978
975
|
rt.get('/set')
|
979
976
|
rt.get('/null')
|
980
977
|
rt.get('/get').body.should == 'meow'
|
981
978
|
rt.get('/get').body.should == ''
|
982
979
|
end
|
983
|
-
|
980
|
+
|
984
981
|
it "can keep multiple sets of flash session variables" do
|
985
982
|
app.get('/set_animal') { flash(:animals)[:cat] = 'meow' }
|
986
983
|
app.get('/get_animal') { flash(:animals)[:cat] }
|
987
984
|
app.get('/set_name') { flash(:names)[:jeff] = 'male' }
|
988
985
|
app.get('/get_name') { flash(:names)[:jeff] }
|
989
|
-
|
986
|
+
|
990
987
|
rt.get('/set_animal')
|
991
988
|
rt.get('/set_name')
|
992
989
|
rt.get('/get_animal').body.should == 'meow'
|
@@ -996,7 +993,7 @@ module Scorched
|
|
996
993
|
end
|
997
994
|
end
|
998
995
|
end
|
999
|
-
|
996
|
+
|
1000
997
|
describe "cookie helper" do
|
1001
998
|
it "sets, retrieves and deletes cookies" do
|
1002
999
|
app.get('/') { cookie :test }
|
@@ -1004,7 +1001,7 @@ module Scorched
|
|
1004
1001
|
app.post('/goodbye') { cookie :test, {value: 'goodbye', expires: Time.now() + 999999 } }
|
1005
1002
|
app.delete('/') { cookie :test, nil }
|
1006
1003
|
app.delete('/alt') { cookie :test, {value: nil} }
|
1007
|
-
|
1004
|
+
|
1008
1005
|
rt.get('/').body.should == ''
|
1009
1006
|
rt.post('/')
|
1010
1007
|
rt.get('/').body.should == 'hello'
|
@@ -1016,7 +1013,7 @@ module Scorched
|
|
1016
1013
|
rt.get('/').body.should == ''
|
1017
1014
|
end
|
1018
1015
|
end
|
1019
|
-
|
1016
|
+
|
1020
1017
|
describe "rendering" do
|
1021
1018
|
before(:each) do
|
1022
1019
|
app.render_defaults.each { |k,v| app.render_defaults[k] = nil }
|
@@ -1042,7 +1039,7 @@ module Scorched
|
|
1042
1039
|
end
|
1043
1040
|
rt.get('/')
|
1044
1041
|
end
|
1045
|
-
|
1042
|
+
|
1046
1043
|
it "properly respects absolute and relative file paths in respect to the view directory" do
|
1047
1044
|
app.get('/relative') do
|
1048
1045
|
render(:'../views/main.erb', dir: 'views')
|
@@ -1105,14 +1102,14 @@ module Scorched
|
|
1105
1102
|
end
|
1106
1103
|
rt.get('/').body.should == '({1 for none}{1 for none})'
|
1107
1104
|
end
|
1108
|
-
|
1105
|
+
|
1109
1106
|
it "can pass local variables through to view" do
|
1110
1107
|
app.get '/' do
|
1111
1108
|
render '<%= var %>', engine: 'erb', dir: 'views', locals: {var: 'hello sailor'}
|
1112
1109
|
end
|
1113
1110
|
rt.get('/').body.should == 'hello sailor'
|
1114
1111
|
end
|
1115
|
-
|
1112
|
+
|
1116
1113
|
it "provides a means for passing options directly to tilt" do
|
1117
1114
|
Tilt.register(Class.new(Tilt::ERBTemplate) do
|
1118
1115
|
def prepare
|
@@ -1120,13 +1117,13 @@ module Scorched
|
|
1120
1117
|
super
|
1121
1118
|
end
|
1122
1119
|
end, 'test')
|
1123
|
-
|
1120
|
+
|
1124
1121
|
app.get '/safe' do
|
1125
1122
|
render '<%= var %>', engine: 'test', dir: 'views', locals: {var: 'hello sailor'}
|
1126
1123
|
render '<%= var %>', engine: 'test', dir: 'views', locals: {var: 'hello sailor'}, tilt: {engine: Class.new}
|
1127
1124
|
end
|
1128
1125
|
rt.get('/safe').body.should == 'hello sailor'
|
1129
|
-
|
1126
|
+
|
1130
1127
|
app.get '/boomer' do
|
1131
1128
|
render '<%= var %>', engine: 'test', dir: 'views', locals: {var: 'hello sailor'}, tilt: {engine: 'invalid'}
|
1132
1129
|
end
|
@@ -1135,12 +1132,12 @@ module Scorched
|
|
1135
1132
|
}.to raise_error(NoMethodError)
|
1136
1133
|
end
|
1137
1134
|
end
|
1138
|
-
|
1135
|
+
|
1139
1136
|
describe "url helpers" do
|
1140
1137
|
let(:my_app) do
|
1141
1138
|
Class.new(Scorched::Controller)
|
1142
1139
|
end
|
1143
|
-
|
1140
|
+
|
1144
1141
|
let(:root_app) do
|
1145
1142
|
Class.new(Scorched::Controller)
|
1146
1143
|
end
|
@@ -1152,7 +1149,7 @@ module Scorched
|
|
1152
1149
|
builder.map('/') { run this.root_app }
|
1153
1150
|
builder.to_app
|
1154
1151
|
end
|
1155
|
-
|
1152
|
+
|
1156
1153
|
it "can determine the root path of the current Scorched application" do
|
1157
1154
|
my_app.controller '/article' do
|
1158
1155
|
get '/name' do
|
@@ -1161,26 +1158,26 @@ module Scorched
|
|
1161
1158
|
end
|
1162
1159
|
rt.get('/myapp/article/name').body.should == '/myapp'
|
1163
1160
|
end
|
1164
|
-
|
1161
|
+
|
1165
1162
|
describe "url" do
|
1166
1163
|
it "returns the fully qualified URL" do
|
1167
1164
|
my_app.get('/') { url }
|
1168
1165
|
rt.get('https://scorchedrb.com:73/myapp?something=true').body.should ==
|
1169
1166
|
'https://scorchedrb.com:73/myapp'
|
1170
1167
|
end
|
1171
|
-
|
1168
|
+
|
1172
1169
|
it "can append an optional path" do
|
1173
1170
|
my_app.get('/') { url('hello') }
|
1174
1171
|
rt.get('https://scorchedrb.com:73/myapp?something=true').body.should ==
|
1175
1172
|
'https://scorchedrb.com:73/myapp/hello'
|
1176
1173
|
end
|
1177
|
-
|
1174
|
+
|
1178
1175
|
it "returns the given URL if scheme detected" do
|
1179
1176
|
test_url = 'http://google.com/blah'
|
1180
1177
|
my_app.get('/') { url(test_url) }
|
1181
1178
|
rt.get('/myapp').body.should == test_url
|
1182
1179
|
end
|
1183
|
-
|
1180
|
+
|
1184
1181
|
it "generates URL from inside subcontroller defined with controller helper" do
|
1185
1182
|
root_app.controller '/sub2' do
|
1186
1183
|
get('/') { url('hi') }
|
@@ -1188,29 +1185,29 @@ module Scorched
|
|
1188
1185
|
rt.get('https://scorchedrb.com:73/sub2').body.should == 'https://scorchedrb.com:73/hi'
|
1189
1186
|
end
|
1190
1187
|
end
|
1191
|
-
|
1188
|
+
|
1192
1189
|
describe "absolute" do
|
1193
1190
|
it "returns an absolute URL path" do
|
1194
1191
|
my_app.get('/absolute') { absolute }
|
1195
1192
|
rt.get('http://scorchedrb.com/myapp/absolute?something=true').body.should == '/myapp'
|
1196
1193
|
end
|
1197
|
-
|
1194
|
+
|
1198
1195
|
it "returns a forward slash if script name is the root of the URL path" do
|
1199
1196
|
root_app.get('/') { absolute }
|
1200
1197
|
rt.get('http://scorchedrb.com').body.should == '/'
|
1201
1198
|
end
|
1202
|
-
|
1199
|
+
|
1203
1200
|
it "can append an optional path" do
|
1204
1201
|
my_app.get('/absolute') { absolute('hello') }
|
1205
1202
|
rt.get('http://scorchedrb.com/myapp/absolute?something=true').body.should == '/myapp/hello'
|
1206
1203
|
end
|
1207
|
-
|
1204
|
+
|
1208
1205
|
it "returns the given URL if scheme detected" do
|
1209
1206
|
test_url = 'http://google.com/blah'
|
1210
1207
|
my_app.get('/') { absolute(test_url) }
|
1211
1208
|
rt.get('/myapp').body.should == test_url
|
1212
1209
|
end
|
1213
|
-
|
1210
|
+
|
1214
1211
|
it "returns an absolute URL path for subcontroller defined with controller helper" do
|
1215
1212
|
root_app.controller '/sub2' do
|
1216
1213
|
get('/') { absolute }
|
@@ -1219,7 +1216,7 @@ module Scorched
|
|
1219
1216
|
end
|
1220
1217
|
end
|
1221
1218
|
end
|
1222
|
-
|
1219
|
+
|
1223
1220
|
describe "delegators" do
|
1224
1221
|
it "delegates captures" do
|
1225
1222
|
app.get('/:id') { captures[:id] }
|