howl-router 0.1
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 +7 -0
- data/.travis.yml +13 -0
- data/Gemfile +3 -0
- data/README.md +132 -0
- data/Rakefile +10 -0
- data/config.ru +9 -0
- data/lib/howl-router.rb +163 -0
- data/lib/howl-router/matcher.rb +46 -0
- data/lib/howl-router/padrino.rb +17 -0
- data/lib/howl-router/padrino/core.rb +41 -0
- data/lib/howl-router/padrino/ext/class_methods.rb +179 -0
- data/lib/howl-router/padrino/ext/instance_methods.rb +60 -0
- data/lib/howl-router/padrino/matcher.rb +8 -0
- data/lib/howl-router/padrino/route.rb +45 -0
- data/lib/howl-router/padrino/router.rb +8 -0
- data/lib/howl-router/request.rb +7 -0
- data/lib/howl-router/route.rb +40 -0
- data/lib/howl-router/router.rb +70 -0
- data/lib/howl-router/version.rb +3 -0
- data/test/helper.rb +83 -0
- data/test/howl_test.rb +101 -0
- data/test/padrino_test.rb +1918 -0
- metadata +165 -0
data/test/howl_test.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require File.expand_path('../../lib/howl-router', __FILE__)
|
2
|
+
$:.unshift(File.dirname(__FILE__))
|
3
|
+
require 'helper'
|
4
|
+
|
5
|
+
describe Howl do
|
6
|
+
setup{ @howl = howl }
|
7
|
+
|
8
|
+
describe "normal routing" do
|
9
|
+
before(:each){ @howl.reset! }
|
10
|
+
|
11
|
+
should "basic route" do
|
12
|
+
@howl.add(:get, "/"){ "index" }
|
13
|
+
@howl.add(:get, "/users"){ "users" }
|
14
|
+
get("/")
|
15
|
+
assert_equal "index", body
|
16
|
+
get("/users")
|
17
|
+
assert_equal "users", body
|
18
|
+
end
|
19
|
+
|
20
|
+
should "ignore trailing delimiters for basic route" do
|
21
|
+
@howl.add(:get, "/"){ "index" }
|
22
|
+
@howl.add(:get, "/users"){ "users" }
|
23
|
+
|
24
|
+
get("")
|
25
|
+
assert_equal "index", body
|
26
|
+
get("/users/")
|
27
|
+
assert_equal "users", body
|
28
|
+
end
|
29
|
+
|
30
|
+
should "use pattern" do
|
31
|
+
@howl.add(:get, "/:id"){|params| "show #{params[:id]}" }
|
32
|
+
@howl.add(:get, "/:id.:ext"){|params| "show #{params[:id]}.#{params[:ext]}" }
|
33
|
+
|
34
|
+
get("/1")
|
35
|
+
assert_equal "show 1", body
|
36
|
+
get("/foo")
|
37
|
+
assert_equal "show foo", body
|
38
|
+
get("/1.json")
|
39
|
+
assert_equal "show 1.json", body
|
40
|
+
get("/foo.xml")
|
41
|
+
assert_equal "show foo.xml", body
|
42
|
+
end
|
43
|
+
|
44
|
+
should "use capture" do
|
45
|
+
id_route = @howl.add(:get, "/:id"){|params| "show #{params[:id]}" }
|
46
|
+
id_route.capture[:id] = /\d+/
|
47
|
+
|
48
|
+
id_with_ext_route = @howl.add(:get, "/:id.:ext"){|params| "show #{params[:id]}.#{params[:ext]}" }
|
49
|
+
id_with_ext_route.capture[:id] = /(foo|bar)/
|
50
|
+
id_with_ext_route.capture[:ext] = %w[html json]
|
51
|
+
|
52
|
+
get("/1")
|
53
|
+
assert_equal "show 1", body
|
54
|
+
get("/foo")
|
55
|
+
assert_equal "Not Found", body
|
56
|
+
get("/foo.json")
|
57
|
+
assert_equal "show foo.json", body
|
58
|
+
get("/baz.json")
|
59
|
+
assert_equal "Not Found", body
|
60
|
+
get("/foo.html")
|
61
|
+
assert_equal "show foo.html", body
|
62
|
+
get("/foo.xml")
|
63
|
+
assert_equal "Not Found", body
|
64
|
+
end
|
65
|
+
end
|
66
|
+
describe "regexp routing" do
|
67
|
+
before(:each){ @howl.reset! }
|
68
|
+
|
69
|
+
should "basic route of regexp" do
|
70
|
+
@howl.add(:get, /\/(\d+)/){|params| params[:captures].join(",") }
|
71
|
+
@howl.add(:get, /\/(foo|bar)(baz)?/){|params| params[:captures].compact.join(",") }
|
72
|
+
|
73
|
+
get("/123")
|
74
|
+
assert_equal "123", body
|
75
|
+
get("/foo")
|
76
|
+
assert_equal "foo", body
|
77
|
+
get("/foobaz")
|
78
|
+
assert_equal "foo,baz", body
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "generate path" do
|
83
|
+
before(:each){ @howl.reset! }
|
84
|
+
|
85
|
+
should "basic route of regexp" do
|
86
|
+
index = @howl.add(:get, "/"){}
|
87
|
+
index.name = :index
|
88
|
+
foo_bar = @howl.add(:post, "/foo/bar"){}
|
89
|
+
foo_bar.name = :foo_bar
|
90
|
+
users = @howl.add(:get, "/users/:user_id"){}
|
91
|
+
users.name = :users
|
92
|
+
|
93
|
+
assert_equal @howl.path(:index), "/"
|
94
|
+
assert_equal @howl.path(:foo_bar), "/foo/bar"
|
95
|
+
assert_equal @howl.path(:users, :user_id => 1), "/users/1"
|
96
|
+
assert_equal @howl.path(:users, :user_id => 1, :query => "string"), "/users/1?query=string"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
end
|
@@ -0,0 +1,1918 @@
|
|
1
|
+
require File.expand_path('../../lib/howl-router/padrino', __FILE__)
|
2
|
+
$:.unshift(File.dirname(__FILE__))
|
3
|
+
require 'helper'
|
4
|
+
|
5
|
+
class FooError < RuntimeError; end
|
6
|
+
|
7
|
+
describe "Howl::Padrino" do
|
8
|
+
setup do
|
9
|
+
Padrino::Application.send(:register, Padrino::Rendering)
|
10
|
+
Padrino::Application.send(:register, Howl::Padrino)
|
11
|
+
Padrino::Rendering::DEFAULT_RENDERING_OPTIONS[:strict_format] = false
|
12
|
+
end
|
13
|
+
|
14
|
+
should "serve static files with simple cache control" do
|
15
|
+
mock_app do
|
16
|
+
set :static_cache_control, :public
|
17
|
+
set :public_folder, File.dirname(__FILE__)
|
18
|
+
end
|
19
|
+
get "/#{File.basename(__FILE__)}"
|
20
|
+
assert headers.has_key?('Cache-Control')
|
21
|
+
assert_equal headers['Cache-Control'], 'public'
|
22
|
+
end # static simple
|
23
|
+
|
24
|
+
should "serve static files with cache control and max_age" do
|
25
|
+
mock_app do
|
26
|
+
set :static_cache_control, [:public, :must_revalidate, {:max_age => 300}]
|
27
|
+
set :public_folder, File.dirname(__FILE__)
|
28
|
+
end
|
29
|
+
get "/#{File.basename(__FILE__)}"
|
30
|
+
assert headers.has_key?('Cache-Control')
|
31
|
+
assert_equal headers['Cache-Control'], 'public, must-revalidate, max-age=300'
|
32
|
+
end # static max_age
|
33
|
+
|
34
|
+
should 'ignore trailing delimiters for basic route' do
|
35
|
+
mock_app do
|
36
|
+
get("/foo"){ "okey" }
|
37
|
+
get(:test) { "tester" }
|
38
|
+
end
|
39
|
+
get "/foo"
|
40
|
+
assert_equal "okey", body
|
41
|
+
get "/foo/"
|
42
|
+
assert_equal "okey", body
|
43
|
+
get "/test"
|
44
|
+
assert_equal "tester", body
|
45
|
+
get "/test/"
|
46
|
+
assert_equal "tester", body
|
47
|
+
end
|
48
|
+
|
49
|
+
should 'fail with unrecognized route exception when not found' do
|
50
|
+
mock_app do
|
51
|
+
get(:index){ "okey" }
|
52
|
+
end
|
53
|
+
get @app.url_for(:index)
|
54
|
+
assert_equal "okey", body
|
55
|
+
assert_raises(Padrino::Routing::UnrecognizedException) {
|
56
|
+
get @app.url_for(:fake)
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
should 'accept regexp routes' do
|
61
|
+
mock_app do
|
62
|
+
get(%r./fob|/baz.) { "regexp" }
|
63
|
+
get("/foo") { "str" }
|
64
|
+
get %r./([0-9]+)/. do |num|
|
65
|
+
"Your lucky number: #{num} #{params[:captures].first}"
|
66
|
+
end
|
67
|
+
get %r./page/([0-9]+)|/. do |num|
|
68
|
+
"My lucky number: #{num} #{params[:captures].first}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
get "/foo"
|
72
|
+
assert_equal "str", body
|
73
|
+
get "/fob"
|
74
|
+
assert_equal "regexp", body
|
75
|
+
get "/baz"
|
76
|
+
assert_equal "regexp", body
|
77
|
+
get "/321/"
|
78
|
+
assert_equal "Your lucky number: 321 321", body
|
79
|
+
get "/page/99"
|
80
|
+
assert_equal "My lucky number: 99 99", body
|
81
|
+
end
|
82
|
+
|
83
|
+
should 'accept regexp routes with generate with :generate_with' do
|
84
|
+
mock_app do
|
85
|
+
get(%r{/fob|/baz}, :name => :foo, :generate_with => '/fob') { "regexp" }
|
86
|
+
end
|
87
|
+
assert_equal "/fob", @app.url(:foo)
|
88
|
+
end
|
89
|
+
|
90
|
+
should "parse routes with question marks" do
|
91
|
+
mock_app do
|
92
|
+
get("/foo/?"){ "okey" }
|
93
|
+
post('/unauthenticated/?') { "no access" }
|
94
|
+
end
|
95
|
+
get "/foo"
|
96
|
+
assert_equal "okey", body
|
97
|
+
get "/foo/"
|
98
|
+
assert_equal "okey", body
|
99
|
+
post "/unauthenticated"
|
100
|
+
assert_equal "no access", body
|
101
|
+
post "/unauthenticated/"
|
102
|
+
assert_equal "no access", body
|
103
|
+
end
|
104
|
+
|
105
|
+
should 'parse routes that are encoded' do
|
106
|
+
mock_app do
|
107
|
+
get('/щч') { 'success!' }
|
108
|
+
end
|
109
|
+
get(URI.escape('/щч'))
|
110
|
+
assert_equal 'success!', body
|
111
|
+
end
|
112
|
+
|
113
|
+
should 'encode params using UTF-8' do
|
114
|
+
#skip unless ''.respond_to?(:encoding) # for 1.8.7
|
115
|
+
|
116
|
+
mock_app do
|
117
|
+
get('/:foo') { params[:foo].encoding.name }
|
118
|
+
end
|
119
|
+
get '/bar'
|
120
|
+
assert_equal 'UTF-8', body
|
121
|
+
end
|
122
|
+
|
123
|
+
should 'match correctly similar paths' do
|
124
|
+
mock_app do
|
125
|
+
get("/my/:foo_id"){ params[:foo_id] }
|
126
|
+
get("/my/:bar_id/bar"){ params[:bar_id] }
|
127
|
+
end
|
128
|
+
get "/my/1"
|
129
|
+
assert_equal "1", body
|
130
|
+
get "/my/2/bar"
|
131
|
+
assert_equal "2", body
|
132
|
+
end
|
133
|
+
|
134
|
+
should "match user agents" do
|
135
|
+
app = mock_app do
|
136
|
+
get("/main", :agent => /IE/){ "hello IE" }
|
137
|
+
get("/main"){ "hello" }
|
138
|
+
end
|
139
|
+
get "/main"
|
140
|
+
assert_equal "hello", body
|
141
|
+
get "/main", {}, {'HTTP_USER_AGENT' => 'This is IE'}
|
142
|
+
assert_equal "hello IE", body
|
143
|
+
end
|
144
|
+
|
145
|
+
should "use regex for parts of a route" do
|
146
|
+
app = mock_app do
|
147
|
+
get("/main/:id", :id => /\d+/){ "hello #{params[:id]}" }
|
148
|
+
end
|
149
|
+
get "/main/123"
|
150
|
+
assert_equal "hello 123", body
|
151
|
+
get "/main/asd"
|
152
|
+
assert_equal 404, status
|
153
|
+
end
|
154
|
+
|
155
|
+
should "parse params when use regex for parts of a route" do
|
156
|
+
mock_app do
|
157
|
+
post :index, :with => [:foo, :bar], :bar => /.+/ do
|
158
|
+
"show #{params[:foo]}"
|
159
|
+
end
|
160
|
+
|
161
|
+
get :index, :map => '/mystuff/:a_id/boing/:boing_id' do
|
162
|
+
"show #{params[:a_id]} and #{params[:boing_id]}"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
get "/mystuff/5/boing/2"
|
166
|
+
assert_equal "show 5 and 2", body
|
167
|
+
end
|
168
|
+
|
169
|
+
should "not generate overlapping head urls" do
|
170
|
+
app = mock_app do
|
171
|
+
get("/main"){ "hello" }
|
172
|
+
post("/main"){ "hello" }
|
173
|
+
end
|
174
|
+
assert_equal 3, app.routes.size, "should generate GET, HEAD and PUT"
|
175
|
+
assert_equal "GET", app.routes[0].request_methods.first
|
176
|
+
assert_equal "HEAD", app.routes[1].request_methods.first
|
177
|
+
assert_equal "POST", app.routes[2].request_methods.first
|
178
|
+
end
|
179
|
+
|
180
|
+
should 'generate basic urls' do
|
181
|
+
mock_app do
|
182
|
+
get(:foo){ "/foo" }
|
183
|
+
get(:foo, :with => :id){ |id| "/foo/#{id}" }
|
184
|
+
get([:foo, :id]){ |id| "/foo/#{id}" }
|
185
|
+
get(:hash, :with => :id){ url(:hash, :id => 1) }
|
186
|
+
get([:hash, :id]){ url(:hash, :id => 1) }
|
187
|
+
get(:array, :with => :id){ url(:array, 23) }
|
188
|
+
get([:array, :id]){ url(:array, 23) }
|
189
|
+
get(:hash_with_extra, :with => :id){ url(:hash_with_extra, :id => 1, :query => 'string') }
|
190
|
+
get([:hash_with_extra, :id]){ url(:hash_with_extra, :id => 1, :query => 'string') }
|
191
|
+
get(:array_with_extra, :with => :id){ url(:array_with_extra, 23, :query => 'string') }
|
192
|
+
get([:array_with_extra, :id]){ url(:array_with_extra, 23, :query => 'string') }
|
193
|
+
get("/old-bar/:id"){ params[:id] }
|
194
|
+
post(:mix, :map => "/mix-bar/:id"){ params[:id] }
|
195
|
+
get(:mix, :map => "/mix-bar/:id"){ params[:id] }
|
196
|
+
end
|
197
|
+
get "/foo"
|
198
|
+
assert_equal "/foo", body
|
199
|
+
get "/foo/123"
|
200
|
+
assert_equal "/foo/123", body
|
201
|
+
get "/hash/2"
|
202
|
+
assert_equal "/hash/1", body
|
203
|
+
get "/array/23"
|
204
|
+
assert_equal "/array/23", body
|
205
|
+
get "/hash_with_extra/1"
|
206
|
+
assert_equal "/hash_with_extra/1?query=string", body
|
207
|
+
get "/array_with_extra/23"
|
208
|
+
assert_equal "/array_with_extra/23?query=string", body
|
209
|
+
get "/old-bar/3"
|
210
|
+
assert_equal "3", body
|
211
|
+
post "/mix-bar/4"
|
212
|
+
assert_equal "4", body
|
213
|
+
get "/mix-bar/4"
|
214
|
+
assert_equal "4", body
|
215
|
+
end
|
216
|
+
|
217
|
+
should 'generate url with format' do
|
218
|
+
mock_app do
|
219
|
+
get(:a, :provides => :any){ url(:a, :format => :json) }
|
220
|
+
get(:b, :provides => :js){ url(:b, :format => :js) }
|
221
|
+
get(:c, :provides => [:js, :json]){ url(:c, :format => :json) }
|
222
|
+
get(:d, :provides => [:html, :js]){ url(:d, :format => :js, :foo => :bar) }
|
223
|
+
end
|
224
|
+
get "/a.js"
|
225
|
+
assert_equal "/a.json", body
|
226
|
+
get "/b.js"
|
227
|
+
assert_equal "/b.js", body
|
228
|
+
get "/b.ru"
|
229
|
+
assert_equal 404, status
|
230
|
+
get "/c.js"
|
231
|
+
assert_equal "/c.json", body
|
232
|
+
get "/c.json"
|
233
|
+
assert_equal "/c.json", body
|
234
|
+
get "/c.ru"
|
235
|
+
assert_equal 404, status
|
236
|
+
get "/d"
|
237
|
+
assert_equal "/d.js?foo=bar", body
|
238
|
+
get "/d.js"
|
239
|
+
assert_equal "/d.js?foo=bar", body
|
240
|
+
get "/e.xml"
|
241
|
+
assert_equal 404, status
|
242
|
+
end
|
243
|
+
|
244
|
+
should 'generate absolute urls' do
|
245
|
+
mock_app do
|
246
|
+
get(:hash, :with => :id){ absolute_url(:hash, :id => 1) }
|
247
|
+
end
|
248
|
+
get "/hash/2"
|
249
|
+
assert_equal "http://example.org/hash/1", body
|
250
|
+
get "https://example.org/hash/2"
|
251
|
+
assert_equal "https://example.org/hash/1", body
|
252
|
+
end
|
253
|
+
|
254
|
+
should 'generate proper absolute urls for mounted apps' do
|
255
|
+
class Test < Padrino::Application
|
256
|
+
get :foo do
|
257
|
+
absolute_url(:foo, :id => 1)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
Padrino.mount("Test").to("/test")
|
261
|
+
@app = Padrino.application
|
262
|
+
get('/test/foo')
|
263
|
+
assert_equal 'http://example.org/test/foo?id=1', body
|
264
|
+
end
|
265
|
+
|
266
|
+
should 'allow regex url with format' do
|
267
|
+
mock_app do
|
268
|
+
get(/.*/, :provides => :any) { "regexp" }
|
269
|
+
end
|
270
|
+
get "/anything"
|
271
|
+
assert_equal "regexp", body
|
272
|
+
end
|
273
|
+
|
274
|
+
should 'use padrino url method' do
|
275
|
+
mock_app do
|
276
|
+
end
|
277
|
+
|
278
|
+
assert_equal @app.method(:url).owner, Howl::Padrino::ClassMethods
|
279
|
+
end
|
280
|
+
|
281
|
+
should 'work correctly with sinatra redirects' do
|
282
|
+
mock_app do
|
283
|
+
get(:index) { redirect url(:index) }
|
284
|
+
get(:google) { redirect "http://google.com" }
|
285
|
+
get("/foo") { redirect "/bar" }
|
286
|
+
get("/bar") { "Bar" }
|
287
|
+
end
|
288
|
+
|
289
|
+
get "/"
|
290
|
+
assert_equal "http://example.org/", headers['Location']
|
291
|
+
get "/google"
|
292
|
+
assert_equal "http://google.com", headers['Location']
|
293
|
+
get "/foo"
|
294
|
+
assert_equal "http://example.org/bar", headers['Location']
|
295
|
+
end
|
296
|
+
|
297
|
+
should "return 406 on Accept-Headers it does not provide" do
|
298
|
+
mock_app do
|
299
|
+
get(:a, :provides => [:html, :js]){ content_type }
|
300
|
+
end
|
301
|
+
|
302
|
+
get "/a", {}, {"HTTP_ACCEPT" => "application/yaml"}
|
303
|
+
assert_equal 406, status
|
304
|
+
end
|
305
|
+
|
306
|
+
should "return 406 on file extensions it does not provide and flag is set" do
|
307
|
+
mock_app do
|
308
|
+
enable :treat_format_as_accept
|
309
|
+
get(:a, :provides => [:html, :js]){ content_type }
|
310
|
+
end
|
311
|
+
|
312
|
+
get "/a.xml", {}, {}
|
313
|
+
assert_equal 406, status
|
314
|
+
end
|
315
|
+
|
316
|
+
should "return 404 on file extensions it does not provide and flag is not set" do
|
317
|
+
mock_app do
|
318
|
+
get(:a, :provides => [:html, :js]){ content_type }
|
319
|
+
end
|
320
|
+
|
321
|
+
get "/a.xml", {}, {}
|
322
|
+
assert_equal 404, status
|
323
|
+
end
|
324
|
+
|
325
|
+
should "not set content_type to :html if Accept */* and html not in provides" do
|
326
|
+
mock_app do
|
327
|
+
get("/foo", :provides => [:json, :xml]) { content_type.to_s }
|
328
|
+
end
|
329
|
+
|
330
|
+
get '/foo', {}, { 'HTTP_ACCEPT' => '*/*;q=0.5' }
|
331
|
+
assert_equal 'json', body
|
332
|
+
end
|
333
|
+
|
334
|
+
should "set content_type to :json if Accept contains */*" do
|
335
|
+
mock_app do
|
336
|
+
get("/foo", :provides => [:json]) { content_type.to_s }
|
337
|
+
end
|
338
|
+
|
339
|
+
get '/foo', {}, { 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' }
|
340
|
+
assert_equal 'json', body
|
341
|
+
end
|
342
|
+
|
343
|
+
should 'set and get content_type' do
|
344
|
+
mock_app do
|
345
|
+
get("/foo"){ content_type(:json); content_type.to_s }
|
346
|
+
end
|
347
|
+
get "/foo"
|
348
|
+
assert_equal 'application/json;charset=utf-8', content_type
|
349
|
+
assert_equal 'json', body
|
350
|
+
end
|
351
|
+
|
352
|
+
should "send the appropriate number of params" do
|
353
|
+
mock_app do
|
354
|
+
get('/id/:user_id', :provides => [:json]) { |user_id, format| user_id}
|
355
|
+
end
|
356
|
+
get '/id/5.json'
|
357
|
+
assert_equal '5', body
|
358
|
+
end
|
359
|
+
|
360
|
+
should "allow .'s in param values" do
|
361
|
+
#skip
|
362
|
+
mock_app do
|
363
|
+
get('/id/:email', :provides => [:json]) { |email, format| [email, format] * '/' }
|
364
|
+
end
|
365
|
+
get '/id/foo@bar.com.json'
|
366
|
+
assert_equal 'foo@bar.com/json', body
|
367
|
+
end
|
368
|
+
|
369
|
+
should "set correct content_type for Accept not equal to */* even if */* also provided" do
|
370
|
+
mock_app do
|
371
|
+
get("/foo", :provides => [:html, :js, :xml]) { content_type.to_s }
|
372
|
+
end
|
373
|
+
|
374
|
+
get '/foo', {}, { 'HTTP_ACCEPT' => 'application/javascript, */*;q=0.5' }
|
375
|
+
assert_equal 'js', body
|
376
|
+
end
|
377
|
+
|
378
|
+
should "return the first content type in provides if accept header is empty" do
|
379
|
+
mock_app do
|
380
|
+
get(:a, :provides => [:js]){ content_type.to_s }
|
381
|
+
end
|
382
|
+
|
383
|
+
get "/a", {}, {}
|
384
|
+
assert_equal "js", body
|
385
|
+
end
|
386
|
+
|
387
|
+
should "not default to HTML if HTML is not provided and no type is given" do
|
388
|
+
mock_app do
|
389
|
+
get(:a, :provides => [:js]){ content_type }
|
390
|
+
end
|
391
|
+
|
392
|
+
get "/a", {}, {}
|
393
|
+
assert_equal "application/javascript;charset=utf-8", content_type
|
394
|
+
end
|
395
|
+
|
396
|
+
should "not match routes if url_format and http_accept is provided but not included" do
|
397
|
+
mock_app do
|
398
|
+
get(:a, :provides => [:js, :html]){ content_type }
|
399
|
+
end
|
400
|
+
|
401
|
+
get "/a.xml", {}, {"HTTP_ACCEPT" => "text/html"}
|
402
|
+
assert_equal 404, status
|
403
|
+
end
|
404
|
+
|
405
|
+
should "generate routes for format simple" do
|
406
|
+
mock_app do
|
407
|
+
get(:foo, :provides => [:html, :rss]) { render :haml, "Test" }
|
408
|
+
end
|
409
|
+
get "/foo"
|
410
|
+
assert_equal "Test\n", body
|
411
|
+
get "/foo.rss"
|
412
|
+
assert_equal "Test\n", body
|
413
|
+
end
|
414
|
+
|
415
|
+
should "should inject the controller name into the request" do
|
416
|
+
mock_app do
|
417
|
+
controller :posts do
|
418
|
+
get(:index) { request.controller }
|
419
|
+
controller :mini do
|
420
|
+
get(:index) { request.controller }
|
421
|
+
end
|
422
|
+
end
|
423
|
+
end
|
424
|
+
get "/posts"
|
425
|
+
assert_equal "posts", body
|
426
|
+
get "/mini"
|
427
|
+
assert_equal "mini", body
|
428
|
+
end
|
429
|
+
|
430
|
+
should "should inject the action name into the request" do
|
431
|
+
mock_app do
|
432
|
+
controller :posts do
|
433
|
+
get('/omnomnom(/:id)') { request.action.inspect }
|
434
|
+
controller :mini do
|
435
|
+
get([:a, :b, :c]) { request.action.inspect }
|
436
|
+
end
|
437
|
+
end
|
438
|
+
end
|
439
|
+
get "/posts/omnomnom"
|
440
|
+
assert_equal "\"/omnomnom(/:id)\"", body
|
441
|
+
get "/mini/a/b/c"
|
442
|
+
assert_equal ":a", body
|
443
|
+
end
|
444
|
+
|
445
|
+
should "support not_found" do
|
446
|
+
mock_app do
|
447
|
+
not_found { 'whatever' }
|
448
|
+
|
449
|
+
get :index, :map => "/" do
|
450
|
+
'index'
|
451
|
+
end
|
452
|
+
end
|
453
|
+
get '/wrong'
|
454
|
+
assert_equal 404, status
|
455
|
+
assert_equal 'whatever', body
|
456
|
+
get '/'
|
457
|
+
assert_equal 'index', body
|
458
|
+
assert_equal 200, status
|
459
|
+
end
|
460
|
+
|
461
|
+
should "should inject the route into the request" do
|
462
|
+
mock_app do
|
463
|
+
controller :posts do
|
464
|
+
get(:index) { request.route_obj.name.to_s }
|
465
|
+
end
|
466
|
+
end
|
467
|
+
get "/posts"
|
468
|
+
assert_equal "posts_index", body
|
469
|
+
end
|
470
|
+
|
471
|
+
should "preserve the format if you set it manually" do
|
472
|
+
mock_app do
|
473
|
+
before do
|
474
|
+
params[:format] = "json"
|
475
|
+
end
|
476
|
+
|
477
|
+
get "test", :provides => [:html, :json] do
|
478
|
+
content_type.inspect
|
479
|
+
end
|
480
|
+
end
|
481
|
+
get "/test"
|
482
|
+
assert_equal ":json", body
|
483
|
+
get "/test.html"
|
484
|
+
assert_equal ":json", body
|
485
|
+
get "/test.php"
|
486
|
+
assert_equal ":json", body
|
487
|
+
end
|
488
|
+
|
489
|
+
should "correctly accept '.' in the route" do
|
490
|
+
mock_app do
|
491
|
+
get "test.php", :provides => [:html, :json] do
|
492
|
+
content_type.inspect
|
493
|
+
end
|
494
|
+
end
|
495
|
+
get "/test.php"
|
496
|
+
assert_equal ":html", body
|
497
|
+
get "/test.php.json"
|
498
|
+
assert_equal ":json", body
|
499
|
+
end
|
500
|
+
|
501
|
+
should "correctly accept priority of format" do
|
502
|
+
mock_app do
|
503
|
+
get "test.php", :provides => [:html, :json, :xml] do
|
504
|
+
content_type.inspect
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
get "/test.php"
|
509
|
+
assert_equal ":html", body
|
510
|
+
get "/test.php", {}, { 'HTTP_ACCEPT' => 'application/xml' }
|
511
|
+
assert_equal ":xml", body
|
512
|
+
get "/test.php?format=json", { 'HTTP_ACCEPT' => 'application/xml' }
|
513
|
+
assert_equal ":json", body
|
514
|
+
get "/test.php.json?format=html", { 'HTTP_ACCEPT' => 'application/xml' }
|
515
|
+
assert_equal ":json", body
|
516
|
+
end
|
517
|
+
|
518
|
+
should "generate routes for format with controller" do
|
519
|
+
mock_app do
|
520
|
+
controller :posts do
|
521
|
+
get(:index, :provides => [:html, :rss, :atom, :js]) { render :haml, "Index.#{content_type}" }
|
522
|
+
get(:show, :with => :id, :provides => [:html, :rss, :atom]) { render :haml, "Show.#{content_type}" }
|
523
|
+
end
|
524
|
+
end
|
525
|
+
get "/posts"
|
526
|
+
assert_equal "Index.html\n", body
|
527
|
+
get "/posts.rss"
|
528
|
+
assert_equal "Index.rss\n", body
|
529
|
+
get "/posts.atom"
|
530
|
+
assert_equal "Index.atom\n", body
|
531
|
+
get "/posts.js"
|
532
|
+
assert_equal "Index.js\n", body
|
533
|
+
get "/posts/show/5"
|
534
|
+
assert_equal "Show.html\n", body
|
535
|
+
get "/posts/show/5.rss"
|
536
|
+
assert_equal "Show.rss\n", body
|
537
|
+
get "/posts/show/10.atom"
|
538
|
+
assert_equal "Show.atom\n", body
|
539
|
+
end
|
540
|
+
|
541
|
+
should 'map routes' do
|
542
|
+
mock_app do
|
543
|
+
get(:bar){ "bar" }
|
544
|
+
end
|
545
|
+
get "/bar"
|
546
|
+
assert_equal "bar", body
|
547
|
+
assert_equal "/bar", @app.url(:bar)
|
548
|
+
end
|
549
|
+
|
550
|
+
should 'remove index from path' do
|
551
|
+
mock_app do
|
552
|
+
get(:index){ "index" }
|
553
|
+
get("/accounts/index"){ "accounts" }
|
554
|
+
end
|
555
|
+
get "/"
|
556
|
+
assert_equal "index", body
|
557
|
+
assert_equal "/", @app.url(:index)
|
558
|
+
get "/accounts/index"
|
559
|
+
assert_equal "accounts", body
|
560
|
+
end
|
561
|
+
|
562
|
+
should 'remove index from path with params' do
|
563
|
+
mock_app do
|
564
|
+
get(:index, :with => :name){ "index with #{params[:name]}" }
|
565
|
+
end
|
566
|
+
get "/bobby"
|
567
|
+
assert_equal "index with bobby", body
|
568
|
+
assert_equal "/john", @app.url(:index, :name => "john")
|
569
|
+
end
|
570
|
+
|
571
|
+
should 'parse named params' do
|
572
|
+
mock_app do
|
573
|
+
get(:print, :with => :id){ "Im #{params[:id]}" }
|
574
|
+
end
|
575
|
+
get "/print/9"
|
576
|
+
assert_equal "Im 9", body
|
577
|
+
assert_equal "/print/9", @app.url(:print, :id => 9)
|
578
|
+
end
|
579
|
+
|
580
|
+
should '405 on wrong request_method' do
|
581
|
+
mock_app do
|
582
|
+
post('/bar'){ "bar" }
|
583
|
+
end
|
584
|
+
get "/bar"
|
585
|
+
assert_equal 405, status
|
586
|
+
end
|
587
|
+
|
588
|
+
should 'respond to' do
|
589
|
+
mock_app do
|
590
|
+
get(:a, :provides => :js){ "js" }
|
591
|
+
get(:b, :provides => :any){ "any" }
|
592
|
+
get(:c, :provides => [:js, :json]){ "js,json" }
|
593
|
+
get(:d, :provides => [:html, :js]){ "html,js"}
|
594
|
+
end
|
595
|
+
get "/a"
|
596
|
+
assert_equal 200, status
|
597
|
+
assert_equal "js", body
|
598
|
+
get "/a.js"
|
599
|
+
assert_equal "js", body
|
600
|
+
get "/b"
|
601
|
+
assert_equal "any", body
|
602
|
+
# TODO randomly fails in minitest :(
|
603
|
+
# assert_raises(RuntimeError) { get "/b.foo" }
|
604
|
+
get "/c"
|
605
|
+
assert_equal 200, status
|
606
|
+
assert_equal "js,json", body
|
607
|
+
get "/c.js"
|
608
|
+
assert_equal "js,json", body
|
609
|
+
get "/c.json"
|
610
|
+
assert_equal "js,json", body
|
611
|
+
get "/d"
|
612
|
+
assert_equal "html,js", body
|
613
|
+
get "/d.js"
|
614
|
+
assert_equal "html,js", body
|
615
|
+
end
|
616
|
+
|
617
|
+
should 'respond_to and set content_type' do
|
618
|
+
Rack::Mime::MIME_TYPES['.foo'] = 'application/foo'
|
619
|
+
mock_app do
|
620
|
+
get :a, :provides => :any do
|
621
|
+
case content_type
|
622
|
+
when :js then "js"
|
623
|
+
when :json then "json"
|
624
|
+
when :foo then "foo"
|
625
|
+
when :html then "html"
|
626
|
+
end
|
627
|
+
end
|
628
|
+
end
|
629
|
+
get "/a.js"
|
630
|
+
assert_equal "js", body
|
631
|
+
assert_equal 'application/javascript;charset=utf-8', response["Content-Type"]
|
632
|
+
get "/a.json"
|
633
|
+
assert_equal "json", body
|
634
|
+
assert_equal 'application/json;charset=utf-8', response["Content-Type"]
|
635
|
+
get "/a.foo"
|
636
|
+
assert_equal "foo", body
|
637
|
+
assert_equal 'application/foo;charset=utf-8', response["Content-Type"]
|
638
|
+
get "/a"
|
639
|
+
assert_equal "html", body
|
640
|
+
assert_equal 'text/html;charset=utf-8', response["Content-Type"]
|
641
|
+
end
|
642
|
+
|
643
|
+
should 'use controllers' do
|
644
|
+
mock_app do
|
645
|
+
controller "/admin" do
|
646
|
+
get("/"){ "index" }
|
647
|
+
get("/show/:id"){ "show #{params[:id]}" }
|
648
|
+
end
|
649
|
+
end
|
650
|
+
get "/admin"
|
651
|
+
assert_equal "index", body
|
652
|
+
get "/admin/show/1"
|
653
|
+
assert_equal "show 1", body
|
654
|
+
end
|
655
|
+
|
656
|
+
should 'use named controllers' do
|
657
|
+
mock_app do
|
658
|
+
controller :admin do
|
659
|
+
get(:index, :with => :id){ params[:id] }
|
660
|
+
get(:show, :with => :id){ "show #{params[:id]}" }
|
661
|
+
end
|
662
|
+
controllers :foo, :bar do
|
663
|
+
get(:index){ "foo_bar_index" }
|
664
|
+
end
|
665
|
+
end
|
666
|
+
get "/admin/1"
|
667
|
+
assert_equal "1", body
|
668
|
+
get "/admin/show/1"
|
669
|
+
assert_equal "show 1", body
|
670
|
+
assert_equal "/admin/1", @app.url(:admin_index, :id => 1)
|
671
|
+
assert_equal "/admin/show/1", @app.url(:admin_show, :id => 1)
|
672
|
+
get "/foo/bar"
|
673
|
+
assert_equal "foo_bar_index", body
|
674
|
+
end
|
675
|
+
|
676
|
+
should 'use map and with' do
|
677
|
+
mock_app do
|
678
|
+
get :index, :map => '/bugs', :with => :id do
|
679
|
+
params[:id]
|
680
|
+
end
|
681
|
+
end
|
682
|
+
get '/bugs/4'
|
683
|
+
assert_equal '4', body
|
684
|
+
assert_equal "/bugs/4", @app.url(:index, :id => 4)
|
685
|
+
end
|
686
|
+
|
687
|
+
should "ignore trailing delimiters within a named controller" do
|
688
|
+
mock_app do
|
689
|
+
controller :posts do
|
690
|
+
get(:index, :provides => [:html, :js]){ "index" }
|
691
|
+
get(:new) { "new" }
|
692
|
+
get(:show, :with => :id){ "show #{params[:id]}" }
|
693
|
+
end
|
694
|
+
end
|
695
|
+
get "/posts"
|
696
|
+
assert_equal "index", body
|
697
|
+
get "/posts/"
|
698
|
+
assert_equal "index", body
|
699
|
+
get "/posts.js"
|
700
|
+
assert_equal "index", body
|
701
|
+
get "/posts.js/"
|
702
|
+
assert_equal "index", body
|
703
|
+
get "/posts/new"
|
704
|
+
assert_equal "new", body
|
705
|
+
get "/posts/new/"
|
706
|
+
assert_equal "new", body
|
707
|
+
end
|
708
|
+
|
709
|
+
should "ignore trailing delimiters within a named controller for unnamed actions" do
|
710
|
+
mock_app do
|
711
|
+
controller :accounts do
|
712
|
+
get("/") { "account_index" }
|
713
|
+
get("/new") { "new" }
|
714
|
+
end
|
715
|
+
controller :votes do
|
716
|
+
get("/") { "vote_index" }
|
717
|
+
end
|
718
|
+
end
|
719
|
+
get "/accounts"
|
720
|
+
assert_equal "account_index", body
|
721
|
+
get "/accounts/"
|
722
|
+
assert_equal "account_index", body
|
723
|
+
get "/accounts/new"
|
724
|
+
assert_equal "new", body
|
725
|
+
get "/accounts/new/"
|
726
|
+
assert_equal "new", body
|
727
|
+
get "/votes"
|
728
|
+
assert_equal "vote_index", body
|
729
|
+
get "/votes/"
|
730
|
+
assert_equal "vote_index", body
|
731
|
+
end
|
732
|
+
|
733
|
+
should 'use named controllers with array routes' do
|
734
|
+
mock_app do
|
735
|
+
controller :admin do
|
736
|
+
get(:index){ "index" }
|
737
|
+
get(:show, :with => :id){ "show #{params[:id]}" }
|
738
|
+
end
|
739
|
+
controllers :foo, :bar do
|
740
|
+
get(:index){ "foo_bar_index" }
|
741
|
+
end
|
742
|
+
end
|
743
|
+
get "/admin"
|
744
|
+
assert_equal "index", body
|
745
|
+
get "/admin/show/1"
|
746
|
+
assert_equal "show 1", body
|
747
|
+
assert_equal "/admin", @app.url(:admin, :index)
|
748
|
+
assert_equal "/admin/show/1", @app.url(:admin, :show, :id => 1)
|
749
|
+
get "/foo/bar"
|
750
|
+
assert_equal "foo_bar_index", body
|
751
|
+
end
|
752
|
+
|
753
|
+
should "support a reindex action and remove index inside controller" do
|
754
|
+
mock_app do
|
755
|
+
controller :posts do
|
756
|
+
get(:index){ "index" }
|
757
|
+
get(:reindex){ "reindex" }
|
758
|
+
end
|
759
|
+
end
|
760
|
+
get "/posts"
|
761
|
+
assert_equal "index", body
|
762
|
+
get "/posts/reindex"
|
763
|
+
assert_equal "/posts/reindex", @app.url(:posts, :reindex)
|
764
|
+
assert_equal "reindex", body
|
765
|
+
end
|
766
|
+
|
767
|
+
should 'use uri_root' do
|
768
|
+
mock_app do
|
769
|
+
get(:foo){ "foo" }
|
770
|
+
end
|
771
|
+
@app.uri_root = '/'
|
772
|
+
assert_equal "/foo", @app.url(:foo)
|
773
|
+
@app.uri_root = '/testing'
|
774
|
+
assert_equal "/testing/foo", @app.url(:foo)
|
775
|
+
@app.uri_root = '/testing/'
|
776
|
+
assert_equal "/testing/foo", @app.url(:foo)
|
777
|
+
@app.uri_root = 'testing/bar///'
|
778
|
+
assert_equal "/testing/bar/foo", @app.url(:foo)
|
779
|
+
end
|
780
|
+
|
781
|
+
should 'use uri_root with controllers' do
|
782
|
+
mock_app do
|
783
|
+
controller :foo do
|
784
|
+
get(:bar){ "bar" }
|
785
|
+
end
|
786
|
+
end
|
787
|
+
@app.uri_root = '/testing'
|
788
|
+
assert_equal "/testing/foo/bar", @app.url(:foo, :bar)
|
789
|
+
end
|
790
|
+
|
791
|
+
should 'use RACK_BASE_URI' do
|
792
|
+
mock_app do
|
793
|
+
get(:foo){ "foo" }
|
794
|
+
end
|
795
|
+
# Wish there was a side-effect free way to test this...
|
796
|
+
ENV['RACK_BASE_URI'] = '/'
|
797
|
+
assert_equal "/foo", @app.url(:foo)
|
798
|
+
ENV['RACK_BASE_URI'] = '/testing'
|
799
|
+
assert_equal "/testing/foo", @app.url(:foo)
|
800
|
+
ENV['RACK_BASE_URI'] = nil
|
801
|
+
end
|
802
|
+
|
803
|
+
should 'reset routes' do
|
804
|
+
mock_app do
|
805
|
+
get("/"){ "foo" }
|
806
|
+
reset_router!
|
807
|
+
end
|
808
|
+
get "/"
|
809
|
+
assert_equal 404, status
|
810
|
+
end
|
811
|
+
|
812
|
+
should "match params and format" do
|
813
|
+
app = mock_app do
|
814
|
+
get '/:id', :provides => [:json, :html] do |id, _|
|
815
|
+
id
|
816
|
+
end
|
817
|
+
|
818
|
+
get 'format/:id', :provides => [:json, :html] do |id, format|
|
819
|
+
format
|
820
|
+
end
|
821
|
+
end
|
822
|
+
|
823
|
+
get '/123.html'
|
824
|
+
assert_equal '123', body
|
825
|
+
|
826
|
+
get 'format/123.html'
|
827
|
+
assert_equal 'html', body
|
828
|
+
end
|
829
|
+
|
830
|
+
|
831
|
+
should 'respect priorities' do
|
832
|
+
route_order = []
|
833
|
+
mock_app do
|
834
|
+
get(:index, :priority => :normal) { route_order << :normal; pass }
|
835
|
+
get(:index, :priority => :low) { route_order << :low; "hello" }
|
836
|
+
get(:index, :priority => :high) { route_order << :high; pass }
|
837
|
+
end
|
838
|
+
get '/'
|
839
|
+
assert_equal [:high, :normal, :low], route_order
|
840
|
+
assert_equal "hello", body
|
841
|
+
end
|
842
|
+
|
843
|
+
should 'catch all after controllers' do
|
844
|
+
mock_app do
|
845
|
+
get(:index, :with => :slug, :priority => :low) { "catch all" }
|
846
|
+
controllers :contact do
|
847
|
+
get(:index) { "contact"}
|
848
|
+
end
|
849
|
+
end
|
850
|
+
get "/contact"
|
851
|
+
assert_equal "contact", body
|
852
|
+
get "/foo"
|
853
|
+
assert_equal "catch all", body
|
854
|
+
end
|
855
|
+
|
856
|
+
should 'allow optionals' do
|
857
|
+
mock_app do
|
858
|
+
get(:show, :map => "/stories/:type(/:category)") do
|
859
|
+
"#{params[:type]}/#{params[:category]}"
|
860
|
+
end
|
861
|
+
end
|
862
|
+
get "/stories/foo"
|
863
|
+
assert_equal "foo/", body
|
864
|
+
get "/stories/foo/bar"
|
865
|
+
assert_equal "foo/bar", body
|
866
|
+
end
|
867
|
+
|
868
|
+
should 'apply maps' do
|
869
|
+
mock_app do
|
870
|
+
controllers :admin do
|
871
|
+
get(:index, :map => "/"){ "index" }
|
872
|
+
get(:show, :with => :id, :map => "/show"){ "show #{params[:id]}" }
|
873
|
+
get(:edit, :map => "/edit/:id/product"){ "edit #{params[:id]}" }
|
874
|
+
get(:wacky, :map => "/wacky-:id-:product_id"){ "wacky #{params[:id]}-#{params[:product_id]}" }
|
875
|
+
end
|
876
|
+
end
|
877
|
+
get "/"
|
878
|
+
assert_equal "index", body
|
879
|
+
get @app.url(:admin, :index)
|
880
|
+
assert_equal "index", body
|
881
|
+
get "/show/1"
|
882
|
+
assert_equal "show 1", body
|
883
|
+
get "/edit/1/product"
|
884
|
+
assert_equal "edit 1", body
|
885
|
+
get "/wacky-1-2"
|
886
|
+
assert_equal "wacky 1-2", body
|
887
|
+
end
|
888
|
+
|
889
|
+
should 'apply maps when given path is kind of hash' do
|
890
|
+
mock_app do
|
891
|
+
controllers :admin do
|
892
|
+
get(:foobar, "/foo/bar"){ "foobar" }
|
893
|
+
end
|
894
|
+
end
|
895
|
+
get "/foo/bar"
|
896
|
+
assert_equal "foobar", body
|
897
|
+
end
|
898
|
+
|
899
|
+
should "apply parent to route" do
|
900
|
+
mock_app do
|
901
|
+
controllers :project do
|
902
|
+
get(:index, :parent => :user) { "index #{params[:user_id]}" }
|
903
|
+
get(:index, :parent => [:user, :section]) { "index #{params[:user_id]} #{params[:section_id]}" }
|
904
|
+
get(:edit, :with => :id, :parent => :user) { "edit #{params[:id]} #{params[:user_id]}"}
|
905
|
+
get(:show, :with => :id, :parent => [:user, :product]) { "show #{params[:id]} #{params[:user_id]} #{params[:product_id]}"}
|
906
|
+
end
|
907
|
+
end
|
908
|
+
get "/user/1/project"
|
909
|
+
assert_equal "index 1", body
|
910
|
+
get "/user/1/section/3/project"
|
911
|
+
assert_equal "index 1 3", body
|
912
|
+
get "/user/1/project/edit/2"
|
913
|
+
assert_equal "edit 2 1", body
|
914
|
+
get "/user/1/product/2/project/show/3"
|
915
|
+
assert_equal "show 3 1 2", body
|
916
|
+
end
|
917
|
+
|
918
|
+
should "respect parent precedence: controllers parents go before route parents" do
|
919
|
+
mock_app do
|
920
|
+
controllers :project do
|
921
|
+
get(:index, :parent => :user) { "index #{params[:user_id]}" }
|
922
|
+
end
|
923
|
+
|
924
|
+
controllers :bar, :parent => :foo do
|
925
|
+
get(:index) { "index on foo #{params[:foo_id]} @ bar" }
|
926
|
+
get(:index, :parent => :baz) { "index on foo #{params[:foo_id]} @ baz #{params[:baz_id]} @ bar" }
|
927
|
+
end
|
928
|
+
end
|
929
|
+
|
930
|
+
get "/user/1/project"
|
931
|
+
assert_equal "index 1", body
|
932
|
+
get "/foo/1/bar"
|
933
|
+
assert_equal "index on foo 1 @ bar", body
|
934
|
+
get "/foo/1/baz/2/bar"
|
935
|
+
assert_equal "index on foo 1 @ baz 2 @ bar", body
|
936
|
+
end
|
937
|
+
|
938
|
+
should "keep a reference to the parent on the route" do
|
939
|
+
mock_app do
|
940
|
+
controllers :project do
|
941
|
+
get(:index, :parent => :user) { "index #{params[:user_id]}" }
|
942
|
+
get(:index, :parent => [:user, :section]) { "index #{params[:user_id]} #{params[:section_id]}" }
|
943
|
+
get(:edit, :with => :id, :parent => :user) { "edit #{params[:id]} #{params[:user_id]}"}
|
944
|
+
get(:show, :with => :id, :parent => [:user, :product]) { "show #{params[:id]} #{params[:user_id]} #{params[:product_id]}"}
|
945
|
+
end
|
946
|
+
|
947
|
+
controllers :bar, :parent => :foo do
|
948
|
+
get(:index) { "index on foo/bar" }
|
949
|
+
get(:index, :parent => :baz) { "index on foo/baz/bar" }
|
950
|
+
end
|
951
|
+
end
|
952
|
+
|
953
|
+
# get "/user/1/project"
|
954
|
+
assert_equal :user, @app.routes[0].parent
|
955
|
+
# get "/user/1/section/3/project"
|
956
|
+
assert_equal [:user, :section], @app.routes[2].parent
|
957
|
+
# get "/user/1/project/edit/2"
|
958
|
+
assert_equal :user, @app.routes[4].parent
|
959
|
+
# get "/user/1/product/2/project/show/3"
|
960
|
+
assert_equal [:user, :product], @app.routes[6].parent
|
961
|
+
# get "/foo/1/bar"
|
962
|
+
assert_equal :foo, @app.routes[8].parent
|
963
|
+
# get "/foo/1/baz/2/bar"
|
964
|
+
assert_equal [:foo, :baz], @app.routes[10].parent
|
965
|
+
end
|
966
|
+
|
967
|
+
should "apply parent to controller" do
|
968
|
+
mock_app do
|
969
|
+
controller :project, :parent => :user do
|
970
|
+
get(:index) { "index #{params[:user_id]}"}
|
971
|
+
get(:edit, :with => :id, :parent => :user) { "edit #{params[:id]} #{params[:user_id]}"}
|
972
|
+
get(:show, :with => :id, :parent => :product) { "show #{params[:id]} #{params[:user_id]} #{params[:product_id]}"}
|
973
|
+
end
|
974
|
+
end
|
975
|
+
|
976
|
+
user_project_url = "/user/1/project"
|
977
|
+
get user_project_url
|
978
|
+
assert_equal "index 1", body
|
979
|
+
assert_equal user_project_url, @app.url(:project, :index, :user_id => 1)
|
980
|
+
|
981
|
+
user_project_edit_url = "/user/1/project/edit/2"
|
982
|
+
get user_project_edit_url
|
983
|
+
assert_equal "edit 2 1", body
|
984
|
+
assert_equal user_project_edit_url, @app.url(:project, :edit, :user_id => 1, :id => 2)
|
985
|
+
|
986
|
+
user_product_project_url = "/user/1/product/2/project/show/3"
|
987
|
+
get user_product_project_url
|
988
|
+
assert_equal "show 3 1 2", body
|
989
|
+
assert_equal user_product_project_url, @app.url(:project, :show, :user_id => 1, :product_id => 2, :id => 3)
|
990
|
+
end
|
991
|
+
|
992
|
+
should "apply parent with shallowing to controller" do
|
993
|
+
mock_app do
|
994
|
+
controller :project do
|
995
|
+
parent :user
|
996
|
+
parent :shop, :optional => true
|
997
|
+
get(:index) { "index #{params[:user_id]} #{params[:shop_id]}" }
|
998
|
+
get(:edit, :with => :id) { "edit #{params[:id]} #{params[:user_id]} #{params[:shop_id]}" }
|
999
|
+
get(:show, :with => :id, :parent => :product) { "show #{params[:id]} #{params[:user_id]} #{params[:product_id]} #{params[:shop_id]}" }
|
1000
|
+
end
|
1001
|
+
end
|
1002
|
+
|
1003
|
+
assert_equal "/user/1/project", @app.url(:project, :index, :user_id => 1, :shop_id => nil)
|
1004
|
+
assert_equal "/user/1/shop/23/project", @app.url(:project, :index, :user_id => 1, :shop_id => 23)
|
1005
|
+
|
1006
|
+
user_project_url = "/user/1/project"
|
1007
|
+
get user_project_url
|
1008
|
+
assert_equal "index 1 ", body
|
1009
|
+
assert_equal user_project_url, @app.url(:project, :index, :user_id => 1)
|
1010
|
+
|
1011
|
+
user_project_edit_url = "/user/1/project/edit/2"
|
1012
|
+
get user_project_edit_url
|
1013
|
+
assert_equal "edit 2 1 ", body
|
1014
|
+
assert_equal user_project_edit_url, @app.url(:project, :edit, :user_id => 1, :id => 2)
|
1015
|
+
|
1016
|
+
user_product_project_url = "/user/1/product/2/project/show/3"
|
1017
|
+
get user_product_project_url
|
1018
|
+
assert_equal "show 3 1 2 ", body
|
1019
|
+
assert_equal user_product_project_url, @app.url(:project, :show, :user_id => 1, :product_id => 2, :id => 3)
|
1020
|
+
|
1021
|
+
user_project_url = "/user/1/shop/1/project"
|
1022
|
+
get user_project_url
|
1023
|
+
assert_equal "index 1 1", body
|
1024
|
+
assert_equal user_project_url, @app.url(:project, :index, :user_id => 1, :shop_id => 1)
|
1025
|
+
|
1026
|
+
user_project_edit_url = "/user/1/shop/1/project/edit/2"
|
1027
|
+
get user_project_edit_url
|
1028
|
+
assert_equal "edit 2 1 1", body
|
1029
|
+
assert_equal user_project_edit_url, @app.url(:project, :edit, :user_id => 1, :id => 2, :shop_id => 1)
|
1030
|
+
|
1031
|
+
user_product_project_url = "/user/1/shop/1/product/2/project/show/3"
|
1032
|
+
get user_product_project_url
|
1033
|
+
assert_equal "show 3 1 2 1", body
|
1034
|
+
assert_equal user_product_project_url, @app.url(:project, :show, :user_id => 1, :product_id => 2, :id => 3, :shop_id => 1)
|
1035
|
+
end
|
1036
|
+
|
1037
|
+
should "respect map in parents with shallowing" do
|
1038
|
+
mock_app do
|
1039
|
+
controller :project do
|
1040
|
+
parent :shop, :map => "/foo/bar"
|
1041
|
+
get(:index) { "index #{params[:shop_id]}" }
|
1042
|
+
end
|
1043
|
+
end
|
1044
|
+
|
1045
|
+
shop_project_url = "/foo/bar/1/project"
|
1046
|
+
get shop_project_url
|
1047
|
+
assert_equal "index 1", body
|
1048
|
+
assert_equal shop_project_url, @app.url(:project, :index, :shop_id => 1)
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
should "use default values" do
|
1052
|
+
mock_app do
|
1053
|
+
controller :lang => :it do
|
1054
|
+
get(:index, :map => "/:lang") { "lang is #{params[:lang]}" }
|
1055
|
+
end
|
1056
|
+
# This is only for be sure that default values
|
1057
|
+
# work only for the given controller
|
1058
|
+
get(:foo, :map => "/foo") {}
|
1059
|
+
end
|
1060
|
+
assert_equal "/it", @app.url(:index)
|
1061
|
+
assert_equal "/foo", @app.url(:foo)
|
1062
|
+
get "/en"
|
1063
|
+
assert_equal "lang is en", body
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
should "transitions to the next matching route on pass" do
|
1067
|
+
mock_app do
|
1068
|
+
get '/:foo' do
|
1069
|
+
pass
|
1070
|
+
'Hello Foo'
|
1071
|
+
end
|
1072
|
+
get '/:bar' do
|
1073
|
+
'Hello World'
|
1074
|
+
end
|
1075
|
+
end
|
1076
|
+
|
1077
|
+
get '/za'
|
1078
|
+
assert_equal 'Hello World', body
|
1079
|
+
end
|
1080
|
+
|
1081
|
+
should "filters by accept header" do
|
1082
|
+
mock_app do
|
1083
|
+
get '/foo', :provides => [:xml, :js] do
|
1084
|
+
request.env['HTTP_ACCEPT']
|
1085
|
+
end
|
1086
|
+
end
|
1087
|
+
|
1088
|
+
get '/foo', {}, { 'HTTP_ACCEPT' => 'application/xml' }
|
1089
|
+
assert ok?
|
1090
|
+
assert_equal 'application/xml', body
|
1091
|
+
assert_equal 'application/xml;charset=utf-8', response.headers['Content-Type']
|
1092
|
+
|
1093
|
+
get '/foo.xml'
|
1094
|
+
assert ok?
|
1095
|
+
assert_equal 'application/xml;charset=utf-8', response.headers['Content-Type']
|
1096
|
+
|
1097
|
+
get '/foo', {}, { 'HTTP_ACCEPT' => 'application/javascript' }
|
1098
|
+
assert ok?
|
1099
|
+
assert_equal 'application/javascript', body
|
1100
|
+
assert_equal 'application/javascript;charset=utf-8', response.headers['Content-Type']
|
1101
|
+
|
1102
|
+
get '/foo.js'
|
1103
|
+
assert ok?
|
1104
|
+
assert_equal 'application/javascript;charset=utf-8', response.headers['Content-Type']
|
1105
|
+
|
1106
|
+
get '/foo', {}, { "HTTP_ACCEPT" => 'text/html' }
|
1107
|
+
assert_equal 406, status
|
1108
|
+
end
|
1109
|
+
|
1110
|
+
should "does not allow global provides" do
|
1111
|
+
mock_app do
|
1112
|
+
provides :xml
|
1113
|
+
|
1114
|
+
get("/foo"){ "Foo in #{content_type}" }
|
1115
|
+
get("/bar"){ "Bar in #{content_type}" }
|
1116
|
+
end
|
1117
|
+
|
1118
|
+
get '/foo', {}, { 'HTTP_ACCEPT' => 'application/xml' }
|
1119
|
+
assert_equal 'Foo in xml', body
|
1120
|
+
get '/foo'
|
1121
|
+
assert_equal 'Foo in xml', body
|
1122
|
+
|
1123
|
+
get '/bar', {}, { 'HTTP_ACCEPT' => 'application/xml' }
|
1124
|
+
assert_equal 'Bar in html', body
|
1125
|
+
end
|
1126
|
+
|
1127
|
+
should "does not allow global provides in controller" do
|
1128
|
+
mock_app do
|
1129
|
+
controller :base do
|
1130
|
+
provides :xml
|
1131
|
+
|
1132
|
+
get(:foo, "/foo"){ "Foo in #{content_type}" }
|
1133
|
+
get(:bar, "/bar"){ "Bar in #{content_type}" }
|
1134
|
+
end
|
1135
|
+
end
|
1136
|
+
|
1137
|
+
get '/foo', {}, { 'HTTP_ACCEPT' => 'application/xml' }
|
1138
|
+
assert_equal 'Foo in xml', body
|
1139
|
+
get '/foo'
|
1140
|
+
assert_equal 'Foo in xml', body
|
1141
|
+
|
1142
|
+
get '/bar', {}, { 'HTTP_ACCEPT' => 'application/xml' }
|
1143
|
+
assert_equal 'Bar in html', body
|
1144
|
+
end
|
1145
|
+
|
1146
|
+
should "map non named routes in controllers" do
|
1147
|
+
mock_app do
|
1148
|
+
controller :base do
|
1149
|
+
get("/foo") { "ok" }
|
1150
|
+
get("/bar") { "ok" }
|
1151
|
+
end
|
1152
|
+
end
|
1153
|
+
|
1154
|
+
get "/base/foo"
|
1155
|
+
assert ok?
|
1156
|
+
get "/base/bar"
|
1157
|
+
assert ok?
|
1158
|
+
end
|
1159
|
+
|
1160
|
+
should "set content_type to :html for both empty Accept as well as Accept text/html" do
|
1161
|
+
mock_app do
|
1162
|
+
provides :html
|
1163
|
+
|
1164
|
+
get("/foo"){ content_type.to_s }
|
1165
|
+
end
|
1166
|
+
|
1167
|
+
get '/foo', {}, {}
|
1168
|
+
assert_equal 'html', body
|
1169
|
+
|
1170
|
+
get '/foo', {}, { 'HTTP_ACCEPT' => 'text/html' }
|
1171
|
+
assert_equal 'html', body
|
1172
|
+
end
|
1173
|
+
|
1174
|
+
should "set content_type to :html if Accept */*" do
|
1175
|
+
mock_app do
|
1176
|
+
get("/foo", :provides => [:html, :js]) { content_type.to_s }
|
1177
|
+
end
|
1178
|
+
get '/foo', {}, {}
|
1179
|
+
assert_equal 'html', body
|
1180
|
+
|
1181
|
+
get '/foo', {}, { 'HTTP_ACCEPT' => '*/*;q=0.5' }
|
1182
|
+
assert_equal 'html', body
|
1183
|
+
end
|
1184
|
+
|
1185
|
+
should "set content_type to :js if Accept includes both application/javascript and */*;q=0.5" do
|
1186
|
+
mock_app do
|
1187
|
+
get("/foo", :provides => [:html, :js]) { content_type.to_s }
|
1188
|
+
end
|
1189
|
+
get '/foo', {}, { 'HTTP_ACCEPT' => 'application/javascript, */*;q=0.5' }
|
1190
|
+
assert_equal 'js', body
|
1191
|
+
end
|
1192
|
+
|
1193
|
+
should "set content_type to :html if Accept */* and provides of :any" do
|
1194
|
+
mock_app do
|
1195
|
+
get("/foo", :provides => :any) { content_type.to_s }
|
1196
|
+
end
|
1197
|
+
|
1198
|
+
get '/foo', {}, { 'HTTP_ACCEPT' => '*/*' }
|
1199
|
+
assert_equal 'html', body
|
1200
|
+
end
|
1201
|
+
|
1202
|
+
should "set content_type to :js if Accept includes both application/javascript, */*;q=0.5 and provides of :any" do
|
1203
|
+
mock_app do
|
1204
|
+
get("/foo", :provides => :any) { content_type.to_s }
|
1205
|
+
end
|
1206
|
+
|
1207
|
+
get '/foo', {}, { 'HTTP_ACCEPT' => 'application/javascript, */*;q=0.5' }
|
1208
|
+
assert_equal 'js', body
|
1209
|
+
end
|
1210
|
+
|
1211
|
+
should 'allows custom route-conditions to be set via route options and halt' do
|
1212
|
+
protector = Module.new do
|
1213
|
+
def protect(*args)
|
1214
|
+
condition {
|
1215
|
+
unless authorize(params["user"], params["password"])
|
1216
|
+
halt 403, "go away"
|
1217
|
+
end
|
1218
|
+
}
|
1219
|
+
end
|
1220
|
+
end
|
1221
|
+
|
1222
|
+
mock_app do
|
1223
|
+
register protector
|
1224
|
+
|
1225
|
+
helpers do
|
1226
|
+
def authorize(username, password)
|
1227
|
+
username == "foo" && password == "bar"
|
1228
|
+
end
|
1229
|
+
end
|
1230
|
+
|
1231
|
+
get "/", :protect => true do
|
1232
|
+
"hey"
|
1233
|
+
end
|
1234
|
+
end
|
1235
|
+
|
1236
|
+
get "/"
|
1237
|
+
assert forbidden?
|
1238
|
+
assert_equal "go away", body
|
1239
|
+
|
1240
|
+
get "/", :user => "foo", :password => "bar"
|
1241
|
+
assert ok?
|
1242
|
+
assert_equal "hey", body
|
1243
|
+
end
|
1244
|
+
|
1245
|
+
should 'allows custom route-conditions to be set via route options using two routes' do
|
1246
|
+
protector = Module.new do
|
1247
|
+
def protect(*args)
|
1248
|
+
condition { authorize(params["user"], params["password"]) }
|
1249
|
+
end
|
1250
|
+
end
|
1251
|
+
|
1252
|
+
mock_app do
|
1253
|
+
register protector
|
1254
|
+
|
1255
|
+
helpers do
|
1256
|
+
def authorize(username, password)
|
1257
|
+
username == "foo" && password == "bar"
|
1258
|
+
end
|
1259
|
+
end
|
1260
|
+
|
1261
|
+
get "/", :protect => true do
|
1262
|
+
"hey"
|
1263
|
+
end
|
1264
|
+
|
1265
|
+
get "/" do
|
1266
|
+
"go away"
|
1267
|
+
end
|
1268
|
+
end
|
1269
|
+
|
1270
|
+
get "/"
|
1271
|
+
assert_equal "go away", body
|
1272
|
+
|
1273
|
+
get "/", :user => "foo", :password => "bar"
|
1274
|
+
assert ok?
|
1275
|
+
assert_equal "hey", body
|
1276
|
+
end
|
1277
|
+
|
1278
|
+
should "allow concise routing" do
|
1279
|
+
mock_app do
|
1280
|
+
get :index, ":id" do
|
1281
|
+
params[:id]
|
1282
|
+
end
|
1283
|
+
|
1284
|
+
get :map, "route/:id" do
|
1285
|
+
params[:id]
|
1286
|
+
end
|
1287
|
+
end
|
1288
|
+
|
1289
|
+
get "/123"
|
1290
|
+
assert_equal "123", body
|
1291
|
+
|
1292
|
+
get "/route/123"
|
1293
|
+
assert_equal "123", body
|
1294
|
+
end
|
1295
|
+
|
1296
|
+
should "support halting with 404 and message" do
|
1297
|
+
mock_app do
|
1298
|
+
controller do
|
1299
|
+
get :index do
|
1300
|
+
halt 404, "not found"
|
1301
|
+
end
|
1302
|
+
end
|
1303
|
+
end
|
1304
|
+
|
1305
|
+
get "/"
|
1306
|
+
assert_equal 404, status
|
1307
|
+
assert_equal "not found", body
|
1308
|
+
end
|
1309
|
+
|
1310
|
+
should "allow passing & halting in before filters" do
|
1311
|
+
mock_app do
|
1312
|
+
controller do
|
1313
|
+
before { env['QUERY_STRING'] == 'secret' or pass }
|
1314
|
+
get :index do
|
1315
|
+
"secret index"
|
1316
|
+
end
|
1317
|
+
end
|
1318
|
+
|
1319
|
+
controller do
|
1320
|
+
before { env['QUERY_STRING'] == 'halt' and halt 401, 'go away!' }
|
1321
|
+
get :index do
|
1322
|
+
"index"
|
1323
|
+
end
|
1324
|
+
end
|
1325
|
+
end
|
1326
|
+
|
1327
|
+
get "/?secret"
|
1328
|
+
assert_equal "secret index", body
|
1329
|
+
|
1330
|
+
get "/?halt"
|
1331
|
+
assert_equal "go away!", body
|
1332
|
+
assert_equal 401, status
|
1333
|
+
|
1334
|
+
get "/"
|
1335
|
+
assert_equal "index", body
|
1336
|
+
end
|
1337
|
+
|
1338
|
+
should 'scope filters in the given controller' do
|
1339
|
+
mock_app do
|
1340
|
+
before { @global = 'global' }
|
1341
|
+
after { @global = nil }
|
1342
|
+
|
1343
|
+
controller :foo do
|
1344
|
+
before { @foo = :foo }
|
1345
|
+
after { @foo = nil }
|
1346
|
+
get("/") { [@foo, @bar, @global].compact.join(" ") }
|
1347
|
+
end
|
1348
|
+
|
1349
|
+
get("/") { [@foo, @bar, @global].compact.join(" ") }
|
1350
|
+
|
1351
|
+
controller :bar do
|
1352
|
+
before { @bar = :bar }
|
1353
|
+
after { @bar = nil }
|
1354
|
+
get("/") { [@foo, @bar, @global].compact.join(" ") }
|
1355
|
+
end
|
1356
|
+
end
|
1357
|
+
|
1358
|
+
get "/bar"
|
1359
|
+
assert_equal "bar global", body
|
1360
|
+
|
1361
|
+
get "/foo"
|
1362
|
+
assert_equal "foo global", body
|
1363
|
+
|
1364
|
+
get "/"
|
1365
|
+
assert_equal "global", body
|
1366
|
+
end
|
1367
|
+
|
1368
|
+
should 'works with optionals params' do
|
1369
|
+
mock_app do
|
1370
|
+
get("/foo(/:bar)") { params[:bar] }
|
1371
|
+
end
|
1372
|
+
|
1373
|
+
get "/foo/bar"
|
1374
|
+
assert_equal "bar", body
|
1375
|
+
|
1376
|
+
get "/foo"
|
1377
|
+
assert_equal "", body
|
1378
|
+
end
|
1379
|
+
|
1380
|
+
should 'work with multiple dashed params' do
|
1381
|
+
mock_app do
|
1382
|
+
get "/route/:foo/:bar/:baz", :provides => :html do
|
1383
|
+
"#{params[:foo]};#{params[:bar]};#{params[:baz]}"
|
1384
|
+
end
|
1385
|
+
end
|
1386
|
+
|
1387
|
+
get "/route/foo/bar/baz"
|
1388
|
+
assert_equal 'foo;bar;baz', body
|
1389
|
+
|
1390
|
+
get "/route/foo/bar-whatever/baz"
|
1391
|
+
assert_equal 'foo;bar-whatever;baz', body
|
1392
|
+
end
|
1393
|
+
|
1394
|
+
should 'work with arbitrary params' do
|
1395
|
+
mock_app do
|
1396
|
+
get(:testing) { params[:foo] }
|
1397
|
+
end
|
1398
|
+
|
1399
|
+
url = @app.url(:testing, :foo => 'bar')
|
1400
|
+
assert_equal "/testing?foo=bar", url
|
1401
|
+
get url
|
1402
|
+
assert_equal "bar", body
|
1403
|
+
end
|
1404
|
+
|
1405
|
+
should 'ignore nil params' do
|
1406
|
+
mock_app do
|
1407
|
+
get(:testing, :provides => [:html, :json]) do
|
1408
|
+
end
|
1409
|
+
end
|
1410
|
+
assert_equal '/testing.html', @app.url(:testing, :format => :html)
|
1411
|
+
assert_equal '/testing', @app.url(:testing, :format => nil)
|
1412
|
+
end
|
1413
|
+
|
1414
|
+
should 'be able to access params in a before filter' do
|
1415
|
+
username_from_before_filter = nil
|
1416
|
+
|
1417
|
+
mock_app do
|
1418
|
+
before do
|
1419
|
+
username_from_before_filter = params[:username]
|
1420
|
+
end
|
1421
|
+
|
1422
|
+
get :users, :with => :username do
|
1423
|
+
end
|
1424
|
+
end
|
1425
|
+
get '/users/josh'
|
1426
|
+
assert_equal 'josh', username_from_before_filter
|
1427
|
+
end
|
1428
|
+
|
1429
|
+
should "be able to access params normally when a before filter is specified" do
|
1430
|
+
mock_app do
|
1431
|
+
before { }
|
1432
|
+
get :index do
|
1433
|
+
params.inspect
|
1434
|
+
end
|
1435
|
+
end
|
1436
|
+
get '/?test=what'
|
1437
|
+
assert_equal '{"test"=>"what"}', body
|
1438
|
+
end
|
1439
|
+
|
1440
|
+
should 'work with controller and arbitrary params' do
|
1441
|
+
mock_app do
|
1442
|
+
get(:testing) { params[:foo] }
|
1443
|
+
controller :test1 do
|
1444
|
+
get(:url1) { params[:foo] }
|
1445
|
+
get(:url2, :provides => [:html, :json]) { params[:foo] }
|
1446
|
+
end
|
1447
|
+
end
|
1448
|
+
|
1449
|
+
url = @app.url(:test1, :url1, :foo => 'bar1')
|
1450
|
+
assert_equal "/test1/url1?foo=bar1", url
|
1451
|
+
get url
|
1452
|
+
assert_equal "bar1", body
|
1453
|
+
|
1454
|
+
url = @app.url(:test1, :url2, :foo => 'bar2')
|
1455
|
+
assert_equal "/test1/url2?foo=bar2", url
|
1456
|
+
get url
|
1457
|
+
assert_equal "bar2", body
|
1458
|
+
end
|
1459
|
+
|
1460
|
+
should "parse two routes with the same path but different http verbs" do
|
1461
|
+
mock_app do
|
1462
|
+
get(:index) { "This is the get index" }
|
1463
|
+
post(:index) { "This is the post index" }
|
1464
|
+
end
|
1465
|
+
get "/"
|
1466
|
+
assert_equal "This is the get index", body
|
1467
|
+
post "/"
|
1468
|
+
assert_equal "This is the post index", body
|
1469
|
+
end
|
1470
|
+
|
1471
|
+
should "use optionals params" do
|
1472
|
+
mock_app do
|
1473
|
+
get(:index, :map => "/(:foo(/:bar))") { "#{params[:foo]}-#{params[:bar]}" }
|
1474
|
+
end
|
1475
|
+
get "/foo"
|
1476
|
+
assert_equal "foo-", body
|
1477
|
+
get "/foo/bar"
|
1478
|
+
assert_equal "foo-bar", body
|
1479
|
+
end
|
1480
|
+
|
1481
|
+
should "parse two routes with the same path but different http verbs and provides" do
|
1482
|
+
mock_app do
|
1483
|
+
get(:index, :provides => [:html, :json]) { "This is the get index.#{content_type}" }
|
1484
|
+
post(:index, :provides => [:html, :json]) { "This is the post index.#{content_type}" }
|
1485
|
+
end
|
1486
|
+
get "/"
|
1487
|
+
assert_equal "This is the get index.html", body
|
1488
|
+
post "/"
|
1489
|
+
assert_equal "This is the post index.html", body
|
1490
|
+
get "/.json"
|
1491
|
+
assert_equal "This is the get index.json", body
|
1492
|
+
get "/.js"
|
1493
|
+
assert_equal 404, status
|
1494
|
+
post "/.json"
|
1495
|
+
assert_equal "This is the post index.json", body
|
1496
|
+
post "/.js"
|
1497
|
+
assert_equal 404, status
|
1498
|
+
end
|
1499
|
+
|
1500
|
+
should "allow controller level mapping" do
|
1501
|
+
mock_app do
|
1502
|
+
controller :map => "controller-:id" do
|
1503
|
+
get(:url3) { "#{params[:id]}" }
|
1504
|
+
get(:url4, :map => 'test-:id2') { "#{params[:id]}, #{params[:id2]}" }
|
1505
|
+
end
|
1506
|
+
end
|
1507
|
+
|
1508
|
+
url = @app.url(:url3, :id => 1)
|
1509
|
+
assert_equal "/controller-1/url3", url
|
1510
|
+
get url
|
1511
|
+
assert_equal "1", body
|
1512
|
+
|
1513
|
+
url = @app.url(:url4, 1, 2)
|
1514
|
+
assert_equal "/controller-1/test-2", url
|
1515
|
+
get url
|
1516
|
+
assert_equal "1, 2", body
|
1517
|
+
end
|
1518
|
+
|
1519
|
+
should "replace name of named controller with mapping path" do
|
1520
|
+
mock_app do
|
1521
|
+
controller :ugly, :map => "/pretty/:id" do
|
1522
|
+
get(:url3) { "#{params[:id]}" }
|
1523
|
+
get(:url4, :map => 'test-:id2') { "#{params[:id]}, #{params[:id2]}" }
|
1524
|
+
end
|
1525
|
+
controller :voldemort, :map => "" do
|
1526
|
+
get(:url5) { "okay" }
|
1527
|
+
end
|
1528
|
+
end
|
1529
|
+
|
1530
|
+
url = @app.url(:ugly, :url3, :id => 1)
|
1531
|
+
assert_equal "/pretty/1/url3", url
|
1532
|
+
get url
|
1533
|
+
assert_equal "1", body
|
1534
|
+
|
1535
|
+
url = @app.url(:ugly, :url4, 3, 5)
|
1536
|
+
assert_equal "/pretty/3/test-5", url
|
1537
|
+
get url
|
1538
|
+
assert_equal "3, 5", body
|
1539
|
+
|
1540
|
+
url = @app.url(:voldemort, :url5)
|
1541
|
+
assert_equal "/url5", url
|
1542
|
+
get url
|
1543
|
+
assert_equal 'okay', body
|
1544
|
+
end
|
1545
|
+
|
1546
|
+
should 'use absolute and relative maps' do
|
1547
|
+
mock_app do
|
1548
|
+
controller :one do
|
1549
|
+
parent :three
|
1550
|
+
get :index, :map => 'one' do; end
|
1551
|
+
get :index2, :map => '/one' do; end
|
1552
|
+
end
|
1553
|
+
|
1554
|
+
controller :two, :map => 'two' do
|
1555
|
+
parent :three
|
1556
|
+
get :index, :map => 'two' do; end
|
1557
|
+
get :index2, :map => '/two', :with => :id do; end
|
1558
|
+
end
|
1559
|
+
end
|
1560
|
+
assert_equal "/three/three_id/one", @app.url(:one, :index, 'three_id')
|
1561
|
+
assert_equal "/one", @app.url(:one, :index2)
|
1562
|
+
assert_equal "/two/three/three_id/two", @app.url(:two, :index, 'three_id')
|
1563
|
+
assert_equal "/two/four_id", @app.url(:two, :index2, 'four_id')
|
1564
|
+
end
|
1565
|
+
|
1566
|
+
should "work with params and parent options" do
|
1567
|
+
mock_app do
|
1568
|
+
controller :test2, :parent => :parent1, :parent1_id => 1 do
|
1569
|
+
get(:url3) { params[:foo] }
|
1570
|
+
get(:url4, :with => :with1) { params[:foo] }
|
1571
|
+
get(:url5, :with => :with2, :provides => [:html]) { params[:foo] }
|
1572
|
+
end
|
1573
|
+
end
|
1574
|
+
|
1575
|
+
url = @app.url(:test2, :url3, :foo => 'bar3')
|
1576
|
+
assert_equal "/parent1/1/test2/url3?foo=bar3", url
|
1577
|
+
get url
|
1578
|
+
assert_equal "bar3", body
|
1579
|
+
|
1580
|
+
url = @app.url(:test2, :url4, :with1 => 'awith1', :foo => 'bar4')
|
1581
|
+
assert_equal "/parent1/1/test2/url4/awith1?foo=bar4", url
|
1582
|
+
get url
|
1583
|
+
assert_equal "bar4", body
|
1584
|
+
|
1585
|
+
url = @app.url(:test2, :url5, :with2 => 'awith1', :foo => 'bar5')
|
1586
|
+
assert_equal "/parent1/1/test2/url5/awith1?foo=bar5", url
|
1587
|
+
get url
|
1588
|
+
assert_equal "bar5", body
|
1589
|
+
end
|
1590
|
+
|
1591
|
+
should "parse params without explicit provides for every matching route" do
|
1592
|
+
mock_app do
|
1593
|
+
get(:index, :map => "/foos/:bar") { "get bar = #{params[:bar]}" }
|
1594
|
+
post :create, :map => "/foos/:bar", :provides => [:html, :js] do
|
1595
|
+
"post bar = #{params[:bar]}"
|
1596
|
+
end
|
1597
|
+
end
|
1598
|
+
|
1599
|
+
get "/foos/hello"
|
1600
|
+
assert_equal "get bar = hello", body
|
1601
|
+
post "/foos/hello"
|
1602
|
+
assert_equal "post bar = hello", body
|
1603
|
+
post "/foos/hello.js"
|
1604
|
+
assert_equal "post bar = hello", body
|
1605
|
+
end
|
1606
|
+
|
1607
|
+
should "properly route to first foo with two similar routes" do
|
1608
|
+
mock_app do
|
1609
|
+
controllers do
|
1610
|
+
get('/foo/') { "this is foo" }
|
1611
|
+
get(:show, :map => "/foo/:bar/:id") { "/foo/#{params[:bar]}/#{params[:id]}" }
|
1612
|
+
end
|
1613
|
+
end
|
1614
|
+
get "/foo"
|
1615
|
+
assert_equal "this is foo", body
|
1616
|
+
get "/foo/"
|
1617
|
+
assert_equal "this is foo", body
|
1618
|
+
get '/foo/5/10'
|
1619
|
+
assert_equal "/foo/5/10", body
|
1620
|
+
end
|
1621
|
+
|
1622
|
+
should "index routes should be optional when nested" do
|
1623
|
+
mock_app do
|
1624
|
+
controller '/users', :provides => [:json] do
|
1625
|
+
get '/' do
|
1626
|
+
"foo"
|
1627
|
+
end
|
1628
|
+
end
|
1629
|
+
end
|
1630
|
+
get "/users.json"
|
1631
|
+
assert_equal "foo", body
|
1632
|
+
end
|
1633
|
+
|
1634
|
+
should "use provides as conditional" do
|
1635
|
+
mock_app do
|
1636
|
+
provides :json
|
1637
|
+
get "/" do
|
1638
|
+
"foo"
|
1639
|
+
end
|
1640
|
+
end
|
1641
|
+
get "/.json"
|
1642
|
+
assert_equal "foo", body
|
1643
|
+
end
|
1644
|
+
|
1645
|
+
should_eventually "reset provides for routes that didn't use it" do
|
1646
|
+
mock_app do
|
1647
|
+
get('/foo', :provides => :js){}
|
1648
|
+
get('/bar'){}
|
1649
|
+
end
|
1650
|
+
get '/foo'
|
1651
|
+
assert ok?
|
1652
|
+
get '/foo.js'
|
1653
|
+
assert ok?
|
1654
|
+
get '/bar'
|
1655
|
+
assert ok?
|
1656
|
+
get '/bar.js'
|
1657
|
+
assert_equal 404, status
|
1658
|
+
end
|
1659
|
+
|
1660
|
+
should "pass controller conditions to each route" do
|
1661
|
+
counter = 0
|
1662
|
+
|
1663
|
+
mock_app do
|
1664
|
+
self.class.send(:define_method, :increment!) do |*args|
|
1665
|
+
condition { counter += 1 }
|
1666
|
+
end
|
1667
|
+
|
1668
|
+
controller :posts, :conditions => {:increment! => true} do
|
1669
|
+
get("/foo") { "foo" }
|
1670
|
+
get("/bar") { "bar" }
|
1671
|
+
end
|
1672
|
+
|
1673
|
+
end
|
1674
|
+
|
1675
|
+
get "/posts/foo"
|
1676
|
+
get "/posts/bar"
|
1677
|
+
assert_equal 2, counter
|
1678
|
+
end
|
1679
|
+
|
1680
|
+
should "allow controller conditions to be overridden" do
|
1681
|
+
counter = 0
|
1682
|
+
|
1683
|
+
mock_app do
|
1684
|
+
self.class.send(:define_method, :increment!) do |increment|
|
1685
|
+
condition { counter += 1 } if increment
|
1686
|
+
end
|
1687
|
+
|
1688
|
+
controller :posts, :conditions => {:increment! => true} do
|
1689
|
+
get("/foo") { "foo" }
|
1690
|
+
get("/bar", :increment! => false) { "bar" }
|
1691
|
+
end
|
1692
|
+
|
1693
|
+
end
|
1694
|
+
|
1695
|
+
get "/posts/foo"
|
1696
|
+
get "/posts/bar"
|
1697
|
+
assert_equal 1, counter
|
1698
|
+
end
|
1699
|
+
|
1700
|
+
should "parse params with class level provides" do
|
1701
|
+
mock_app do
|
1702
|
+
controllers :posts, :provides => [:html, :js] do
|
1703
|
+
post(:create, :map => "/foo/:bar/:baz/:id") {
|
1704
|
+
"POST CREATE #{params[:bar]} - #{params[:baz]} - #{params[:id]}"
|
1705
|
+
}
|
1706
|
+
end
|
1707
|
+
controllers :topics, :provides => [:js, :html] do
|
1708
|
+
get(:show, :map => "/foo/:bar/:baz/:id") { render "topics/show" }
|
1709
|
+
post(:create, :map => "/foo/:bar/:baz") { "TOPICS CREATE #{params[:bar]} - #{params[:baz]}" }
|
1710
|
+
end
|
1711
|
+
end
|
1712
|
+
post "/foo/bar/baz.js"
|
1713
|
+
assert_equal "TOPICS CREATE bar - baz", body, "should parse params with explicit .js"
|
1714
|
+
post @app.url(:topics, :create, :format => :js, :bar => 'bar', :baz => 'baz')
|
1715
|
+
assert_equal "TOPICS CREATE bar - baz", body, "should parse params from generated url"
|
1716
|
+
post "/foo/bar/baz/5.js"
|
1717
|
+
assert_equal "POST CREATE bar - baz - 5", body
|
1718
|
+
post @app.url(:posts, :create, :format => :js, :bar => 'bar', :baz => 'baz', :id => 5)
|
1719
|
+
assert_equal "POST CREATE bar - baz - 5", body
|
1720
|
+
end
|
1721
|
+
|
1722
|
+
should "parse params properly with inline provides" do
|
1723
|
+
mock_app do
|
1724
|
+
controllers :posts do
|
1725
|
+
post(:create, :map => "/foo/:bar/:baz/:id", :provides => [:html, :js]) {
|
1726
|
+
"POST CREATE #{params[:bar]} - #{params[:baz]} - #{params[:id]}"
|
1727
|
+
}
|
1728
|
+
end
|
1729
|
+
controllers :topics do
|
1730
|
+
get(:show, :map => "/foo/:bar/:baz/:id", :provides => [:html, :js]) { render "topics/show" }
|
1731
|
+
post(:create, :map => "/foo/:bar/:baz", :provides => [:html, :js]) { "TOPICS CREATE #{params[:bar]} - #{params[:baz]}" }
|
1732
|
+
end
|
1733
|
+
end
|
1734
|
+
post @app.url(:topics, :create, :format => :js, :bar => 'bar', :baz => 'baz')
|
1735
|
+
assert_equal "TOPICS CREATE bar - baz", body, "should properly post to topics create action"
|
1736
|
+
post @app.url(:posts, :create, :format => :js, :bar => 'bar', :baz => 'baz', :id => 5)
|
1737
|
+
assert_equal "POST CREATE bar - baz - 5", body, "should properly post to create action"
|
1738
|
+
end
|
1739
|
+
|
1740
|
+
should "have overideable format" do
|
1741
|
+
::Rack::Mime::MIME_TYPES[".other"] = "text/html"
|
1742
|
+
mock_app do
|
1743
|
+
before do
|
1744
|
+
params[:format] ||= :other
|
1745
|
+
end
|
1746
|
+
get("/format_test", :provides => [:html, :other]){ content_type.to_s }
|
1747
|
+
end
|
1748
|
+
get "/format_test"
|
1749
|
+
assert_equal "other", body
|
1750
|
+
::Rack::Mime::MIME_TYPES.delete('.other')
|
1751
|
+
end
|
1752
|
+
|
1753
|
+
should 'invokes handlers registered with ::error when raised' do
|
1754
|
+
mock_app do
|
1755
|
+
set :raise_errors, false
|
1756
|
+
error(FooError) { 'Foo!' }
|
1757
|
+
get '/' do
|
1758
|
+
raise FooError
|
1759
|
+
end
|
1760
|
+
end
|
1761
|
+
get '/'
|
1762
|
+
assert_equal 500, status
|
1763
|
+
assert_equal 'Foo!', body
|
1764
|
+
end
|
1765
|
+
|
1766
|
+
should 'have MethodOverride middleware' do
|
1767
|
+
mock_app do
|
1768
|
+
put('/') { 'okay' }
|
1769
|
+
end
|
1770
|
+
assert @app.method_override?
|
1771
|
+
post '/', {'_method'=>'PUT'}, {}
|
1772
|
+
assert_equal 200, status
|
1773
|
+
assert_equal 'okay', body
|
1774
|
+
end
|
1775
|
+
|
1776
|
+
should 'return value from params' do
|
1777
|
+
mock_app do
|
1778
|
+
get("/foo/:bar"){ raise "'bar' should be a string" unless params[:bar].kind_of? String}
|
1779
|
+
end
|
1780
|
+
get "/foo/50"
|
1781
|
+
assert ok?
|
1782
|
+
end
|
1783
|
+
|
1784
|
+
should 'have MethodOverride middleware with more options' do
|
1785
|
+
mock_app do
|
1786
|
+
put('/hi', :provides => [:json]) { 'hi' }
|
1787
|
+
end
|
1788
|
+
post '/hi', {'_method'=>'PUT'}
|
1789
|
+
assert_equal 200, status
|
1790
|
+
assert_equal 'hi', body
|
1791
|
+
post '/hi.json', {'_method'=>'PUT'}
|
1792
|
+
assert_equal 200, status
|
1793
|
+
assert_equal 'hi', body
|
1794
|
+
post '/hi.json'
|
1795
|
+
assert_equal 405, status
|
1796
|
+
end
|
1797
|
+
|
1798
|
+
should 'parse nested params' do
|
1799
|
+
mock_app do
|
1800
|
+
get(:index) { "%s %s" % [params[:account][:name], params[:account][:surname]] }
|
1801
|
+
end
|
1802
|
+
get "/?account[name]=foo&account[surname]=bar"
|
1803
|
+
assert_equal 'foo bar', body
|
1804
|
+
get @app.url(:index, "account[name]" => "foo", "account[surname]" => "bar")
|
1805
|
+
assert_equal 'foo bar', body
|
1806
|
+
end
|
1807
|
+
|
1808
|
+
should 'render sinatra NotFound page' do
|
1809
|
+
mock_app { set :environment, :development }
|
1810
|
+
get "/"
|
1811
|
+
assert_equal 404, status
|
1812
|
+
assert_match %r{(Sinatra doesn’t know this ditty.|<h1>Not Found</h1>)}, body
|
1813
|
+
end
|
1814
|
+
|
1815
|
+
should 'render a custom NotFound page' do
|
1816
|
+
mock_app do
|
1817
|
+
error(Sinatra::NotFound) { "not found" }
|
1818
|
+
end
|
1819
|
+
get "/"
|
1820
|
+
assert_equal 404, status
|
1821
|
+
assert_match /not found/, body
|
1822
|
+
end
|
1823
|
+
|
1824
|
+
should 'render a custom 404 page using not_found' do
|
1825
|
+
mock_app do
|
1826
|
+
not_found { "custom 404 not found" }
|
1827
|
+
end
|
1828
|
+
get "/"
|
1829
|
+
assert_equal 404, status
|
1830
|
+
assert_equal "custom 404 not found", body
|
1831
|
+
end
|
1832
|
+
|
1833
|
+
should 'render a custom error page using error method' do
|
1834
|
+
skip
|
1835
|
+
mock_app do
|
1836
|
+
error(404) { "custom 404 error" }
|
1837
|
+
end
|
1838
|
+
get "/"
|
1839
|
+
assert_equal 404, status
|
1840
|
+
assert_equal "custom 404 error", body
|
1841
|
+
end
|
1842
|
+
|
1843
|
+
should 'render a custom 403 page' do
|
1844
|
+
mock_app do
|
1845
|
+
error(403) { "custom 403 not found" }
|
1846
|
+
get("/") { status 403 }
|
1847
|
+
end
|
1848
|
+
get "/"
|
1849
|
+
assert_equal 403, status
|
1850
|
+
assert_equal "custom 403 not found", body
|
1851
|
+
end
|
1852
|
+
|
1853
|
+
should 'recognize paths' do
|
1854
|
+
mock_app do
|
1855
|
+
controller :foo do
|
1856
|
+
get(:bar, :map => "/my/:id/custom-route") { }
|
1857
|
+
end
|
1858
|
+
get(:simple, :map => "/simple/:id") { }
|
1859
|
+
get(:with_format, :with => :id, :provides => :js) { }
|
1860
|
+
end
|
1861
|
+
assert_equal [:foo_bar, { :id => "fantastic" }], @app.recognize_path(@app.url(:foo, :bar, :id => :fantastic))
|
1862
|
+
assert_equal [:foo_bar, { :id => "18" }], @app.recognize_path(@app.url(:foo, :bar, :id => 18))
|
1863
|
+
assert_equal [:simple, { :id => "bar" }], @app.recognize_path(@app.url(:simple, :id => "bar"))
|
1864
|
+
assert_equal [:simple, { :id => "true" }], @app.recognize_path(@app.url(:simple, :id => true))
|
1865
|
+
assert_equal [:simple, { :id => "9" }], @app.recognize_path(@app.url(:simple, :id => 9))
|
1866
|
+
assert_equal [:with_format, { :id => "bar", :format => "js" }], @app.recognize_path(@app.url(:with_format, :id => "bar", :format => :js))
|
1867
|
+
assert_equal [:with_format, { :id => "true", :format => "js" }], @app.recognize_path(@app.url(:with_format, :id => true, :format => "js"))
|
1868
|
+
assert_equal [:with_format, { :id => "9", :format => "js" }], @app.recognize_path(@app.url(:with_format, :id => 9, :format => :js))
|
1869
|
+
end
|
1870
|
+
|
1871
|
+
should 'have current_path' do
|
1872
|
+
mock_app do
|
1873
|
+
controller :foo do
|
1874
|
+
get(:index) { current_path }
|
1875
|
+
get :bar, :map => "/paginate/:page" do
|
1876
|
+
current_path
|
1877
|
+
end
|
1878
|
+
get(:after) { current_path }
|
1879
|
+
end
|
1880
|
+
end
|
1881
|
+
get "/paginate/10"
|
1882
|
+
assert_equal "/paginate/10", body
|
1883
|
+
get "/foo/after"
|
1884
|
+
assert_equal "/foo/after", body
|
1885
|
+
get "/foo"
|
1886
|
+
assert_equal "/foo", body
|
1887
|
+
end
|
1888
|
+
|
1889
|
+
should 'accept :map and :parent' do
|
1890
|
+
mock_app do
|
1891
|
+
controller :posts do
|
1892
|
+
get :show, :parent => :users, :map => "posts/:id" do
|
1893
|
+
"#{params[:user_id]}-#{params[:id]}"
|
1894
|
+
end
|
1895
|
+
end
|
1896
|
+
end
|
1897
|
+
get '/users/123/posts/321'
|
1898
|
+
assert_equal "123-321", body
|
1899
|
+
end
|
1900
|
+
|
1901
|
+
should 'change params in current_path' do
|
1902
|
+
mock_app do
|
1903
|
+
get :index, :map => "/paginate/:page" do
|
1904
|
+
current_path(:page => 66)
|
1905
|
+
end
|
1906
|
+
end
|
1907
|
+
get @app.url(:index, :page => 10)
|
1908
|
+
assert_equal "/paginate/66", body
|
1909
|
+
end
|
1910
|
+
|
1911
|
+
should 'not route get :users, :with => :id to /users//' do
|
1912
|
+
mock_app do
|
1913
|
+
get(:users, :with => :id) { 'boo' }
|
1914
|
+
end
|
1915
|
+
get '/users//'
|
1916
|
+
assert_equal 404, status
|
1917
|
+
end
|
1918
|
+
end
|