roda 3.28.0 → 3.29.0
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/CHANGELOG +10 -0
- data/README.rdoc +10 -0
- data/doc/release_notes/3.29.0.txt +15 -0
- data/lib/roda.rb +1 -0
- data/lib/roda/plugins/caching.rb +2 -0
- data/lib/roda/plugins/common_logger.rb +1 -1
- data/lib/roda/plugins/exception_page.rb +7 -1
- data/lib/roda/plugins/indifferent_params.rb +2 -0
- data/lib/roda/version.rb +1 -1
- metadata +4 -214
- data/Rakefile +0 -108
- data/doc/release_notes/1.0.0.txt +0 -329
- data/doc/release_notes/1.1.0.txt +0 -226
- data/doc/release_notes/1.2.0.txt +0 -406
- data/doc/release_notes/1.3.0.txt +0 -109
- data/doc/release_notes/2.0.0.txt +0 -75
- data/doc/release_notes/2.1.0.txt +0 -124
- data/doc/release_notes/2.10.0.txt +0 -27
- data/doc/release_notes/2.11.0.txt +0 -70
- data/doc/release_notes/2.12.0.txt +0 -40
- data/doc/release_notes/2.13.0.txt +0 -10
- data/doc/release_notes/2.14.0.txt +0 -44
- data/doc/release_notes/2.15.0.txt +0 -53
- data/doc/release_notes/2.16.0.txt +0 -48
- data/doc/release_notes/2.17.0.txt +0 -62
- data/doc/release_notes/2.18.0.txt +0 -69
- data/doc/release_notes/2.19.0.txt +0 -30
- data/doc/release_notes/2.2.0.txt +0 -97
- data/doc/release_notes/2.20.0.txt +0 -5
- data/doc/release_notes/2.21.0.txt +0 -17
- data/doc/release_notes/2.22.0.txt +0 -41
- data/doc/release_notes/2.23.0.txt +0 -29
- data/doc/release_notes/2.24.0.txt +0 -65
- data/doc/release_notes/2.25.0.txt +0 -14
- data/doc/release_notes/2.26.0.txt +0 -13
- data/doc/release_notes/2.27.0.txt +0 -56
- data/doc/release_notes/2.28.0.txt +0 -17
- data/doc/release_notes/2.29.0.txt +0 -156
- data/doc/release_notes/2.3.0.txt +0 -109
- data/doc/release_notes/2.4.0.txt +0 -55
- data/doc/release_notes/2.5.0.txt +0 -23
- data/doc/release_notes/2.5.1.txt +0 -4
- data/doc/release_notes/2.6.0.txt +0 -21
- data/doc/release_notes/2.7.0.txt +0 -75
- data/doc/release_notes/2.8.0.txt +0 -44
- data/doc/release_notes/2.9.0.txt +0 -6
- data/spec/all.rb +0 -1
- data/spec/assets/css/app.scss +0 -1
- data/spec/assets/css/no_access.css +0 -1
- data/spec/assets/css/raw.css +0 -1
- data/spec/assets/js/head/app.js +0 -1
- data/spec/composition_spec.rb +0 -31
- data/spec/define_roda_method_spec.rb +0 -274
- data/spec/env_spec.rb +0 -11
- data/spec/freeze_spec.rb +0 -37
- data/spec/integration_spec.rb +0 -209
- data/spec/matchers_spec.rb +0 -832
- data/spec/opts_spec.rb +0 -42
- data/spec/plugin/_after_hook_spec.rb +0 -19
- data/spec/plugin/all_verbs_spec.rb +0 -29
- data/spec/plugin/assets_preloading_spec.rb +0 -98
- data/spec/plugin/assets_spec.rb +0 -745
- data/spec/plugin/backtracking_array_spec.rb +0 -42
- data/spec/plugin/branch_locals_spec.rb +0 -106
- data/spec/plugin/caching_spec.rb +0 -337
- data/spec/plugin/chunked_spec.rb +0 -201
- data/spec/plugin/class_level_routing_spec.rb +0 -164
- data/spec/plugin/class_matchers_spec.rb +0 -40
- data/spec/plugin/common_logger_spec.rb +0 -85
- data/spec/plugin/content_for_spec.rb +0 -162
- data/spec/plugin/content_security_policy_spec.rb +0 -175
- data/spec/plugin/cookies_spec.rb +0 -51
- data/spec/plugin/csrf_spec.rb +0 -111
- data/spec/plugin/default_headers_spec.rb +0 -82
- data/spec/plugin/default_status_spec.rb +0 -95
- data/spec/plugin/delay_build_spec.rb +0 -23
- data/spec/plugin/delegate_spec.rb +0 -23
- data/spec/plugin/delete_empty_headers_spec.rb +0 -27
- data/spec/plugin/direct_call_spec.rb +0 -28
- data/spec/plugin/disallow_file_uploads_spec.rb +0 -25
- data/spec/plugin/drop_body_spec.rb +0 -24
- data/spec/plugin/early_hints_spec.rb +0 -19
- data/spec/plugin/empty_root_spec.rb +0 -14
- data/spec/plugin/environments_spec.rb +0 -42
- data/spec/plugin/error_email_spec.rb +0 -97
- data/spec/plugin/error_handler_spec.rb +0 -216
- data/spec/plugin/error_mail_spec.rb +0 -93
- data/spec/plugin/exception_page_spec.rb +0 -168
- data/spec/plugin/flash_spec.rb +0 -121
- data/spec/plugin/h_spec.rb +0 -11
- data/spec/plugin/halt_spec.rb +0 -119
- data/spec/plugin/hash_matcher_spec.rb +0 -27
- data/spec/plugin/hash_routes_spec.rb +0 -535
- data/spec/plugin/head_spec.rb +0 -52
- data/spec/plugin/header_matchers_spec.rb +0 -98
- data/spec/plugin/heartbeat_spec.rb +0 -74
- data/spec/plugin/hooks_spec.rb +0 -152
- data/spec/plugin/indifferent_params_spec.rb +0 -14
- data/spec/plugin/json_parser_spec.rb +0 -141
- data/spec/plugin/json_spec.rb +0 -83
- data/spec/plugin/mail_processor_spec.rb +0 -451
- data/spec/plugin/mailer_spec.rb +0 -282
- data/spec/plugin/match_affix_spec.rb +0 -43
- data/spec/plugin/match_hook_spec.rb +0 -79
- data/spec/plugin/middleware_spec.rb +0 -237
- data/spec/plugin/middleware_stack_spec.rb +0 -81
- data/spec/plugin/module_include_spec.rb +0 -48
- data/spec/plugin/multi_route_spec.rb +0 -268
- data/spec/plugin/multi_run_spec.rb +0 -87
- data/spec/plugin/multi_view_spec.rb +0 -50
- data/spec/plugin/multibyte_string_matcher_spec.rb +0 -44
- data/spec/plugin/named_templates_spec.rb +0 -96
- data/spec/plugin/not_allowed_spec.rb +0 -69
- data/spec/plugin/not_found_spec.rb +0 -128
- data/spec/plugin/optimized_string_matchers_spec.rb +0 -43
- data/spec/plugin/padrino_render_spec.rb +0 -34
- data/spec/plugin/param_matchers_spec.rb +0 -69
- data/spec/plugin/params_capturing_spec.rb +0 -33
- data/spec/plugin/partials_spec.rb +0 -43
- data/spec/plugin/pass_spec.rb +0 -29
- data/spec/plugin/path_matchers_spec.rb +0 -42
- data/spec/plugin/path_rewriter_spec.rb +0 -45
- data/spec/plugin/path_spec.rb +0 -222
- data/spec/plugin/placeholder_string_matchers_spec.rb +0 -126
- data/spec/plugin/precompile_templates_spec.rb +0 -61
- data/spec/plugin/public_spec.rb +0 -85
- data/spec/plugin/render_each_spec.rb +0 -82
- data/spec/plugin/render_locals_spec.rb +0 -114
- data/spec/plugin/render_spec.rb +0 -912
- data/spec/plugin/request_aref_spec.rb +0 -51
- data/spec/plugin/request_headers_spec.rb +0 -39
- data/spec/plugin/response_request_spec.rb +0 -43
- data/spec/plugin/route_block_args_spec.rb +0 -86
- data/spec/plugin/route_csrf_spec.rb +0 -305
- data/spec/plugin/run_append_slash_spec.rb +0 -77
- data/spec/plugin/run_handler_spec.rb +0 -53
- data/spec/plugin/sessions_spec.rb +0 -452
- data/spec/plugin/shared_vars_spec.rb +0 -45
- data/spec/plugin/sinatra_helpers_spec.rb +0 -537
- data/spec/plugin/slash_path_empty_spec.rb +0 -22
- data/spec/plugin/static_routing_spec.rb +0 -192
- data/spec/plugin/static_spec.rb +0 -30
- data/spec/plugin/status_303_spec.rb +0 -28
- data/spec/plugin/status_handler_spec.rb +0 -158
- data/spec/plugin/streaming_spec.rb +0 -246
- data/spec/plugin/strip_path_prefix_spec.rb +0 -24
- data/spec/plugin/symbol_matchers_spec.rb +0 -51
- data/spec/plugin/symbol_status_spec.rb +0 -25
- data/spec/plugin/symbol_views_spec.rb +0 -32
- data/spec/plugin/timestamp_public_spec.rb +0 -85
- data/spec/plugin/type_routing_spec.rb +0 -348
- data/spec/plugin/typecast_params_spec.rb +0 -1370
- data/spec/plugin/unescape_path_spec.rb +0 -22
- data/spec/plugin/view_options_spec.rb +0 -170
- data/spec/plugin_spec.rb +0 -71
- data/spec/redirect_spec.rb +0 -41
- data/spec/request_spec.rb +0 -97
- data/spec/response_spec.rb +0 -199
- data/spec/route_spec.rb +0 -39
- data/spec/session_middleware_spec.rb +0 -129
- data/spec/session_spec.rb +0 -37
- data/spec/spec_helper.rb +0 -137
- data/spec/version_spec.rb +0 -14
- data/spec/views/_test.erb +0 -1
- data/spec/views/a.erb +0 -1
- data/spec/views/a.rdoc +0 -2
- data/spec/views/about.erb +0 -1
- data/spec/views/about.str +0 -1
- data/spec/views/about/_test.css.gz +0 -0
- data/spec/views/about/_test.erb +0 -1
- data/spec/views/about/_test.erb.gz +0 -0
- data/spec/views/about/comp_test.erb +0 -1
- data/spec/views/b.erb +0 -1
- data/spec/views/c.erb +0 -1
- data/spec/views/comp_layout.erb +0 -1
- data/spec/views/comp_test.erb +0 -1
- data/spec/views/content-yield.erb +0 -1
- data/spec/views/each.str +0 -1
- data/spec/views/home.erb +0 -2
- data/spec/views/home.str +0 -2
- data/spec/views/iv.erb +0 -1
- data/spec/views/layout-alternative.erb +0 -2
- data/spec/views/layout-yield.erb +0 -3
- data/spec/views/layout.erb +0 -2
- data/spec/views/layout.str +0 -2
- data/spec/views/multiple-layout.erb +0 -1
- data/spec/views/multiple.erb +0 -1
data/spec/env_spec.rb
DELETED
data/spec/freeze_spec.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
require_relative "spec_helper"
|
2
|
-
|
3
|
-
describe "Roda.freeze" do
|
4
|
-
before do
|
5
|
-
app{'a'}.freeze
|
6
|
-
end
|
7
|
-
|
8
|
-
it "should result in a working application" do
|
9
|
-
body.must_equal 'a'
|
10
|
-
end
|
11
|
-
|
12
|
-
it "should not break if called more than once" do
|
13
|
-
app.freeze
|
14
|
-
body.must_equal 'a'
|
15
|
-
end
|
16
|
-
|
17
|
-
it "should make opts not be modifiable after calling finalize!" do
|
18
|
-
proc{app.opts[:foo] = 'bar'}.must_raise
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should make use and route raise errors" do
|
22
|
-
proc{app.use Class.new}.must_raise
|
23
|
-
proc{app.route{}}.must_raise
|
24
|
-
end
|
25
|
-
|
26
|
-
it "should make plugin raise errors" do
|
27
|
-
proc{app.plugin Module.new}.must_raise
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should make subclassing raise errors" do
|
31
|
-
proc{Class.new(app)}.must_raise
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should freeze app" do
|
35
|
-
app.frozen?.must_equal true
|
36
|
-
end
|
37
|
-
end
|
data/spec/integration_spec.rb
DELETED
@@ -1,209 +0,0 @@
|
|
1
|
-
require_relative "spec_helper"
|
2
|
-
|
3
|
-
describe "integration" do
|
4
|
-
before do
|
5
|
-
@c = Class.new do
|
6
|
-
def initialize(app, first, second, &block)
|
7
|
-
@app, @first, @second, @block = app, first, second, block
|
8
|
-
end
|
9
|
-
|
10
|
-
def call(env)
|
11
|
-
env["m.first"] = @first
|
12
|
-
env["m.second"] = @second
|
13
|
-
env["m.block"] = @block.call
|
14
|
-
|
15
|
-
@app.call(env)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should setup middleware using use" do
|
22
|
-
c = @c
|
23
|
-
app(:bare) do
|
24
|
-
use c, "First", "Second" do
|
25
|
-
"Block"
|
26
|
-
end
|
27
|
-
|
28
|
-
route do |r|
|
29
|
-
r.get "hello" do
|
30
|
-
"D #{r.env['m.first']} #{r.env['m.second']} #{r.env['m.block']}"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
body('/hello').must_equal 'D First Second Block'
|
36
|
-
end
|
37
|
-
|
38
|
-
it "should clear middleware when clear_middleware! is called" do
|
39
|
-
c = @c
|
40
|
-
app(:bare) do
|
41
|
-
use c, "First", "Second" do
|
42
|
-
"Block"
|
43
|
-
end
|
44
|
-
|
45
|
-
route do |r|
|
46
|
-
r.get "hello" do
|
47
|
-
"D #{r.env['m.first']} #{r.env['m.second']} #{r.env['m.block']}"
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
clear_middleware!
|
52
|
-
end
|
53
|
-
|
54
|
-
body('/hello').must_equal 'D '
|
55
|
-
end
|
56
|
-
|
57
|
-
it "should freeze middleware if opts[:freeze_middleware] is true" do
|
58
|
-
c = Class.new do
|
59
|
-
def initialize(app) @app = app end
|
60
|
-
def call(env) @a = 1; @app.call(env) end
|
61
|
-
end
|
62
|
-
|
63
|
-
app do
|
64
|
-
"D"
|
65
|
-
end
|
66
|
-
|
67
|
-
body.must_equal 'D'
|
68
|
-
|
69
|
-
app.use c
|
70
|
-
body.must_equal 'D'
|
71
|
-
|
72
|
-
app.clear_middleware!
|
73
|
-
app.opts[:freeze_middleware] = true
|
74
|
-
app.use c
|
75
|
-
proc{body}.must_raise RuntimeError, TypeError
|
76
|
-
end
|
77
|
-
|
78
|
-
it "should support adding middleware using use after route block setup" do
|
79
|
-
c = @c
|
80
|
-
app(:bare) do
|
81
|
-
route do |r|
|
82
|
-
r.get "hello" do
|
83
|
-
"D #{r.env['m.first']} #{r.env['m.second']} #{r.env['m.block']}"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
use c, "First", "Second" do
|
88
|
-
"Block"
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
body('/hello').must_equal 'D First Second Block'
|
93
|
-
end
|
94
|
-
|
95
|
-
it "should inherit middleware in subclass" do
|
96
|
-
c = @c
|
97
|
-
@app = Class.new(app(:bare){use(c, '1', '2'){"3"}})
|
98
|
-
@app.route do |r|
|
99
|
-
r.get "hello" do
|
100
|
-
"D #{r.env['m.first']} #{r.env['m.second']} #{r.env['m.block']}"
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
body('/hello').must_equal 'D 1 2 3'
|
105
|
-
end
|
106
|
-
|
107
|
-
it "should not inherit middleware in subclass if inhert_middleware = false" do
|
108
|
-
c = @c
|
109
|
-
app(:bare){use(c, '1', '2'){"3"}}
|
110
|
-
@app.inherit_middleware = false
|
111
|
-
@app = Class.new(@app)
|
112
|
-
@app.route do |r|
|
113
|
-
r.get "hello" do
|
114
|
-
"D #{r.env['m.first']} #{r.env['m.second']} #{r.env['m.block']}"
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
body('/hello').must_equal 'D '
|
119
|
-
end
|
120
|
-
|
121
|
-
it "should inherit route in subclass" do
|
122
|
-
c = @c
|
123
|
-
app(:bare) do
|
124
|
-
use(c, '1', '2'){"3"}
|
125
|
-
route do |r|
|
126
|
-
r.get "hello" do
|
127
|
-
"D #{r.env['m.first']} #{r.env['m.second']} #{r.env['m.block']}"
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
@app = Class.new(app)
|
132
|
-
|
133
|
-
body('/hello').must_equal 'D 1 2 3'
|
134
|
-
end
|
135
|
-
|
136
|
-
it "should use instance of subclass when inheriting routes" do
|
137
|
-
c = @c
|
138
|
-
obj = nil
|
139
|
-
app(:bare) do
|
140
|
-
use(c, '1', '2'){"3"}
|
141
|
-
route do |r|
|
142
|
-
r.get "hello" do
|
143
|
-
obj = self
|
144
|
-
"D #{r.env['m.first']} #{r.env['m.second']} #{r.env['m.block']}"
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
@app = Class.new(app)
|
149
|
-
|
150
|
-
body('/hello').must_equal 'D 1 2 3'
|
151
|
-
obj.must_be_kind_of(@app)
|
152
|
-
end
|
153
|
-
|
154
|
-
it "should handle middleware added to subclass using superclass route" do
|
155
|
-
c = @c
|
156
|
-
app(:bare) do
|
157
|
-
route do |r|
|
158
|
-
r.get "hello" do
|
159
|
-
"D #{r.env['m.first']} #{r.env['m.second']} #{r.env['m.block']}"
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
163
|
-
@app = Class.new(app)
|
164
|
-
@app.use(c, '1', '2'){"3"}
|
165
|
-
|
166
|
-
body('/hello').must_equal 'D 1 2 3'
|
167
|
-
end
|
168
|
-
|
169
|
-
it "should not have future middleware additions to superclass affect subclass" do
|
170
|
-
c = @c
|
171
|
-
a = app
|
172
|
-
@app = Class.new(a)
|
173
|
-
@app.route do |r|
|
174
|
-
r.get "hello" do
|
175
|
-
"D #{r.env['m.first']} #{r.env['m.second']} #{r.env['m.block']}"
|
176
|
-
end
|
177
|
-
end
|
178
|
-
a.use(c, '1', '2'){"3"}
|
179
|
-
|
180
|
-
body('/hello').must_equal 'D '
|
181
|
-
end
|
182
|
-
|
183
|
-
it "should not have future middleware additions to subclass affect superclass" do
|
184
|
-
c = @c
|
185
|
-
a = app do |r|
|
186
|
-
r.get "hello" do
|
187
|
-
"D #{r.env['m.first']} #{r.env['m.second']} #{r.env['m.block']}"
|
188
|
-
end
|
189
|
-
end
|
190
|
-
@app = Class.new(a)
|
191
|
-
@app.use(c, '1', '2'){"3"}
|
192
|
-
@app = a
|
193
|
-
|
194
|
-
body('/hello').must_equal 'D '
|
195
|
-
end
|
196
|
-
|
197
|
-
it "should have app return the rack application to call" do
|
198
|
-
app(:bare){}.app.must_be_kind_of(Proc)
|
199
|
-
app.route{|r|}
|
200
|
-
app.app.must_be_kind_of(Proc)
|
201
|
-
c = Class.new{def initialize(app) @app = app end; def call(env) @app.call(env) end}
|
202
|
-
app.use c
|
203
|
-
app.app.must_be_kind_of(c)
|
204
|
-
end
|
205
|
-
|
206
|
-
it "should have route_block return the route block" do
|
207
|
-
app{|r| 1}.route_block.call(nil).must_equal 1
|
208
|
-
end
|
209
|
-
end
|
data/spec/matchers_spec.rb
DELETED
@@ -1,832 +0,0 @@
|
|
1
|
-
require_relative "spec_helper"
|
2
|
-
|
3
|
-
describe "capturing" do
|
4
|
-
it "doesn't yield the verb for verb matcher" do
|
5
|
-
app do |r|
|
6
|
-
r.get do |*args|
|
7
|
-
args.size.to_s
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
body.must_equal '0'
|
12
|
-
end
|
13
|
-
|
14
|
-
it "doesn't yield the path for string matcher" do
|
15
|
-
app do |r|
|
16
|
-
r.get "home" do |*args|
|
17
|
-
args.size.to_s
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
body('/home').must_equal '0'
|
22
|
-
end
|
23
|
-
|
24
|
-
it "yields the segment for symbol matcher" do
|
25
|
-
app do |r|
|
26
|
-
r.get "user", :id do |id|
|
27
|
-
id
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
body("/user/johndoe").must_equal 'johndoe'
|
32
|
-
end
|
33
|
-
|
34
|
-
it "yields an integer segment as a string when using symbol matcher" do
|
35
|
-
app do |r|
|
36
|
-
r.get "user", :id do |id|
|
37
|
-
id
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
body("/user/101").must_equal '101'
|
42
|
-
end
|
43
|
-
|
44
|
-
it "yields a segment per nested block for symbol matcher" do
|
45
|
-
app do |r|
|
46
|
-
r.on :one do |one|
|
47
|
-
r.on :two do |two|
|
48
|
-
r.on :three do |three|
|
49
|
-
one + two + three
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
body("/one/two/three").must_equal "onetwothree"
|
56
|
-
end
|
57
|
-
|
58
|
-
it "yields a segment per argument for symbol matcher" do
|
59
|
-
app do |r|
|
60
|
-
r.on :one, :two, :three do |one, two, three|
|
61
|
-
one + two + three
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
body("/one/two/three").must_equal "onetwothree"
|
66
|
-
end
|
67
|
-
|
68
|
-
it "yields regex captures as separate arguments" do
|
69
|
-
app do |r|
|
70
|
-
r.get %r{posts/(\d+)-(.*)} do |id, slug|
|
71
|
-
id + slug
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
body("/posts/123-postal-service").must_equal "123postal-service"
|
76
|
-
end
|
77
|
-
|
78
|
-
it "yields an integer segment as an integer when using Integer matcher " do
|
79
|
-
app do |r|
|
80
|
-
r.get "user", Integer do |id|
|
81
|
-
"#{id}-#{id.is_a?(Integer)}"
|
82
|
-
end
|
83
|
-
"b"
|
84
|
-
end
|
85
|
-
|
86
|
-
body("/user/101").must_equal '101-true'
|
87
|
-
body("/user/a").must_equal 'b'
|
88
|
-
end
|
89
|
-
|
90
|
-
it "yields the segment for String class matcher" do
|
91
|
-
app do |r|
|
92
|
-
r.get "user", String do |id|
|
93
|
-
id
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
body("/user/johndoe").must_equal 'johndoe'
|
98
|
-
end
|
99
|
-
|
100
|
-
it "raises error for unsupported class matcher" do
|
101
|
-
app do |r|
|
102
|
-
r.get Hash do |id|
|
103
|
-
id
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
proc{status}.must_raise Roda::RodaError
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
describe "r.is" do
|
112
|
-
it "ensures the patch is matched fully" do
|
113
|
-
app do |r|
|
114
|
-
r.is "" do
|
115
|
-
"+1"
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
body.must_equal '+1'
|
120
|
-
status('//').must_equal 404
|
121
|
-
end
|
122
|
-
|
123
|
-
it "handles no arguments" do
|
124
|
-
app do |r|
|
125
|
-
r.on "" do
|
126
|
-
r.is do
|
127
|
-
"+1"
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
body.must_equal '+1'
|
133
|
-
status('//').must_equal 404
|
134
|
-
end
|
135
|
-
|
136
|
-
it "matches strings" do
|
137
|
-
app do |r|
|
138
|
-
r.is "123" do
|
139
|
-
"+1"
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
body("/123").must_equal '+1'
|
144
|
-
status("/123/").must_equal 404
|
145
|
-
end
|
146
|
-
|
147
|
-
it "matches regexps" do
|
148
|
-
app do |r|
|
149
|
-
r.is(/(\w+)/) do |id|
|
150
|
-
id
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
body("/123").must_equal '123'
|
155
|
-
status("/123/").must_equal 404
|
156
|
-
end
|
157
|
-
|
158
|
-
it "matches regexps" do
|
159
|
-
app do |r|
|
160
|
-
r.on(/foo/) do |id|
|
161
|
-
'a'
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
body("/foo").must_equal 'a'
|
166
|
-
body("/foo/").must_equal 'a'
|
167
|
-
status("/food").must_equal 404
|
168
|
-
end
|
169
|
-
|
170
|
-
it "matches segments" do
|
171
|
-
app do |r|
|
172
|
-
r.is :id do |id|
|
173
|
-
id
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
body("/123").must_equal '123'
|
178
|
-
status("/123/").must_equal 404
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
describe "matchers" do
|
183
|
-
it "should not handle string with embedded param if :verbatim_string_matcher option is set" do
|
184
|
-
app do |r|
|
185
|
-
r.on "posts/:id" do
|
186
|
-
'1'
|
187
|
-
end
|
188
|
-
|
189
|
-
r.on "responses-:id" do
|
190
|
-
'2'
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
status('/post/123').must_equal 404
|
195
|
-
status('/posts/123').must_equal 404
|
196
|
-
body('/posts/:id').must_equal '1'
|
197
|
-
status('/responses-123').must_equal 404
|
198
|
-
body('/responses-:id').must_equal '2'
|
199
|
-
end
|
200
|
-
|
201
|
-
it "should handle regexes and nesting" do
|
202
|
-
app do |r|
|
203
|
-
r.on(/u\/(\w+)/) do |uid|
|
204
|
-
r.on(/posts\/(\d+)/) do |id|
|
205
|
-
uid + id
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
body("/u/jdoe/posts/123").must_equal 'jdoe123'
|
211
|
-
status("/u/jdoe/pots/123").must_equal 404
|
212
|
-
end
|
213
|
-
|
214
|
-
it "should handle regex nesting colon param style" do
|
215
|
-
app do |r|
|
216
|
-
r.on(/u:(\w+)/) do |uid|
|
217
|
-
r.on(/posts:(\d+)/) do |id|
|
218
|
-
uid + id
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
body("/u:jdoe/posts:123").must_equal 'jdoe123'
|
224
|
-
status("/u:jdoe/poss:123").must_equal 404
|
225
|
-
end
|
226
|
-
|
227
|
-
it "symbol matching" do
|
228
|
-
app do |r|
|
229
|
-
r.on "user", :id do |uid|
|
230
|
-
r.on "posts", :pid do |id|
|
231
|
-
uid + id
|
232
|
-
end
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
body("/user/jdoe/posts/123").must_equal 'jdoe123'
|
237
|
-
status("/user/jdoe/pots/123").must_equal 404
|
238
|
-
end
|
239
|
-
|
240
|
-
it "paths and numbers" do
|
241
|
-
app do |r|
|
242
|
-
r.on "about" do
|
243
|
-
r.on :one, :two do |one, two|
|
244
|
-
one + two
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
body("/about/1/2").must_equal '12'
|
250
|
-
status("/about/1").must_equal 404
|
251
|
-
end
|
252
|
-
|
253
|
-
it "paths and decimals" do
|
254
|
-
app do |r|
|
255
|
-
r.on "about" do
|
256
|
-
r.on(/(\d+)/) do |one|
|
257
|
-
one
|
258
|
-
end
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
body("/about/1").must_equal '1'
|
263
|
-
status("/about/1.2").must_equal 404
|
264
|
-
end
|
265
|
-
|
266
|
-
it "should allow arrays to match any value" do
|
267
|
-
app do |r|
|
268
|
-
r.on [/(\d+)/, /\d+(bar)?/] do |id|
|
269
|
-
id
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
body('/123').must_equal '123'
|
274
|
-
body('/123bar').must_equal 'bar'
|
275
|
-
status('/123bard').must_equal 404
|
276
|
-
end
|
277
|
-
|
278
|
-
it "should allow arrays to match optional segments with splats" do
|
279
|
-
app do |r|
|
280
|
-
r.on :foo, [:bar, true] do |*m|
|
281
|
-
m.inspect
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
body('/123').must_equal '["123"]'
|
286
|
-
body('/123/456').must_equal '["123", "456"]'
|
287
|
-
end
|
288
|
-
|
289
|
-
it "should allow arrays to match optional segments with separate arguments" do
|
290
|
-
app do |r|
|
291
|
-
r.on :foo, [:bar, true] do |f, b|
|
292
|
-
[f, b].inspect
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
|
-
body('/123').must_equal '["123", nil]'
|
297
|
-
body('/123/456').must_equal '["123", "456"]'
|
298
|
-
end
|
299
|
-
|
300
|
-
it "should allow regexp to match optional segments with separate arguments" do
|
301
|
-
app do |r|
|
302
|
-
r.on(/(\d+)(?:\/(\d+))?/) do |f, b|
|
303
|
-
[f, b].inspect
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
body('/123').must_equal '["123", nil]'
|
308
|
-
body('/123/456').must_equal '["123", "456"]'
|
309
|
-
end
|
310
|
-
|
311
|
-
it "should have array capture match string if match" do
|
312
|
-
app do |r|
|
313
|
-
r.on %w'p q' do |id|
|
314
|
-
id
|
315
|
-
end
|
316
|
-
end
|
317
|
-
|
318
|
-
body('/p').must_equal 'p'
|
319
|
-
body('/q').must_equal 'q'
|
320
|
-
status('/r').must_equal 404
|
321
|
-
end
|
322
|
-
end
|
323
|
-
|
324
|
-
describe "r.on" do
|
325
|
-
it "executes on no arguments" do
|
326
|
-
app do |r|
|
327
|
-
r.on do
|
328
|
-
"+1"
|
329
|
-
end
|
330
|
-
end
|
331
|
-
|
332
|
-
body.must_equal '+1'
|
333
|
-
end
|
334
|
-
|
335
|
-
it "executes on true" do
|
336
|
-
app do |r|
|
337
|
-
r.on true do
|
338
|
-
"+1"
|
339
|
-
end
|
340
|
-
end
|
341
|
-
|
342
|
-
body.must_equal '+1'
|
343
|
-
end
|
344
|
-
|
345
|
-
it "does not execute on false" do
|
346
|
-
app do |r|
|
347
|
-
r.on false do
|
348
|
-
"+1"
|
349
|
-
end
|
350
|
-
end
|
351
|
-
|
352
|
-
status.must_equal 404
|
353
|
-
end
|
354
|
-
|
355
|
-
it "does not execute on nil" do
|
356
|
-
app do |r|
|
357
|
-
r.on nil do
|
358
|
-
"+1"
|
359
|
-
end
|
360
|
-
end
|
361
|
-
|
362
|
-
status.must_equal 404
|
363
|
-
end
|
364
|
-
|
365
|
-
it "raises on arbitrary object" do
|
366
|
-
app(:bare) do
|
367
|
-
route do |r|
|
368
|
-
r.on Object.new do
|
369
|
-
"+1"
|
370
|
-
end
|
371
|
-
end
|
372
|
-
end
|
373
|
-
|
374
|
-
proc{body}.must_raise Roda::RodaError
|
375
|
-
end
|
376
|
-
|
377
|
-
it "executes on non-false" do
|
378
|
-
app do |r|
|
379
|
-
r.on "123" do
|
380
|
-
"+1"
|
381
|
-
end
|
382
|
-
end
|
383
|
-
|
384
|
-
body("/123").must_equal '+1'
|
385
|
-
end
|
386
|
-
|
387
|
-
it "does not modify SCRIPT_NAME/PATH_INFO during routing" do
|
388
|
-
app(:pass) do |r|
|
389
|
-
r.on "foo" do
|
390
|
-
r.is "bar" do
|
391
|
-
"bar|#{env['SCRIPT_NAME']}|#{env['PATH_INFO']}"
|
392
|
-
end
|
393
|
-
r.is "baz" do
|
394
|
-
r.pass
|
395
|
-
end
|
396
|
-
"foo|#{env['SCRIPT_NAME']}|#{env['PATH_INFO']}"
|
397
|
-
end
|
398
|
-
"#{env['SCRIPT_NAME']}|#{env['PATH_INFO']}"
|
399
|
-
end
|
400
|
-
|
401
|
-
body.must_equal '|/'
|
402
|
-
body('SCRIPT_NAME'=>'/a').must_equal '/a|/'
|
403
|
-
body('/foo').must_equal 'foo||/foo'
|
404
|
-
body('/foo', 'SCRIPT_NAME'=>'/a').must_equal 'foo|/a|/foo'
|
405
|
-
body('/foo/bar').must_equal 'bar||/foo/bar'
|
406
|
-
body('/foo/bar', 'SCRIPT_NAME'=>'/a').must_equal 'bar|/a|/foo/bar'
|
407
|
-
body('/foo/baz').must_equal 'foo||/foo/baz'
|
408
|
-
body('/foo/baz', 'SCRIPT_NAME'=>'/a').must_equal 'foo|/a|/foo/baz'
|
409
|
-
end
|
410
|
-
|
411
|
-
it "should have path/matched_path/remaining_path work correctly" do
|
412
|
-
app do |r|
|
413
|
-
r.on "foo" do
|
414
|
-
"#{r.path}:#{r.matched_path}:#{r.remaining_path}"
|
415
|
-
end
|
416
|
-
end
|
417
|
-
|
418
|
-
body("/foo/bar").must_equal "/foo/bar:/foo:/bar"
|
419
|
-
end
|
420
|
-
|
421
|
-
it "ensures remaining_path is reverted if modified in failing matcher" do
|
422
|
-
app do |r|
|
423
|
-
r.on lambda { @remaining_path = "/blah"; false } do
|
424
|
-
"Unreachable"
|
425
|
-
end
|
426
|
-
|
427
|
-
r.on do
|
428
|
-
r.matched_path + ':' + r.remaining_path
|
429
|
-
end
|
430
|
-
end
|
431
|
-
|
432
|
-
body("/hello").must_equal ':/hello'
|
433
|
-
end
|
434
|
-
|
435
|
-
it "modifies matched_path/remaining_path during routing" do
|
436
|
-
app do |r|
|
437
|
-
r.on 'login', 'foo' do
|
438
|
-
"Unreachable"
|
439
|
-
end
|
440
|
-
|
441
|
-
r.on 'hello' do
|
442
|
-
r.matched_path + ':' + r.remaining_path
|
443
|
-
end
|
444
|
-
end
|
445
|
-
|
446
|
-
body("/hello/you").must_equal '/hello:/you'
|
447
|
-
end
|
448
|
-
|
449
|
-
it "doesn't modify SCRIPT_NAME/PATH_INFO during routing" do
|
450
|
-
app do |r|
|
451
|
-
r.on 'login', 'foo' do
|
452
|
-
"Unreachable"
|
453
|
-
end
|
454
|
-
|
455
|
-
r.on 'hello' do
|
456
|
-
r.env["SCRIPT_NAME"] + ':' + r.env["PATH_INFO"]
|
457
|
-
end
|
458
|
-
end
|
459
|
-
|
460
|
-
body("/hello/you").must_equal ':/hello/you'
|
461
|
-
end
|
462
|
-
|
463
|
-
it "doesn't mutate SCRIPT_NAME or PATH_INFO after request is returned" do
|
464
|
-
app do |r|
|
465
|
-
r.on 'login', 'foo' do
|
466
|
-
"Unreachable"
|
467
|
-
end
|
468
|
-
|
469
|
-
r.on do
|
470
|
-
r.env["SCRIPT_NAME"] + ':' + r.env["PATH_INFO"]
|
471
|
-
end
|
472
|
-
end
|
473
|
-
|
474
|
-
pi, sn = '/login', ''
|
475
|
-
env = {"REQUEST_METHOD" => "GET", "PATH_INFO" => pi, "SCRIPT_NAME" => sn}
|
476
|
-
app.call(env)[2].join.must_equal ":/login"
|
477
|
-
env["PATH_INFO"].must_equal pi
|
478
|
-
env["SCRIPT_NAME"].must_equal sn
|
479
|
-
end
|
480
|
-
|
481
|
-
it "skips consecutive matches" do
|
482
|
-
app do |r|
|
483
|
-
r.on do
|
484
|
-
"foo"
|
485
|
-
end
|
486
|
-
|
487
|
-
r.on do
|
488
|
-
"bar"
|
489
|
-
end
|
490
|
-
end
|
491
|
-
|
492
|
-
body.must_equal "foo"
|
493
|
-
end
|
494
|
-
|
495
|
-
it "finds first match available" do
|
496
|
-
app do |r|
|
497
|
-
r.on false do
|
498
|
-
"foo"
|
499
|
-
end
|
500
|
-
|
501
|
-
r.on do
|
502
|
-
"bar"
|
503
|
-
end
|
504
|
-
end
|
505
|
-
|
506
|
-
body.must_equal "bar"
|
507
|
-
end
|
508
|
-
|
509
|
-
it "reverts a half-met matcher" do
|
510
|
-
app do |r|
|
511
|
-
r.on "post", false do
|
512
|
-
"Should be unmet"
|
513
|
-
end
|
514
|
-
|
515
|
-
r.on do
|
516
|
-
r.env["SCRIPT_NAME"] + ':' + r.env["PATH_INFO"]
|
517
|
-
end
|
518
|
-
end
|
519
|
-
|
520
|
-
body("/hello").must_equal ':/hello'
|
521
|
-
end
|
522
|
-
|
523
|
-
it "doesn't write to body if body already written to" do
|
524
|
-
app do |r|
|
525
|
-
r.on do
|
526
|
-
response.write "a"
|
527
|
-
"b"
|
528
|
-
end
|
529
|
-
end
|
530
|
-
|
531
|
-
body.must_equal 'a'
|
532
|
-
end
|
533
|
-
end
|
534
|
-
|
535
|
-
describe "path matchers" do
|
536
|
-
it "one level path" do
|
537
|
-
app do |r|
|
538
|
-
r.on "about" do
|
539
|
-
"About"
|
540
|
-
end
|
541
|
-
end
|
542
|
-
|
543
|
-
body('/about').must_equal "About"
|
544
|
-
status("/abot").must_equal 404
|
545
|
-
end
|
546
|
-
|
547
|
-
it "two level nested paths" do
|
548
|
-
app do |r|
|
549
|
-
r.on "about" do
|
550
|
-
r.on "1" do
|
551
|
-
"+1"
|
552
|
-
end
|
553
|
-
|
554
|
-
r.on "2" do
|
555
|
-
"+2"
|
556
|
-
end
|
557
|
-
end
|
558
|
-
end
|
559
|
-
|
560
|
-
body('/about/1').must_equal "+1"
|
561
|
-
body('/about/2').must_equal "+2"
|
562
|
-
status('/about/3').must_equal 404
|
563
|
-
end
|
564
|
-
|
565
|
-
it "two level inlined paths" do
|
566
|
-
app do |r|
|
567
|
-
r.on "a/b" do
|
568
|
-
"ab"
|
569
|
-
end
|
570
|
-
end
|
571
|
-
|
572
|
-
body('/a/b').must_equal "ab"
|
573
|
-
status('/a/d').must_equal 404
|
574
|
-
end
|
575
|
-
|
576
|
-
it "a path with some regex captures" do
|
577
|
-
app do |r|
|
578
|
-
r.on(/user(\d+)/) do |uid|
|
579
|
-
uid
|
580
|
-
end
|
581
|
-
end
|
582
|
-
|
583
|
-
body('/user123').must_equal "123"
|
584
|
-
status('/useradf').must_equal 404
|
585
|
-
end
|
586
|
-
|
587
|
-
it "matching the root with a string" do
|
588
|
-
app do |r|
|
589
|
-
r.is "" do
|
590
|
-
"Home"
|
591
|
-
end
|
592
|
-
end
|
593
|
-
|
594
|
-
body.must_equal 'Home'
|
595
|
-
status("//").must_equal 404
|
596
|
-
status("/foo").must_equal 404
|
597
|
-
end
|
598
|
-
|
599
|
-
it "matching the root with the root method" do
|
600
|
-
app do |r|
|
601
|
-
r.root do
|
602
|
-
"Home"
|
603
|
-
end
|
604
|
-
end
|
605
|
-
|
606
|
-
body.must_equal 'Home'
|
607
|
-
status('REQUEST_METHOD'=>'POST').must_equal 404
|
608
|
-
status("//").must_equal 404
|
609
|
-
status("/foo").must_equal 404
|
610
|
-
end
|
611
|
-
end
|
612
|
-
|
613
|
-
describe "root/empty segment matching" do
|
614
|
-
it "matching an empty segment" do
|
615
|
-
app do |r|
|
616
|
-
r.on "" do
|
617
|
-
r.path
|
618
|
-
end
|
619
|
-
end
|
620
|
-
|
621
|
-
body.must_equal '/'
|
622
|
-
status("/foo").must_equal 404
|
623
|
-
end
|
624
|
-
|
625
|
-
it "nested empty segments" do
|
626
|
-
app do |r|
|
627
|
-
r.on "" do
|
628
|
-
r.on "" do
|
629
|
-
r.on "1" do
|
630
|
-
r.path
|
631
|
-
end
|
632
|
-
end
|
633
|
-
end
|
634
|
-
end
|
635
|
-
|
636
|
-
body("///1").must_equal '///1'
|
637
|
-
status("/1").must_equal 404
|
638
|
-
status("//1").must_equal 404
|
639
|
-
end
|
640
|
-
|
641
|
-
it "/events/? scenario" do
|
642
|
-
a = app do |r|
|
643
|
-
r.on "" do
|
644
|
-
"Hooray"
|
645
|
-
end
|
646
|
-
|
647
|
-
r.is do
|
648
|
-
"Foo"
|
649
|
-
end
|
650
|
-
end
|
651
|
-
|
652
|
-
app(:new) do |r|
|
653
|
-
r.on "events" do
|
654
|
-
r.run a
|
655
|
-
end
|
656
|
-
end
|
657
|
-
|
658
|
-
body("/events").must_equal 'Foo'
|
659
|
-
body("/events/").must_equal 'Hooray'
|
660
|
-
status("/events/foo").must_equal 404
|
661
|
-
end
|
662
|
-
end
|
663
|
-
|
664
|
-
describe "segment handling" do
|
665
|
-
before do
|
666
|
-
app do |r|
|
667
|
-
r.on "post" do
|
668
|
-
r.on :id do |id|
|
669
|
-
id
|
670
|
-
end
|
671
|
-
end
|
672
|
-
end
|
673
|
-
end
|
674
|
-
|
675
|
-
it "matches numeric ids" do
|
676
|
-
body('/post/1').must_equal '1'
|
677
|
-
end
|
678
|
-
|
679
|
-
it "matches decimal numbers" do
|
680
|
-
body('/post/1.1').must_equal '1.1'
|
681
|
-
end
|
682
|
-
|
683
|
-
it "matches slugs" do
|
684
|
-
body('/post/my-blog-post-about-cuba').must_equal 'my-blog-post-about-cuba'
|
685
|
-
end
|
686
|
-
|
687
|
-
it "matches only the first segment available" do
|
688
|
-
body('/post/one/two/three').must_equal 'one'
|
689
|
-
end
|
690
|
-
end
|
691
|
-
|
692
|
-
describe "request verb methods" do
|
693
|
-
it "executes if verb matches" do
|
694
|
-
app do |r|
|
695
|
-
r.get do
|
696
|
-
"g"
|
697
|
-
end
|
698
|
-
r.post do
|
699
|
-
"p"
|
700
|
-
end
|
701
|
-
end
|
702
|
-
|
703
|
-
body.must_equal 'g'
|
704
|
-
body('REQUEST_METHOD'=>'POST').must_equal 'p'
|
705
|
-
end
|
706
|
-
|
707
|
-
it "requires exact match if given arguments" do
|
708
|
-
app do |r|
|
709
|
-
r.get "" do
|
710
|
-
"g"
|
711
|
-
end
|
712
|
-
r.post "" do
|
713
|
-
"p"
|
714
|
-
end
|
715
|
-
end
|
716
|
-
|
717
|
-
body.must_equal 'g'
|
718
|
-
body('REQUEST_METHOD'=>'POST').must_equal 'p'
|
719
|
-
status("/a").must_equal 404
|
720
|
-
status("/a", 'REQUEST_METHOD'=>'POST').must_equal 404
|
721
|
-
end
|
722
|
-
|
723
|
-
it "does not require exact match if given arguments" do
|
724
|
-
app do |r|
|
725
|
-
r.get do
|
726
|
-
r.is "" do
|
727
|
-
"g"
|
728
|
-
end
|
729
|
-
|
730
|
-
"get"
|
731
|
-
end
|
732
|
-
r.post do
|
733
|
-
r.is "" do
|
734
|
-
"p"
|
735
|
-
end
|
736
|
-
|
737
|
-
"post"
|
738
|
-
end
|
739
|
-
end
|
740
|
-
|
741
|
-
body.must_equal 'g'
|
742
|
-
body('REQUEST_METHOD'=>'POST').must_equal 'p'
|
743
|
-
body("/a").must_equal 'get'
|
744
|
-
body("/a", 'REQUEST_METHOD'=>'POST').must_equal 'post'
|
745
|
-
end
|
746
|
-
end
|
747
|
-
|
748
|
-
describe "all matcher" do
|
749
|
-
it "should match only all all arguments match" do
|
750
|
-
app do |r|
|
751
|
-
r.is :all=>['foo', :y] do |file|
|
752
|
-
file
|
753
|
-
end
|
754
|
-
end
|
755
|
-
|
756
|
-
body("/foo/bar").must_equal 'bar'
|
757
|
-
status.must_equal 404
|
758
|
-
status("/foo").must_equal 404
|
759
|
-
status("/foo/").must_equal 404
|
760
|
-
status("/foo/bar/baz").must_equal 404
|
761
|
-
end
|
762
|
-
end
|
763
|
-
|
764
|
-
describe "method matcher" do
|
765
|
-
it "should match given request types" do
|
766
|
-
app do |r|
|
767
|
-
r.is "", :method=>:get do
|
768
|
-
"foo"
|
769
|
-
end
|
770
|
-
r.is "", :method=>[:patch, :post] do
|
771
|
-
"bar"
|
772
|
-
end
|
773
|
-
end
|
774
|
-
|
775
|
-
body("REQUEST_METHOD"=>"GET").must_equal 'foo'
|
776
|
-
body("REQUEST_METHOD"=>"PATCH").must_equal 'bar'
|
777
|
-
body("REQUEST_METHOD"=>"POST").must_equal 'bar'
|
778
|
-
status("REQUEST_METHOD"=>"DELETE").must_equal 404
|
779
|
-
end
|
780
|
-
end
|
781
|
-
|
782
|
-
describe "route block that returns string" do
|
783
|
-
it "should be treated as if an on block returned string" do
|
784
|
-
app do |r|
|
785
|
-
"+1"
|
786
|
-
end
|
787
|
-
|
788
|
-
body.must_equal '+1'
|
789
|
-
end
|
790
|
-
end
|
791
|
-
|
792
|
-
describe "app with :unsupported_block_result => :raise option" do
|
793
|
-
def app_value(v)
|
794
|
-
app(:bare) do
|
795
|
-
opts[:unsupported_block_result] = :raise
|
796
|
-
route do |r|
|
797
|
-
r.is 'a' do v end
|
798
|
-
v
|
799
|
-
end
|
800
|
-
end
|
801
|
-
end
|
802
|
-
|
803
|
-
it "should handle String as body" do
|
804
|
-
app_value '1'
|
805
|
-
status.must_equal 200
|
806
|
-
body.must_equal '1'
|
807
|
-
status('/a').must_equal 200
|
808
|
-
body('/a').must_equal '1'
|
809
|
-
end
|
810
|
-
|
811
|
-
it "should handle nil and false as not found" do
|
812
|
-
app_value nil
|
813
|
-
status.must_equal 404
|
814
|
-
body.must_equal ''
|
815
|
-
status('/a').must_equal 404
|
816
|
-
body('/a').must_equal ''
|
817
|
-
end
|
818
|
-
|
819
|
-
it "should handle false as not found" do
|
820
|
-
app_value false
|
821
|
-
status.must_equal 404
|
822
|
-
body.must_equal ''
|
823
|
-
status('/a').must_equal 404
|
824
|
-
body('/a').must_equal ''
|
825
|
-
end
|
826
|
-
|
827
|
-
it "should raise RodaError for other types" do
|
828
|
-
app_value Object.new
|
829
|
-
proc{body}.must_raise Roda::RodaError
|
830
|
-
proc{body('/a')}.must_raise Roda::RodaError
|
831
|
-
end
|
832
|
-
end
|