roda 2.2.0 → 2.3.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 +34 -0
- data/Rakefile +22 -46
- data/doc/release_notes/2.3.0.txt +109 -0
- data/lib/roda/plugins/assets.rb +2 -1
- data/lib/roda/plugins/caching.rb +1 -1
- data/lib/roda/plugins/chunked.rb +1 -1
- data/lib/roda/plugins/error_email.rb +1 -1
- data/lib/roda/plugins/head.rb +6 -0
- data/lib/roda/plugins/heartbeat.rb +40 -0
- data/lib/roda/plugins/json.rb +23 -3
- data/lib/roda/plugins/json_parser.rb +72 -0
- data/lib/roda/plugins/mailer.rb +22 -5
- data/lib/roda/plugins/named_templates.rb +2 -2
- data/lib/roda/plugins/path_rewriter.rb +82 -0
- data/lib/roda/plugins/precompile_templates.rb +87 -0
- data/lib/roda/plugins/render.rb +111 -43
- data/lib/roda/plugins/render_each.rb +1 -1
- data/lib/roda/plugins/shared_vars.rb +1 -1
- data/lib/roda/plugins/view_options.rb +28 -3
- data/lib/roda/version.rb +1 -1
- data/spec/composition_spec.rb +3 -3
- data/spec/env_spec.rb +1 -1
- data/spec/freeze_spec.rb +6 -6
- data/spec/integration_spec.rb +16 -15
- data/spec/matchers_spec.rb +110 -110
- data/spec/opts_spec.rb +8 -8
- data/spec/plugin/_erubis_escaping_spec.rb +34 -3
- data/spec/plugin/all_verbs_spec.rb +8 -8
- data/spec/plugin/assets_spec.rb +164 -150
- data/spec/plugin/backtracking_array_spec.rb +18 -18
- data/spec/plugin/caching_spec.rb +70 -70
- data/spec/plugin/chunked_spec.rb +38 -38
- data/spec/plugin/class_level_routing_spec.rb +78 -78
- data/spec/plugin/content_for_spec.rb +2 -2
- data/spec/plugin/cookies_spec.rb +4 -4
- data/spec/plugin/csrf_spec.rb +8 -8
- data/spec/plugin/default_headers_spec.rb +6 -6
- data/spec/plugin/delay_build_spec.rb +7 -6
- data/spec/plugin/delegate_spec.rb +2 -2
- data/spec/plugin/delete_empty_headers_spec.rb +2 -2
- data/spec/plugin/drop_body_spec.rb +6 -6
- data/spec/plugin/empty_root_spec.rb +3 -3
- data/spec/plugin/environments_spec.rb +7 -7
- data/spec/plugin/error_email_spec.rb +23 -23
- data/spec/plugin/error_handler_spec.rb +14 -14
- data/spec/plugin/flash_spec.rb +30 -29
- data/spec/plugin/h_spec.rb +1 -1
- data/spec/plugin/halt_spec.rb +16 -16
- data/spec/plugin/hash_matcher_spec.rb +5 -5
- data/spec/plugin/head_spec.rb +10 -10
- data/spec/plugin/header_matchers_spec.rb +13 -13
- data/spec/plugin/heartbeat_spec.rb +74 -0
- data/spec/plugin/hooks_spec.rb +20 -20
- data/spec/plugin/indifferent_params_spec.rb +1 -1
- data/spec/plugin/json_parser_spec.rb +72 -0
- data/spec/plugin/json_spec.rb +22 -9
- data/spec/plugin/mailer_spec.rb +72 -58
- data/spec/plugin/match_affix_spec.rb +2 -2
- data/spec/plugin/middleware_spec.rb +7 -7
- data/spec/plugin/module_include_spec.rb +4 -4
- data/spec/plugin/multi_route_spec.rb +66 -66
- data/spec/plugin/multi_run_spec.rb +21 -21
- data/spec/plugin/named_templates_spec.rb +6 -6
- data/spec/plugin/not_allowed_spec.rb +17 -17
- data/spec/plugin/not_found_spec.rb +14 -14
- data/spec/plugin/padrino_render_spec.rb +2 -2
- data/spec/plugin/param_matchers_spec.rb +6 -6
- data/spec/plugin/partials_spec.rb +3 -3
- data/spec/plugin/pass_spec.rb +7 -7
- data/spec/plugin/path_matchers_spec.rb +6 -6
- data/spec/plugin/path_rewriter_spec.rb +37 -0
- data/spec/plugin/path_spec.rb +41 -40
- data/spec/plugin/per_thread_caching_spec.rb +6 -6
- data/spec/plugin/precompile_templates_spec.rb +74 -0
- data/spec/plugin/render_each_spec.rb +4 -4
- data/spec/plugin/render_spec.rb +179 -76
- data/spec/plugin/shared_vars_spec.rb +4 -4
- data/spec/plugin/sinatra_helpers_spec.rb +121 -121
- data/spec/plugin/slash_path_empty_spec.rb +10 -10
- data/spec/plugin/static_spec.rb +4 -4
- data/spec/plugin/streaming_spec.rb +11 -11
- data/spec/plugin/symbol_matchers_spec.rb +24 -24
- data/spec/plugin/symbol_views_spec.rb +3 -3
- data/spec/plugin/view_options_spec.rb +10 -10
- data/spec/plugin_spec.rb +2 -2
- data/spec/redirect_spec.rb +10 -10
- data/spec/request_spec.rb +8 -8
- data/spec/response_spec.rb +23 -23
- data/spec/session_spec.rb +4 -4
- data/spec/spec_helper.rb +5 -19
- data/spec/version_spec.rb +4 -4
- data/spec/views/iv.erb +1 -0
- metadata +16 -5
@@ -21,6 +21,8 @@ class Roda
|
|
21
21
|
# the render plugin options, but lower precedence than options
|
22
22
|
# you directly pass to the view/render methods.
|
23
23
|
#
|
24
|
+
# = View Subdirectories
|
25
|
+
#
|
24
26
|
# The view_options plugin also has special support for sites
|
25
27
|
# that have outgrown a flat view directory and use subdirectories
|
26
28
|
# for views. It allows you to set the view directory to
|
@@ -50,6 +52,29 @@ class Roda
|
|
50
52
|
# a slash. So if you want to use a view subdirectory for
|
51
53
|
# templates but have a shared layout, you should make sure your
|
52
54
|
# layout contains a slash, similar to the example above.
|
55
|
+
#
|
56
|
+
# = Per-branch HTML escaping
|
57
|
+
#
|
58
|
+
# If you have an existing Roda application that doesn't use
|
59
|
+
# automatic HTML escaping for <tt><%= %></tt> tags via the
|
60
|
+
# :render plugin's :escape option, but you want to switch to
|
61
|
+
# using the :escape option, you can now do so without making
|
62
|
+
# all changes at once. With set_view_options, you can now
|
63
|
+
# specify escaping or not on a per branch basis in the routing
|
64
|
+
# tree:
|
65
|
+
#
|
66
|
+
# plugin :render, :escape=>true
|
67
|
+
# plugin :view_options
|
68
|
+
#
|
69
|
+
# route do |r|
|
70
|
+
# # Don't escape <%= %> by default
|
71
|
+
# set_view_options :template_opts=>{:engine_class=>nil}
|
72
|
+
#
|
73
|
+
# r.on "users" do
|
74
|
+
# # Escape <%= %> in this branch
|
75
|
+
# set_view_options :template_opts=>{:engine_class=>render_opts[:template_opts][:engine_class]}
|
76
|
+
# end
|
77
|
+
# end
|
53
78
|
module ViewOptions
|
54
79
|
# Load the render plugin before this plugin, since this plugin
|
55
80
|
# works by overriding methods in the render plugin.
|
@@ -69,7 +94,7 @@ class Roda
|
|
69
94
|
module_eval(<<-END, __FILE__, __LINE__+1)
|
70
95
|
def set#{v}(opts)
|
71
96
|
if @#{v}
|
72
|
-
@#{v} = @#{v}.merge(opts)
|
97
|
+
@#{v} = Hash[@#{v}].merge!(opts)
|
73
98
|
else
|
74
99
|
@#{v} = opts
|
75
100
|
end
|
@@ -112,7 +137,7 @@ class Roda
|
|
112
137
|
|
113
138
|
if v_locals = @_view_locals
|
114
139
|
t_opts[:locals] = if t_locals = t_opts[:locals]
|
115
|
-
v_locals.merge(t_locals)
|
140
|
+
Hash[v_locals].merge!(t_locals)
|
116
141
|
else
|
117
142
|
v_locals
|
118
143
|
end
|
@@ -133,7 +158,7 @@ class Roda
|
|
133
158
|
|
134
159
|
if l_locals = @_layout_locals
|
135
160
|
opts[:locals] = if o_locals = opts[:locals]
|
136
|
-
o_locals.merge(l_locals)
|
161
|
+
Hash[o_locals].merge!(l_locals)
|
137
162
|
else
|
138
163
|
l_locals
|
139
164
|
end
|
data/lib/roda/version.rb
CHANGED
data/spec/composition_spec.rb
CHANGED
@@ -14,18 +14,18 @@ describe "r.run" do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
body("/provider/services/101").
|
17
|
+
body("/provider/services/101").must_equal 'View 101'
|
18
18
|
end
|
19
19
|
|
20
20
|
it "modifies SCRIPT_NAME/PATH_INFO when calling run" do
|
21
21
|
a = app{|r| "#{r.script_name}|#{r.path_info}"}
|
22
22
|
app(:static_path_info){|r| r.on("a"){r.run a}}
|
23
|
-
body("/a/b").
|
23
|
+
body("/a/b").must_equal "/a|/b"
|
24
24
|
end
|
25
25
|
|
26
26
|
it "restores SCRIPT_NAME/PATH_INFO before returning from run" do
|
27
27
|
a = app{|r| "#{r.script_name}|#{r.path_info}"}
|
28
28
|
app(:static_path_info){|r| s = catch(:halt){r.on("a"){r.run a}}; "#{s[2].join}%#{r.script_name}|#{r.path_info}"}
|
29
|
-
body("/a/b").
|
29
|
+
body("/a/b").must_equal "/a|/b%|/a/b"
|
30
30
|
end
|
31
31
|
end
|
data/spec/env_spec.rb
CHANGED
data/spec/freeze_spec.rb
CHANGED
@@ -6,23 +6,23 @@ describe "Roda.freeze" do
|
|
6
6
|
end
|
7
7
|
|
8
8
|
it "should make opts not be modifiable after calling finalize!" do
|
9
|
-
proc{app.opts[:foo] = 'bar'}.
|
9
|
+
proc{app.opts[:foo] = 'bar'}.must_raise FrozenError
|
10
10
|
end
|
11
11
|
|
12
12
|
it "should make use and route raise errors" do
|
13
|
-
proc{app.use Class.new}.
|
14
|
-
proc{app.route{}}.
|
13
|
+
proc{app.use Class.new}.must_raise FrozenError
|
14
|
+
proc{app.route{}}.must_raise FrozenError
|
15
15
|
end
|
16
16
|
|
17
17
|
it "should make plugin raise errors" do
|
18
|
-
proc{app.plugin Module.new}.
|
18
|
+
proc{app.plugin Module.new}.must_raise Roda::RodaError
|
19
19
|
end
|
20
20
|
|
21
21
|
it "should make subclassing raise errors" do
|
22
|
-
proc{Class.new(app)}.
|
22
|
+
proc{Class.new(app)}.must_raise Roda::RodaError
|
23
23
|
end
|
24
24
|
|
25
25
|
it "should freeze app" do
|
26
|
-
app.frozen?.
|
26
|
+
app.frozen?.must_equal true
|
27
27
|
end
|
28
28
|
end
|
data/spec/integration_spec.rb
CHANGED
@@ -32,7 +32,7 @@ describe "integration" do
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
body('/hello').
|
35
|
+
body('/hello').must_equal 'D First Second Block'
|
36
36
|
end
|
37
37
|
|
38
38
|
it "should clear middleware when clear_middleware! is called" do
|
@@ -51,7 +51,7 @@ describe "integration" do
|
|
51
51
|
clear_middleware!
|
52
52
|
end
|
53
53
|
|
54
|
-
body('/hello').
|
54
|
+
body('/hello').must_equal 'D '
|
55
55
|
end
|
56
56
|
|
57
57
|
it "should support adding middleware using use after route block setup" do
|
@@ -68,7 +68,7 @@ describe "integration" do
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
-
body('/hello').
|
71
|
+
body('/hello').must_equal 'D First Second Block'
|
72
72
|
end
|
73
73
|
|
74
74
|
it "should inherit middleware in subclass" do
|
@@ -80,7 +80,7 @@ describe "integration" do
|
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
-
body('/hello').
|
83
|
+
body('/hello').must_equal 'D 1 2 3'
|
84
84
|
end
|
85
85
|
|
86
86
|
it "should not inherit middleware in subclass if inhert_middleware = false" do
|
@@ -94,7 +94,7 @@ describe "integration" do
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
-
body('/hello').
|
97
|
+
body('/hello').must_equal 'D '
|
98
98
|
end
|
99
99
|
|
100
100
|
it "should inherit route in subclass" do
|
@@ -109,7 +109,7 @@ describe "integration" do
|
|
109
109
|
end
|
110
110
|
@app = Class.new(app)
|
111
111
|
|
112
|
-
body('/hello').
|
112
|
+
body('/hello').must_equal 'D 1 2 3'
|
113
113
|
end
|
114
114
|
|
115
115
|
it "should use instance of subclass when inheriting routes" do
|
@@ -126,8 +126,8 @@ describe "integration" do
|
|
126
126
|
end
|
127
127
|
@app = Class.new(app)
|
128
128
|
|
129
|
-
body('/hello').
|
130
|
-
obj.
|
129
|
+
body('/hello').must_equal 'D 1 2 3'
|
130
|
+
obj.must_be_kind_of(@app)
|
131
131
|
end
|
132
132
|
|
133
133
|
it "should handle middleware added to subclass using superclass route" do
|
@@ -142,7 +142,7 @@ describe "integration" do
|
|
142
142
|
@app = Class.new(app)
|
143
143
|
@app.use(c, '1', '2'){"3"}
|
144
144
|
|
145
|
-
body('/hello').
|
145
|
+
body('/hello').must_equal 'D 1 2 3'
|
146
146
|
end
|
147
147
|
|
148
148
|
it "should not have future middleware additions to superclass affect subclass" do
|
@@ -156,7 +156,7 @@ describe "integration" do
|
|
156
156
|
end
|
157
157
|
a.use(c, '1', '2'){"3"}
|
158
158
|
|
159
|
-
body('/hello').
|
159
|
+
body('/hello').must_equal 'D '
|
160
160
|
end
|
161
161
|
|
162
162
|
it "should not have future middleware additions to subclass affect superclass" do
|
@@ -170,19 +170,20 @@ describe "integration" do
|
|
170
170
|
@app.use(c, '1', '2'){"3"}
|
171
171
|
@app = a
|
172
172
|
|
173
|
-
body('/hello').
|
173
|
+
body('/hello').must_equal 'D '
|
174
174
|
end
|
175
175
|
|
176
176
|
it "should have app return the rack application to call" do
|
177
|
-
app(:bare){}.app.
|
177
|
+
app(:bare){}.app.must_equal nil
|
178
178
|
app.route{|r|}
|
179
|
-
|
179
|
+
# Work around minitest bug
|
180
|
+
assert_kind_of Proc, app.app
|
180
181
|
c = Class.new{def initialize(app) @app = app end; def call(env) @app.call(env) end}
|
181
182
|
app.use c
|
182
|
-
app.app.
|
183
|
+
app.app.must_be_kind_of(c)
|
183
184
|
end
|
184
185
|
|
185
186
|
it "should have route_block return the route block" do
|
186
|
-
app{|r| 1}.route_block.call(nil).
|
187
|
+
app{|r| 1}.route_block.call(nil).must_equal 1
|
187
188
|
end
|
188
189
|
end
|
data/spec/matchers_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe "capturing" do
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
body.
|
11
|
+
body.must_equal '0'
|
12
12
|
end
|
13
13
|
|
14
14
|
it "doesn't yield the path" do
|
@@ -18,7 +18,7 @@ describe "capturing" do
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
body('/home').
|
21
|
+
body('/home').must_equal '0'
|
22
22
|
end
|
23
23
|
|
24
24
|
it "yields the segment" do
|
@@ -28,7 +28,7 @@ describe "capturing" do
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
body("/user/johndoe").
|
31
|
+
body("/user/johndoe").must_equal 'johndoe'
|
32
32
|
end
|
33
33
|
|
34
34
|
it "yields a number" do
|
@@ -38,7 +38,7 @@ describe "capturing" do
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
body("/user/101").
|
41
|
+
body("/user/101").must_equal '101'
|
42
42
|
end
|
43
43
|
|
44
44
|
it "yields a segment per nested block" do
|
@@ -52,7 +52,7 @@ describe "capturing" do
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
body("/one/two/three").
|
55
|
+
body("/one/two/three").must_equal "onetwothree"
|
56
56
|
end
|
57
57
|
|
58
58
|
it "regex captures in regex format" do
|
@@ -62,7 +62,7 @@ describe "capturing" do
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
body("/posts/123-postal-service").
|
65
|
+
body("/posts/123-postal-service").must_equal "123postal-service"
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
@@ -74,8 +74,8 @@ describe "r.is" do
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
body.
|
78
|
-
status('//').
|
77
|
+
body.must_equal '+1'
|
78
|
+
status('//').must_equal 404
|
79
79
|
end
|
80
80
|
|
81
81
|
it "handles no arguments" do
|
@@ -87,8 +87,8 @@ describe "r.is" do
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
-
body.
|
91
|
-
status('//').
|
90
|
+
body.must_equal '+1'
|
91
|
+
status('//').must_equal 404
|
92
92
|
end
|
93
93
|
|
94
94
|
it "matches strings" do
|
@@ -98,8 +98,8 @@ describe "r.is" do
|
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
|
-
body("/123").
|
102
|
-
status("/123/").
|
101
|
+
body("/123").must_equal '+1'
|
102
|
+
status("/123/").must_equal 404
|
103
103
|
end
|
104
104
|
|
105
105
|
it "matches regexps" do
|
@@ -109,8 +109,8 @@ describe "r.is" do
|
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
|
-
body("/123").
|
113
|
-
status("/123/").
|
112
|
+
body("/123").must_equal '123'
|
113
|
+
status("/123/").must_equal 404
|
114
114
|
end
|
115
115
|
|
116
116
|
it "matches segments" do
|
@@ -120,8 +120,8 @@ describe "r.is" do
|
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
123
|
-
body("/123").
|
124
|
-
status("/123/").
|
123
|
+
body("/123").must_equal '123'
|
124
|
+
status("/123/").must_equal 404
|
125
125
|
end
|
126
126
|
end
|
127
127
|
|
@@ -133,8 +133,8 @@ describe "matchers" do
|
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
136
|
-
body('/posts/123').
|
137
|
-
status('/post/123').
|
136
|
+
body('/posts/123').must_equal '123'
|
137
|
+
status('/post/123').must_equal 404
|
138
138
|
end
|
139
139
|
|
140
140
|
it "should handle multiple params in single string" do
|
@@ -144,8 +144,8 @@ describe "matchers" do
|
|
144
144
|
end
|
145
145
|
end
|
146
146
|
|
147
|
-
body("/u/jdoe/posts/123").
|
148
|
-
status("/u/jdoe/pots/123").
|
147
|
+
body("/u/jdoe/posts/123").must_equal 'jdoe123'
|
148
|
+
status("/u/jdoe/pots/123").must_equal 404
|
149
149
|
end
|
150
150
|
|
151
151
|
it "should escape regexp metacharaters in string" do
|
@@ -155,8 +155,8 @@ describe "matchers" do
|
|
155
155
|
end
|
156
156
|
end
|
157
157
|
|
158
|
-
body("/u/jdoe/posts?/123").
|
159
|
-
status("/u/jdoe/post/123").
|
158
|
+
body("/u/jdoe/posts?/123").must_equal 'jdoe123'
|
159
|
+
status("/u/jdoe/post/123").must_equal 404
|
160
160
|
end
|
161
161
|
|
162
162
|
it "should handle colons by themselves" do
|
@@ -166,8 +166,8 @@ describe "matchers" do
|
|
166
166
|
end
|
167
167
|
end
|
168
168
|
|
169
|
-
body("/u/:/jdoe/posts/:123").
|
170
|
-
status("/u/a/jdoe/post/b123").
|
169
|
+
body("/u/:/jdoe/posts/:123").must_equal 'jdoe123'
|
170
|
+
status("/u/a/jdoe/post/b123").must_equal 404
|
171
171
|
end
|
172
172
|
|
173
173
|
it "should handle regexes and nesting" do
|
@@ -179,8 +179,8 @@ describe "matchers" do
|
|
179
179
|
end
|
180
180
|
end
|
181
181
|
|
182
|
-
body("/u/jdoe/posts/123").
|
183
|
-
status("/u/jdoe/pots/123").
|
182
|
+
body("/u/jdoe/posts/123").must_equal 'jdoe123'
|
183
|
+
status("/u/jdoe/pots/123").must_equal 404
|
184
184
|
end
|
185
185
|
|
186
186
|
it "should handle regex nesting colon param style" do
|
@@ -192,8 +192,8 @@ describe "matchers" do
|
|
192
192
|
end
|
193
193
|
end
|
194
194
|
|
195
|
-
body("/u:jdoe/posts:123").
|
196
|
-
status("/u:jdoe/poss:123").
|
195
|
+
body("/u:jdoe/posts:123").must_equal 'jdoe123'
|
196
|
+
status("/u:jdoe/poss:123").must_equal 404
|
197
197
|
end
|
198
198
|
|
199
199
|
it "symbol matching" do
|
@@ -205,8 +205,8 @@ describe "matchers" do
|
|
205
205
|
end
|
206
206
|
end
|
207
207
|
|
208
|
-
body("/user/jdoe/posts/123").
|
209
|
-
status("/user/jdoe/pots/123").
|
208
|
+
body("/user/jdoe/posts/123").must_equal 'jdoe123'
|
209
|
+
status("/user/jdoe/pots/123").must_equal 404
|
210
210
|
end
|
211
211
|
|
212
212
|
it "paths and numbers" do
|
@@ -218,8 +218,8 @@ describe "matchers" do
|
|
218
218
|
end
|
219
219
|
end
|
220
220
|
|
221
|
-
body("/about/1/2").
|
222
|
-
status("/about/1").
|
221
|
+
body("/about/1/2").must_equal '12'
|
222
|
+
status("/about/1").must_equal 404
|
223
223
|
end
|
224
224
|
|
225
225
|
it "paths and decimals" do
|
@@ -231,8 +231,8 @@ describe "matchers" do
|
|
231
231
|
end
|
232
232
|
end
|
233
233
|
|
234
|
-
body("/about/1").
|
235
|
-
status("/about/1.2").
|
234
|
+
body("/about/1").must_equal '1'
|
235
|
+
status("/about/1.2").must_equal 404
|
236
236
|
end
|
237
237
|
|
238
238
|
it "should allow arrays to match any value" do
|
@@ -242,9 +242,9 @@ describe "matchers" do
|
|
242
242
|
end
|
243
243
|
end
|
244
244
|
|
245
|
-
body('/123').
|
246
|
-
body('/123bar').
|
247
|
-
status('/123bard').
|
245
|
+
body('/123').must_equal '123'
|
246
|
+
body('/123bar').must_equal 'bar'
|
247
|
+
status('/123bard').must_equal 404
|
248
248
|
end
|
249
249
|
|
250
250
|
it "should have array capture match string if match" do
|
@@ -254,9 +254,9 @@ describe "matchers" do
|
|
254
254
|
end
|
255
255
|
end
|
256
256
|
|
257
|
-
body('/p').
|
258
|
-
body('/q').
|
259
|
-
status('/r').
|
257
|
+
body('/p').must_equal 'p'
|
258
|
+
body('/q').must_equal 'q'
|
259
|
+
status('/r').must_equal 404
|
260
260
|
end
|
261
261
|
end
|
262
262
|
|
@@ -268,7 +268,7 @@ describe "r.on" do
|
|
268
268
|
end
|
269
269
|
end
|
270
270
|
|
271
|
-
body.
|
271
|
+
body.must_equal '+1'
|
272
272
|
end
|
273
273
|
|
274
274
|
it "executes on true" do
|
@@ -278,7 +278,7 @@ describe "r.on" do
|
|
278
278
|
end
|
279
279
|
end
|
280
280
|
|
281
|
-
body.
|
281
|
+
body.must_equal '+1'
|
282
282
|
end
|
283
283
|
|
284
284
|
it "executes on non-false" do
|
@@ -288,7 +288,7 @@ describe "r.on" do
|
|
288
288
|
end
|
289
289
|
end
|
290
290
|
|
291
|
-
body("/123").
|
291
|
+
body("/123").must_equal '+1'
|
292
292
|
end
|
293
293
|
|
294
294
|
it "does not modify SCRIPT_NAME/PATH_INFO during routing" do
|
@@ -305,14 +305,14 @@ describe "r.on" do
|
|
305
305
|
"#{env['SCRIPT_NAME']}|#{env['PATH_INFO']}"
|
306
306
|
end
|
307
307
|
|
308
|
-
body.
|
309
|
-
body('SCRIPT_NAME'=>'/a').
|
310
|
-
body('/foo').
|
311
|
-
body('/foo', 'SCRIPT_NAME'=>'/a').
|
312
|
-
body('/foo/bar').
|
313
|
-
body('/foo/bar', 'SCRIPT_NAME'=>'/a').
|
314
|
-
body('/foo/baz').
|
315
|
-
body('/foo/baz', 'SCRIPT_NAME'=>'/a').
|
308
|
+
body.must_equal '|/'
|
309
|
+
body('SCRIPT_NAME'=>'/a').must_equal '/a|/'
|
310
|
+
body('/foo').must_equal 'foo||/foo'
|
311
|
+
body('/foo', 'SCRIPT_NAME'=>'/a').must_equal 'foo|/a|/foo'
|
312
|
+
body('/foo/bar').must_equal 'bar||/foo/bar'
|
313
|
+
body('/foo/bar', 'SCRIPT_NAME'=>'/a').must_equal 'bar|/a|/foo/bar'
|
314
|
+
body('/foo/baz').must_equal 'foo||/foo/baz'
|
315
|
+
body('/foo/baz', 'SCRIPT_NAME'=>'/a').must_equal 'foo|/a|/foo/baz'
|
316
316
|
end
|
317
317
|
|
318
318
|
it "should have path/matched_path/remaining_path work correctly" do
|
@@ -322,7 +322,7 @@ describe "r.on" do
|
|
322
322
|
end
|
323
323
|
end
|
324
324
|
|
325
|
-
body("/foo/bar").
|
325
|
+
body("/foo/bar").must_equal "/foo/bar:/foo:/bar"
|
326
326
|
end
|
327
327
|
|
328
328
|
it "ensures remaining_path is reverted if modified in failing matcher" do
|
@@ -336,7 +336,7 @@ describe "r.on" do
|
|
336
336
|
end
|
337
337
|
end
|
338
338
|
|
339
|
-
body("/hello").
|
339
|
+
body("/hello").must_equal ':/hello'
|
340
340
|
end
|
341
341
|
|
342
342
|
it "modifies matched_path/remaining_path during routing" do
|
@@ -350,7 +350,7 @@ describe "r.on" do
|
|
350
350
|
end
|
351
351
|
end
|
352
352
|
|
353
|
-
body("/hello/you").
|
353
|
+
body("/hello/you").must_equal '/hello:/you'
|
354
354
|
end
|
355
355
|
|
356
356
|
it "doesn't modify SCRIPT_NAME/PATH_INFO during routing" do
|
@@ -364,7 +364,7 @@ describe "r.on" do
|
|
364
364
|
end
|
365
365
|
end
|
366
366
|
|
367
|
-
body("/hello/you").
|
367
|
+
body("/hello/you").must_equal ':/hello/you'
|
368
368
|
end
|
369
369
|
|
370
370
|
it "doesn't mutate SCRIPT_NAME or PATH_INFO after request is returned" do
|
@@ -380,9 +380,9 @@ describe "r.on" do
|
|
380
380
|
|
381
381
|
pi, sn = '/login', ''
|
382
382
|
env = {"REQUEST_METHOD" => "GET", "PATH_INFO" => pi, "SCRIPT_NAME" => sn}
|
383
|
-
app.call(env)[2].join.
|
384
|
-
env["PATH_INFO"].
|
385
|
-
env["SCRIPT_NAME"].
|
383
|
+
app.call(env)[2].join.must_equal ":/login"
|
384
|
+
env["PATH_INFO"].must_equal pi
|
385
|
+
env["SCRIPT_NAME"].must_equal sn
|
386
386
|
end
|
387
387
|
|
388
388
|
it "skips consecutive matches" do
|
@@ -396,7 +396,7 @@ describe "r.on" do
|
|
396
396
|
end
|
397
397
|
end
|
398
398
|
|
399
|
-
body.
|
399
|
+
body.must_equal "foo"
|
400
400
|
end
|
401
401
|
|
402
402
|
it "finds first match available" do
|
@@ -410,7 +410,7 @@ describe "r.on" do
|
|
410
410
|
end
|
411
411
|
end
|
412
412
|
|
413
|
-
body.
|
413
|
+
body.must_equal "bar"
|
414
414
|
end
|
415
415
|
|
416
416
|
it "reverts a half-met matcher" do
|
@@ -424,7 +424,7 @@ describe "r.on" do
|
|
424
424
|
end
|
425
425
|
end
|
426
426
|
|
427
|
-
body("/hello").
|
427
|
+
body("/hello").must_equal ':/hello'
|
428
428
|
end
|
429
429
|
|
430
430
|
it "doesn't write to body if body already written to" do
|
@@ -435,7 +435,7 @@ describe "r.on" do
|
|
435
435
|
end
|
436
436
|
end
|
437
437
|
|
438
|
-
body.
|
438
|
+
body.must_equal 'a'
|
439
439
|
end
|
440
440
|
end
|
441
441
|
|
@@ -447,8 +447,8 @@ describe "path matchers" do
|
|
447
447
|
end
|
448
448
|
end
|
449
449
|
|
450
|
-
body('/about').
|
451
|
-
status("/abot").
|
450
|
+
body('/about').must_equal "About"
|
451
|
+
status("/abot").must_equal 404
|
452
452
|
end
|
453
453
|
|
454
454
|
it "two level nested paths" do
|
@@ -464,9 +464,9 @@ describe "path matchers" do
|
|
464
464
|
end
|
465
465
|
end
|
466
466
|
|
467
|
-
body('/about/1').
|
468
|
-
body('/about/2').
|
469
|
-
status('/about/3').
|
467
|
+
body('/about/1').must_equal "+1"
|
468
|
+
body('/about/2').must_equal "+2"
|
469
|
+
status('/about/3').must_equal 404
|
470
470
|
end
|
471
471
|
|
472
472
|
it "two level inlined paths" do
|
@@ -476,8 +476,8 @@ describe "path matchers" do
|
|
476
476
|
end
|
477
477
|
end
|
478
478
|
|
479
|
-
body('/a/b').
|
480
|
-
status('/a/d').
|
479
|
+
body('/a/b').must_equal "ab"
|
480
|
+
status('/a/d').must_equal 404
|
481
481
|
end
|
482
482
|
|
483
483
|
it "a path with some regex captures" do
|
@@ -487,8 +487,8 @@ describe "path matchers" do
|
|
487
487
|
end
|
488
488
|
end
|
489
489
|
|
490
|
-
body('/user123').
|
491
|
-
status('/useradf').
|
490
|
+
body('/user123').must_equal "123"
|
491
|
+
status('/useradf').must_equal 404
|
492
492
|
end
|
493
493
|
|
494
494
|
it "matching the root with a string" do
|
@@ -498,9 +498,9 @@ describe "path matchers" do
|
|
498
498
|
end
|
499
499
|
end
|
500
500
|
|
501
|
-
body.
|
502
|
-
status("//").
|
503
|
-
status("/foo").
|
501
|
+
body.must_equal 'Home'
|
502
|
+
status("//").must_equal 404
|
503
|
+
status("/foo").must_equal 404
|
504
504
|
end
|
505
505
|
|
506
506
|
it "matching the root with the root method" do
|
@@ -510,10 +510,10 @@ describe "path matchers" do
|
|
510
510
|
end
|
511
511
|
end
|
512
512
|
|
513
|
-
body.
|
514
|
-
status('REQUEST_METHOD'=>'POST').
|
515
|
-
status("//").
|
516
|
-
status("/foo").
|
513
|
+
body.must_equal 'Home'
|
514
|
+
status('REQUEST_METHOD'=>'POST').must_equal 404
|
515
|
+
status("//").must_equal 404
|
516
|
+
status("/foo").must_equal 404
|
517
517
|
end
|
518
518
|
end
|
519
519
|
|
@@ -525,8 +525,8 @@ describe "root/empty segment matching" do
|
|
525
525
|
end
|
526
526
|
end
|
527
527
|
|
528
|
-
body.
|
529
|
-
status("/foo").
|
528
|
+
body.must_equal '/'
|
529
|
+
status("/foo").must_equal 404
|
530
530
|
end
|
531
531
|
|
532
532
|
it "nested empty segments" do
|
@@ -540,9 +540,9 @@ describe "root/empty segment matching" do
|
|
540
540
|
end
|
541
541
|
end
|
542
542
|
|
543
|
-
body("///1").
|
544
|
-
status("/1").
|
545
|
-
status("//1").
|
543
|
+
body("///1").must_equal '///1'
|
544
|
+
status("/1").must_equal 404
|
545
|
+
status("//1").must_equal 404
|
546
546
|
end
|
547
547
|
|
548
548
|
it "/events/? scenario" do
|
@@ -562,9 +562,9 @@ describe "root/empty segment matching" do
|
|
562
562
|
end
|
563
563
|
end
|
564
564
|
|
565
|
-
body("/events").
|
566
|
-
body("/events/").
|
567
|
-
status("/events/foo").
|
565
|
+
body("/events").must_equal 'Foo'
|
566
|
+
body("/events/").must_equal 'Hooray'
|
567
|
+
status("/events/foo").must_equal 404
|
568
568
|
end
|
569
569
|
end
|
570
570
|
|
@@ -580,19 +580,19 @@ describe "segment handling" do
|
|
580
580
|
end
|
581
581
|
|
582
582
|
it "matches numeric ids" do
|
583
|
-
body('/post/1').
|
583
|
+
body('/post/1').must_equal '1'
|
584
584
|
end
|
585
585
|
|
586
586
|
it "matches decimal numbers" do
|
587
|
-
body('/post/1.1').
|
587
|
+
body('/post/1.1').must_equal '1.1'
|
588
588
|
end
|
589
589
|
|
590
590
|
it "matches slugs" do
|
591
|
-
body('/post/my-blog-post-about-cuba').
|
591
|
+
body('/post/my-blog-post-about-cuba').must_equal 'my-blog-post-about-cuba'
|
592
592
|
end
|
593
593
|
|
594
594
|
it "matches only the first segment available" do
|
595
|
-
body('/post/one/two/three').
|
595
|
+
body('/post/one/two/three').must_equal 'one'
|
596
596
|
end
|
597
597
|
end
|
598
598
|
|
@@ -607,8 +607,8 @@ describe "request verb methods" do
|
|
607
607
|
end
|
608
608
|
end
|
609
609
|
|
610
|
-
body.
|
611
|
-
body('REQUEST_METHOD'=>'POST').
|
610
|
+
body.must_equal 'g'
|
611
|
+
body('REQUEST_METHOD'=>'POST').must_equal 'p'
|
612
612
|
end
|
613
613
|
|
614
614
|
it "requires exact match if given arguments" do
|
@@ -621,10 +621,10 @@ describe "request verb methods" do
|
|
621
621
|
end
|
622
622
|
end
|
623
623
|
|
624
|
-
body.
|
625
|
-
body('REQUEST_METHOD'=>'POST').
|
626
|
-
status("/a").
|
627
|
-
status("/a", 'REQUEST_METHOD'=>'POST').
|
624
|
+
body.must_equal 'g'
|
625
|
+
body('REQUEST_METHOD'=>'POST').must_equal 'p'
|
626
|
+
status("/a").must_equal 404
|
627
|
+
status("/a", 'REQUEST_METHOD'=>'POST').must_equal 404
|
628
628
|
end
|
629
629
|
|
630
630
|
it "does not require exact match if given arguments" do
|
@@ -645,10 +645,10 @@ describe "request verb methods" do
|
|
645
645
|
end
|
646
646
|
end
|
647
647
|
|
648
|
-
body.
|
649
|
-
body('REQUEST_METHOD'=>'POST').
|
650
|
-
body("/a").
|
651
|
-
body("/a", 'REQUEST_METHOD'=>'POST').
|
648
|
+
body.must_equal 'g'
|
649
|
+
body('REQUEST_METHOD'=>'POST').must_equal 'p'
|
650
|
+
body("/a").must_equal 'get'
|
651
|
+
body("/a", 'REQUEST_METHOD'=>'POST').must_equal 'post'
|
652
652
|
end
|
653
653
|
end
|
654
654
|
|
@@ -660,11 +660,11 @@ describe "all matcher" do
|
|
660
660
|
end
|
661
661
|
end
|
662
662
|
|
663
|
-
body("/foo/bar").
|
664
|
-
status.
|
665
|
-
status("/foo").
|
666
|
-
status("/foo/").
|
667
|
-
status("/foo/bar/baz").
|
663
|
+
body("/foo/bar").must_equal 'bar'
|
664
|
+
status.must_equal 404
|
665
|
+
status("/foo").must_equal 404
|
666
|
+
status("/foo/").must_equal 404
|
667
|
+
status("/foo/bar/baz").must_equal 404
|
668
668
|
end
|
669
669
|
end
|
670
670
|
|
@@ -679,10 +679,10 @@ describe "method matcher" do
|
|
679
679
|
end
|
680
680
|
end
|
681
681
|
|
682
|
-
body("REQUEST_METHOD"=>"GET").
|
683
|
-
body("REQUEST_METHOD"=>"PATCH").
|
684
|
-
body("REQUEST_METHOD"=>"POST").
|
685
|
-
status("REQUEST_METHOD"=>"DELETE").
|
682
|
+
body("REQUEST_METHOD"=>"GET").must_equal 'foo'
|
683
|
+
body("REQUEST_METHOD"=>"PATCH").must_equal 'bar'
|
684
|
+
body("REQUEST_METHOD"=>"POST").must_equal 'bar'
|
685
|
+
status("REQUEST_METHOD"=>"DELETE").must_equal 404
|
686
686
|
end
|
687
687
|
end
|
688
688
|
|
@@ -692,6 +692,6 @@ describe "route block that returns string" do
|
|
692
692
|
"+1"
|
693
693
|
end
|
694
694
|
|
695
|
-
body.
|
695
|
+
body.must_equal '+1'
|
696
696
|
end
|
697
697
|
end
|