padrino-core 0.10.7 → 0.11.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.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/lib/padrino-core.rb +58 -4
  3. data/lib/padrino-core/application.rb +38 -16
  4. data/lib/padrino-core/application/flash.rb +229 -0
  5. data/lib/padrino-core/application/rendering.rb +39 -11
  6. data/lib/padrino-core/application/rendering/extensions/erubis.rb +55 -0
  7. data/lib/padrino-core/application/rendering/extensions/haml.rb +26 -0
  8. data/lib/padrino-core/application/rendering/extensions/slim.rb +14 -0
  9. data/lib/padrino-core/application/routing.rb +106 -35
  10. data/lib/padrino-core/cli/base.rb +41 -38
  11. data/lib/padrino-core/cli/rake.rb +30 -9
  12. data/lib/padrino-core/cli/rake_tasks.rb +9 -14
  13. data/lib/padrino-core/loader.rb +23 -9
  14. data/lib/padrino-core/locale/fr.yml +1 -1
  15. data/lib/padrino-core/locale/ru.yml +1 -1
  16. data/lib/padrino-core/logger.rb +48 -32
  17. data/lib/padrino-core/module.rb +58 -0
  18. data/lib/padrino-core/mounter.rb +15 -5
  19. data/lib/padrino-core/reloader.rb +14 -12
  20. data/lib/padrino-core/server.rb +4 -4
  21. data/lib/padrino-core/support_lite.rb +43 -6
  22. data/lib/padrino-core/version.rb +1 -1
  23. data/padrino-core.gemspec +9 -4
  24. data/test/fixtures/app_gem/Gemfile +4 -0
  25. data/test/fixtures/app_gem/app/app.rb +3 -0
  26. data/test/fixtures/app_gem/app_gem.gemspec +17 -0
  27. data/test/fixtures/app_gem/lib/app_gem.rb +7 -0
  28. data/test/fixtures/app_gem/lib/app_gem/version.rb +3 -0
  29. data/test/mini_shoulda.rb +1 -1
  30. data/test/test_application.rb +38 -21
  31. data/test/test_csrf_protection.rb +80 -0
  32. data/test/test_filters.rb +70 -0
  33. data/test/test_flash.rb +168 -0
  34. data/test/test_logger.rb +27 -0
  35. data/test/test_mounter.rb +24 -2
  36. data/test/test_reloader_simple.rb +4 -4
  37. data/test/test_rendering.rb +75 -4
  38. data/test/test_routing.rb +164 -35
  39. data/test/test_support_lite.rb +56 -0
  40. metadata +52 -29
@@ -0,0 +1,168 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+
3
+ describe Padrino::Flash do
4
+ context 'storage' do
5
+ before do
6
+ @storage = Padrino::Flash::Storage.new(
7
+ :success => 'Success msg',
8
+ :error => 'Error msg',
9
+ :notice => 'Notice msg',
10
+ :custom => 'Custom msg'
11
+ )
12
+ @storage[:one] = 'One msg'
13
+ @storage[:two] = 'Two msg'
14
+ end
15
+
16
+ should 'acts like hash' do
17
+ assert_respond_to @storage, :[]
18
+ end
19
+
20
+ should 'know its size' do
21
+ assert_equal 4, @storage.length
22
+ assert_equal @storage.length, @storage.size
23
+ end
24
+
25
+ should 'sweep its content' do
26
+ assert_equal 2, @storage.sweep.size
27
+ assert_empty @storage.sweep
28
+ end
29
+
30
+ should 'discard everything' do
31
+ assert_empty @storage.discard.sweep
32
+ end
33
+
34
+ should 'discard specified key' do
35
+ assert_equal 1, @storage.discard(:one).sweep.size
36
+ end
37
+
38
+ should 'keep everything' do
39
+ assert_equal 2, @storage.sweep.keep.sweep.size
40
+ end
41
+
42
+ should 'keep only specified key' do
43
+ assert_equal 1, @storage.sweep.keep(:one).sweep.size
44
+ end
45
+
46
+ should 'not know the values you set right away' do
47
+ @storage[:foo] = 'bar'
48
+ assert_nil @storage[:foo]
49
+ end
50
+
51
+ should 'knows the values you set next time' do
52
+ @storage[:foo] = 'bar'
53
+ @storage.sweep
54
+ assert_equal 'bar', @storage[:foo]
55
+ end
56
+
57
+ should 'set values for now' do
58
+ @storage.now[:foo] = 'bar'
59
+ assert_equal 'bar', @storage[:foo]
60
+ end
61
+
62
+ should 'forgets values you set only for now next time' do
63
+ @storage.now[:foo] = 'bar'
64
+ @storage.sweep
65
+ assert_nil @storage[:foo]
66
+ end
67
+ end
68
+
69
+ routes = Proc.new do
70
+ get :index do
71
+ params[:key] ? flash[params[:key].to_sym].to_s : flash.now.inspect
72
+ end
73
+
74
+ post :index do
75
+ params.each { |k,v| flash[k.to_sym] = v.to_s }
76
+ flash.next.inspect
77
+ end
78
+
79
+ get :session do
80
+ settings.sessions?.inspect
81
+ end
82
+
83
+ get :redirect do
84
+ redirect url(:index, :key => :foo), 301, :foo => 'redirected!'
85
+ end
86
+
87
+ get :success do
88
+ flash.success = 'Yup'
89
+ end
90
+
91
+ get :error do
92
+ flash.error = 'Arg'
93
+ end
94
+
95
+ get :notice do
96
+ flash.notice = 'Mmm'
97
+ end
98
+ end
99
+
100
+ context 'padrino application without sessions' do
101
+ before { mock_app(&routes) }
102
+
103
+ should 'show nothing' do
104
+ get '/'
105
+ assert_equal '{}', body
106
+ end
107
+
108
+ should 'set a flash' do
109
+ post '/', :foo => :bar
110
+ assert_equal '{:foo=>"bar"}', body
111
+ end
112
+ end
113
+
114
+ context 'padrino application with sessions' do
115
+ before do
116
+ mock_app { enable :sessions; class_eval(&routes) }
117
+ end
118
+
119
+ should 'be sure have sessions enabled' do
120
+ assert @app.sessions
121
+ get '/session'
122
+ assert_equal 'true', body
123
+ end
124
+
125
+ should 'show nothing' do
126
+ get '/'
127
+ assert_equal '{}', body
128
+ end
129
+
130
+ should 'set a flash' do
131
+ post '/', :foo => :bar
132
+ assert_equal '{:foo=>"bar"}', body
133
+ end
134
+
135
+ should 'get a flash' do
136
+ post '/', :foo => :bar
137
+ get '/', :key => :foo
138
+ assert_equal 'bar', body
139
+ post '/'
140
+ assert_equal '{}', body
141
+ end
142
+
143
+ should 'follow redirects with flash' do
144
+ get '/redirect'
145
+ follow_redirect!
146
+ assert_equal 'redirected!', body
147
+ assert 301, status
148
+ end
149
+
150
+ should 'set success' do
151
+ get '/success'
152
+ get '/', :key => :success
153
+ assert_equal 'Yup', body
154
+ end
155
+
156
+ should 'set error' do
157
+ get '/error'
158
+ get '/', :key => :error
159
+ assert_equal 'Arg', body
160
+ end
161
+
162
+ should 'set notice' do
163
+ get '/notice'
164
+ get '/', :key => :notice
165
+ assert_equal 'Mmm', body
166
+ end
167
+ end
168
+ end
data/test/test_logger.rb CHANGED
@@ -152,3 +152,30 @@ describe "alternate logger: stdlib logger" do
152
152
  assert_match /\e\[1m200\e\[0m OK/, @log.string
153
153
  end
154
154
  end
155
+
156
+ describe "options :colorize_logging" do
157
+ def access_to_mock_app
158
+ mock_app do
159
+ enable :logging
160
+ get("/"){ "Foo" }
161
+ end
162
+ get "/"
163
+ end
164
+ context 'default' do
165
+ should 'use colorize logging' do
166
+ Padrino::Logger.setup!
167
+
168
+ access_to_mock_app
169
+ assert_match /\e\[1m200\e\[0m OK/, Padrino.logger.log.string
170
+ end
171
+ end
172
+ context 'set value is false' do
173
+ should 'not use colorize logging' do
174
+ Padrino::Logger::Config[:test][:colorize_logging] = false
175
+ Padrino::Logger.setup!
176
+
177
+ access_to_mock_app
178
+ assert_match /200 OK/, Padrino.logger.log.string
179
+ end
180
+ end
181
+ end
data/test/test_mounter.rb CHANGED
@@ -113,11 +113,13 @@ describe "Mounter" do
113
113
  class ::OneApp < Padrino::Application
114
114
  get("/test") { "test" }
115
115
  get(:index, :provides => [:js, :json]) { "index" }
116
+ get(%r{/foo|/baz}) { "regexp" }
116
117
  controllers :posts do
117
118
  get(:index) { "index" }
118
119
  get(:new, :provides => :js) { "new" }
119
120
  get(:show, :provides => [:js, :html], :with => :id) { "show" }
120
121
  post(:create, :provides => :js, :with => :id) { "create" }
122
+ get(:regexp, :map => %r{/foo|/baz}) { "regexp" }
121
123
  end
122
124
  end
123
125
  class ::TwoApp < Padrino::Application
@@ -133,9 +135,9 @@ describe "Mounter" do
133
135
  Padrino.mount("one_app").to("/")
134
136
  Padrino.mount("two_app").to("/two_app")
135
137
 
136
- assert_equal 11, Padrino.mounted_apps[0].routes.size
138
+ assert_equal 15, Padrino.mounted_apps[0].routes.size
137
139
  assert_equal 7, Padrino.mounted_apps[1].routes.size
138
- assert_equal 5, Padrino.mounted_apps[0].named_routes.size
140
+ assert_equal 6, Padrino.mounted_apps[0].named_routes.size
139
141
  assert_equal 5, Padrino.mounted_apps[1].named_routes.size
140
142
 
141
143
  first_route = Padrino.mounted_apps[0].named_routes[3]
@@ -148,6 +150,10 @@ describe "Mounter" do
148
150
  assert_equal "(:users, :create)", another_route.name
149
151
  assert_equal "POST", another_route.verb
150
152
  assert_equal "/two_app/users/create", another_route.path
153
+ regexp_route = Padrino.mounted_apps[0].named_routes[5]
154
+ assert_equal "posts_regexp", regexp_route.identifier.to_s
155
+ assert_equal "(:posts, :regexp)", regexp_route.name
156
+ assert_equal "/\\/foo|\\/baz/", regexp_route.path
151
157
  end
152
158
 
153
159
  should 'correctly instantiate a new padrino application' do
@@ -173,5 +179,21 @@ describe "Mounter" do
173
179
  assert res.ok?
174
180
  assert_equal File.read(__FILE__), res.body
175
181
  end
182
+
183
+ should "load apps from gems" do
184
+ spec_file = Padrino.root("fixtures", "app_gem", "app_gem.gemspec")
185
+ spec = Gem::Specification.load(spec_file)
186
+ spec.activate
187
+ def spec.full_gem_path
188
+ Padrino.root("fixtures", "app_gem")
189
+ end
190
+
191
+ require Padrino.root("fixtures", "app_gem", "lib", "app_gem")
192
+
193
+ Padrino.mount("AppGem::App").to("/from_gem")
194
+ mounter = Padrino.mounted_apps[0]
195
+ assert_equal AppGem::App, mounter.app_obj
196
+ assert_equal Padrino.root('public'), mounter.app_obj.public_folder
197
+ end
176
198
  end
177
199
  end
@@ -78,20 +78,20 @@ describe "SimpleReloader" do
78
78
  last_body = body
79
79
  assert_equal 2, @app.filters[:before].size # one is ours the other is default_filter for content type
80
80
  assert_equal 1, @app.errors.size
81
- assert_equal 1, @app.filters[:after].size
81
+ assert_equal 2, @app.filters[:after].size # app + content-type + padrino-flash
82
82
  assert_equal 0, @app.middleware.size
83
83
  assert_equal 4, @app.routes.size # GET+HEAD of "/" + GET+HEAD of "/rand" = 4
84
- assert_equal 2, @app.extensions.size # [Padrino::Routing, Padrino::Rendering]
84
+ assert_equal 3, @app.extensions.size # [Padrino::Routing, Padrino::Rendering, Padrino::Flash]
85
85
  assert_equal 0, @app.templates.size
86
86
  @app.reload!
87
87
  get "/rand"
88
88
  assert_not_equal last_body, body
89
89
  assert_equal 2, @app.filters[:before].size # one is ours the other is default_filter for content type
90
90
  assert_equal 1, @app.errors.size
91
- assert_equal 1, @app.filters[:after].size
91
+ assert_equal 2, @app.filters[:after].size
92
92
  assert_equal 0, @app.middleware.size
93
93
  assert_equal 4, @app.routes.size # GET+HEAD of "/" = 2
94
- assert_equal 2, @app.extensions.size # [Padrino::Routing, Padrino::Rendering]
94
+ assert_equal 3, @app.extensions.size # [Padrino::Routing, Padrino::Rendering, Padrino::Flash]
95
95
  assert_equal 0, @app.templates.size
96
96
  end
97
97
  end
@@ -1,5 +1,6 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/helper')
2
2
  require 'i18n'
3
+ require 'slim'
3
4
 
4
5
  describe "Rendering" do
5
6
  def setup
@@ -28,7 +29,7 @@ describe "Rendering" do
28
29
  "this is a <%= yield %>"
29
30
  end
30
31
 
31
- get("/"){ render :erb, "sinatra layout" }
32
+ get("/"){ render :erb, "sinatra layout", :layout => true }
32
33
  end
33
34
 
34
35
  get "/"
@@ -137,6 +138,7 @@ describe "Rendering" do
137
138
  should 'use correct layout with each controller' do
138
139
  create_layout :foo, "foo layout at <%= yield %>"
139
140
  create_layout :bar, "bar layout at <%= yield %>"
141
+ create_layout :baz, "baz layout at <%= yield %>"
140
142
  create_layout :application, "default layout at <%= yield %>"
141
143
  mock_app do
142
144
  get("/"){ render :erb, "application" }
@@ -148,6 +150,10 @@ describe "Rendering" do
148
150
  layout :bar
149
151
  get("/"){ render :erb, "bar" }
150
152
  end
153
+ controller :baz do
154
+ layout :baz
155
+ get("/"){ render :erb, "baz", :layout => true }
156
+ end
151
157
  controller :none do
152
158
  get("/") { render :erb, "none" }
153
159
  get("/with_foo_layout") { render :erb, "none with layout", :layout => :foo }
@@ -157,6 +163,8 @@ describe "Rendering" do
157
163
  assert_equal "foo layout at foo", body
158
164
  get "/bar"
159
165
  assert_equal "bar layout at bar", body
166
+ get "/baz"
167
+ assert_equal "baz layout at baz", body
160
168
  get "/none"
161
169
  assert_equal "default layout at none", body
162
170
  get "/none/with_foo_layout"
@@ -207,7 +215,7 @@ describe "Rendering" do
207
215
  create_view :index, "<%= foo %>"
208
216
  mock_app do
209
217
  enable :logging
210
- get("/") { render "index", { :layout => true }, { :foo => "bar" } }
218
+ get("/") { render "index", { :layout => nil }, { :foo => "bar" } }
211
219
  end
212
220
  get "/"
213
221
  assert_equal "bar", body
@@ -396,7 +404,7 @@ describe "Rendering" do
396
404
  assert_equal "Im Italian Js", body
397
405
  I18n.locale = :en
398
406
  get "/foo.pk"
399
- assert_equal 405, status
407
+ assert_equal 404, status
400
408
  end
401
409
 
402
410
  should 'resolve template content_type and locale with layout' do
@@ -438,7 +446,7 @@ describe "Rendering" do
438
446
  get "/bar.json"
439
447
  assert_equal "Im a json", body
440
448
  get "/bar.pk"
441
- assert_equal 405, status
449
+ assert_equal 404, status
442
450
  end
443
451
 
444
452
  should 'renders erb with blocks' do
@@ -457,5 +465,68 @@ describe "Rendering" do
457
465
  assert ok?
458
466
  assert_equal 'THIS. IS. SPARTA!', body
459
467
  end
468
+
469
+ should 'render erb to a SafeBuffer' do
470
+ mock_app do
471
+ layout do
472
+ "this is a <%= yield %>"
473
+ end
474
+ get '/' do
475
+ render :erb, '<p><%= %q{<script lang="ronin">alert("https://github.com/ronin-ruby/ronin")</script>} %></p>', :layout => false
476
+ end
477
+ get '/with_layout' do
478
+ render :erb, '<span>span</span>', :layout => true
479
+ end
480
+ end
481
+ get '/'
482
+ assert ok?
483
+ assert_equal '<p>&lt;script lang=&quot;ronin&quot;&gt;alert(&quot;https://github.com/ronin-ruby/ronin&quot;)&lt;/script&gt;</p>', body
484
+
485
+ get '/with_layout'
486
+ assert ok?
487
+ assert_equal 'this is a <span>span</span>', body
488
+ end
489
+
490
+ should 'render haml to a SafeBuffer' do
491
+ mock_app do
492
+ layout do
493
+ "%p= yield"
494
+ end
495
+ get '/' do
496
+ render :haml, '%p= %s{<script lang="ronin">alert("https://github.com/ronin-ruby/ronin")</script>}', :layout => false
497
+ end
498
+ get '/with_layout' do
499
+ render :haml, "%div\n foo", :layout => true
500
+ end
501
+ end
502
+ get '/'
503
+ assert ok?
504
+ assert_equal '<p>&lt;script lang=&quot;ronin&quot;&gt;alert(&quot;https://github.com/ronin-ruby/ronin&quot;)&lt;/script&gt;</p>', body.strip
505
+
506
+ get 'with_layout'
507
+ assert ok?
508
+ assert_equal '<p><div>foo</div></p>', body.gsub(/\s+/, "")
509
+ end
510
+
511
+ should 'render slim to a SafeBuffer' do
512
+ mock_app do
513
+ layout do
514
+ "p= yield"
515
+ end
516
+ get '/' do
517
+ render :slim, 'p = %q{<script lang="ronin">alert("https://github.com/ronin-ruby/ronin")</script>}', :layout => false
518
+ end
519
+ get "/with_layout" do
520
+ render :slim, 'div foo', :layout => true
521
+ end
522
+ end
523
+ get '/'
524
+ assert ok?
525
+ assert_equal '<p>&lt;script lang=&quot;ronin&quot;&gt;alert(&quot;https://github.com/ronin-ruby/ronin&quot;)&lt;/script&gt;</p>', body.strip
526
+
527
+ get '/with_layout'
528
+ assert ok?
529
+ assert_equal '<p><div>foo</div></p>', body.strip
530
+ end
460
531
  end
461
532
  end
data/test/test_routing.rb CHANGED
@@ -57,12 +57,12 @@ describe "Routing" do
57
57
 
58
58
  should 'accept regexp routes' do
59
59
  mock_app do
60
- get(%r{/fob|/baz}) { "regexp" }
60
+ get(%r./fob|/baz.) { "regexp" }
61
61
  get("/foo") { "str" }
62
- get %r{/([0-9]+)/} do |num|
63
- "Your lucky number: #{num} #{params[:captures].first}"
62
+ get %r./([0-9]+)/. do |num|
63
+ "Your lucky number: #{num} #{params[:captures].first}"
64
64
  end
65
- get /\/page\/([0-9]+)|\// do |num|
65
+ get %r./page/([0-9]+)|/. do |num|
66
66
  "My lucky number: #{num} #{params[:captures].first}"
67
67
  end
68
68
  end
@@ -72,8 +72,8 @@ describe "Routing" do
72
72
  assert_equal "regexp", body
73
73
  get "/baz"
74
74
  assert_equal "regexp", body
75
- get "/1234/"
76
- assert_equal "Your lucky number: 1234 1234", body
75
+ get "/321/"
76
+ assert_equal "Your lucky number: 321 321", body
77
77
  get "/page/99"
78
78
  assert_equal "My lucky number: 99 99", body
79
79
  end
@@ -138,9 +138,9 @@ describe "Routing" do
138
138
  post("/main"){ "hello" }
139
139
  end
140
140
  assert_equal 3, app.routes.size, "should generate GET, HEAD and PUT"
141
- assert_equal ["GET"], app.routes[0].conditions[:request_method]
142
- assert_equal ["HEAD"], app.routes[1].conditions[:request_method]
143
- assert_equal ["POST"], app.routes[2].conditions[:request_method]
141
+ assert_equal "GET", app.routes[0].request_methods.first
142
+ assert_equal "HEAD", app.routes[1].request_methods.first
143
+ assert_equal "POST", app.routes[2].request_methods.first
144
144
  end
145
145
 
146
146
  should 'generate basic urls' do
@@ -192,13 +192,13 @@ describe "Routing" do
192
192
  get "/b.js"
193
193
  assert_equal "/b.js", body
194
194
  get "/b.ru"
195
- assert_equal 405, status
195
+ assert_equal 404, status
196
196
  get "/c.js"
197
197
  assert_equal "/c.json", body
198
198
  get "/c.json"
199
199
  assert_equal "/c.json", body
200
200
  get "/c.ru"
201
- assert_equal 405, status
201
+ assert_equal 404, status
202
202
  get "/d"
203
203
  assert_equal "/d.js?foo=bar", body
204
204
  get "/d.js"
@@ -255,7 +255,7 @@ describe "Routing" do
255
255
  end
256
256
 
257
257
  get "/a.xml", {}, {}
258
- assert_equal 405, status
258
+ assert_equal 404, status
259
259
  end
260
260
 
261
261
  should "not set content_type to :html if Accept */* and html not in provides" do
@@ -276,15 +276,6 @@ describe "Routing" do
276
276
  assert_equal 'json', body
277
277
  end
278
278
 
279
- should "set content_type to :json if render => :json" do
280
- mock_app do
281
- get("/foo"){ render :foo => :bar }
282
- end
283
-
284
- get '/foo'
285
- assert_equal 'application/json;charset=utf-8', content_type
286
- end
287
-
288
279
  should 'set and get content_type' do
289
280
  mock_app do
290
281
  get("/foo"){ content_type(:json); content_type.to_s }
@@ -303,6 +294,7 @@ describe "Routing" do
303
294
  end
304
295
 
305
296
  should "allow .'s in param values" do
297
+ skip
306
298
  mock_app do
307
299
  get('/id/:email', :provides => [:json]) { |email, format| [email, format] * '/' }
308
300
  end
@@ -343,7 +335,7 @@ describe "Routing" do
343
335
  end
344
336
 
345
337
  get "/a.xml", {}, {"HTTP_ACCEPT" => "text/html"}
346
- assert_equal 405, status
338
+ assert_equal 404, status
347
339
  end
348
340
 
349
341
  should "generate routes for format simple" do
@@ -371,20 +363,32 @@ describe "Routing" do
371
363
  assert_equal "mini", body
372
364
  end
373
365
 
374
- should "support not_found" do
366
+ should "should inject the action name into the request" do
375
367
  mock_app do
376
- not_found do
377
- response.status = 404
378
- 'whatever'
368
+ controller :posts do
369
+ get('/omnomnom(/:id)') { request.action.inspect }
370
+ controller :mini do
371
+ get([:a, :b, :c]) { request.action.inspect }
372
+ end
379
373
  end
374
+ end
375
+ get "/posts/omnomnom"
376
+ assert_equal "\"/omnomnom(/:id)\"", body
377
+ get "/mini/a/b/c"
378
+ assert_equal ":a", body
379
+ end
380
+
381
+ should "support not_found" do
382
+ mock_app do
383
+ not_found { 'whatever' }
380
384
 
381
385
  get :index, :map => "/" do
382
386
  'index'
383
387
  end
384
388
  end
385
- get '/something'
386
- assert_equal 'whatever', body
389
+ get '/wrong'
387
390
  assert_equal 404, status
391
+ assert_equal 'whatever', body
388
392
  get '/'
389
393
  assert_equal 'index', body
390
394
  assert_equal 200, status
@@ -393,7 +397,7 @@ describe "Routing" do
393
397
  should "should inject the route into the request" do
394
398
  mock_app do
395
399
  controller :posts do
396
- get(:index) { request.route_obj.named.to_s }
400
+ get(:index) { request.route_obj.name.to_s }
397
401
  end
398
402
  end
399
403
  get "/posts"
@@ -741,7 +745,27 @@ describe "Routing" do
741
745
  assert_equal 404, status
742
746
  end
743
747
 
748
+ should "match params and format" do
749
+ app = mock_app do
750
+ get '/:id', :provides => [:json, :html] do |id, _|
751
+ id
752
+ end
753
+
754
+ get 'format/:id', :provides => [:json, :html] do |id, format|
755
+ format
756
+ end
757
+ end
758
+
759
+ get '/123.html'
760
+ assert_equal '123', body
761
+
762
+ get 'format/123.html'
763
+ assert_equal 'html', body
764
+ end
765
+
766
+
744
767
  should 'respect priorities' do
768
+ skip
745
769
  route_order = []
746
770
  mock_app do
747
771
  get(:index, :priority => :normal) { route_order << :normal; pass }
@@ -815,6 +839,55 @@ describe "Routing" do
815
839
  assert_equal "show 3 1 2", body
816
840
  end
817
841
 
842
+ should "respect parent precedence: controllers parents go before route parents" do
843
+ mock_app do
844
+ controllers :project do
845
+ get(:index, :parent => :user) { "index #{params[:user_id]}" }
846
+ end
847
+
848
+ controllers :bar, :parent => :foo do
849
+ get(:index) { "index on foo #{params[:foo_id]} @ bar" }
850
+ get(:index, :parent => :baz) { "index on foo #{params[:foo_id]} @ baz #{params[:baz_id]} @ bar" }
851
+ end
852
+ end
853
+
854
+ get "/user/1/project"
855
+ assert_equal "index 1", body
856
+ get "/foo/1/bar"
857
+ assert_equal "index on foo 1 @ bar", body
858
+ get "/foo/1/baz/2/bar"
859
+ assert_equal "index on foo 1 @ baz 2 @ bar", body
860
+ end
861
+
862
+ should "keep a reference to the parent on the route" do
863
+ mock_app do
864
+ controllers :project do
865
+ get(:index, :parent => :user) { "index #{params[:user_id]}" }
866
+ get(:index, :parent => [:user, :section]) { "index #{params[:user_id]} #{params[:section_id]}" }
867
+ get(:edit, :with => :id, :parent => :user) { "edit #{params[:id]} #{params[:user_id]}"}
868
+ get(:show, :with => :id, :parent => [:user, :product]) { "show #{params[:id]} #{params[:user_id]} #{params[:product_id]}"}
869
+ end
870
+
871
+ controllers :bar, :parent => :foo do
872
+ get(:index) { "index on foo/bar" }
873
+ get(:index, :parent => :baz) { "index on foo/baz/bar" }
874
+ end
875
+ end
876
+
877
+ # get "/user/1/project"
878
+ assert_equal :user, @app.routes[0].parent
879
+ # get "/user/1/section/3/project"
880
+ assert_equal [:user, :section], @app.routes[2].parent
881
+ # get "/user/1/project/edit/2"
882
+ assert_equal :user, @app.routes[4].parent
883
+ # get "/user/1/product/2/project/show/3"
884
+ assert_equal [:user, :product], @app.routes[6].parent
885
+ # get "/foo/1/bar"
886
+ assert_equal :foo, @app.routes[8].parent
887
+ # get "/foo/1/baz/2/bar"
888
+ assert_equal [:foo, :baz], @app.routes[10].parent
889
+ end
890
+
818
891
  should "apply parent to controller" do
819
892
  mock_app do
820
893
  controller :project, :parent => :user do
@@ -1323,11 +1396,11 @@ describe "Routing" do
1323
1396
  get "/.json"
1324
1397
  assert_equal "This is the get index.json", body
1325
1398
  get "/.js"
1326
- assert_equal 405, status
1399
+ assert_equal 404, status
1327
1400
  post "/.json"
1328
1401
  assert_equal "This is the post index.json", body
1329
1402
  post "/.js"
1330
- assert_equal 405, status
1403
+ assert_equal 404, status
1331
1404
  end
1332
1405
 
1333
1406
  should "allow controller level mapping" do
@@ -1349,6 +1422,33 @@ describe "Routing" do
1349
1422
  assert_equal "1, 2", body
1350
1423
  end
1351
1424
 
1425
+ should "replace name of named controller with mapping path" do
1426
+ mock_app do
1427
+ controller :ugly, :map => "/pretty/:id" do
1428
+ get(:url3) { "#{params[:id]}" }
1429
+ get(:url4, :map => 'test-:id2') { "#{params[:id]}, #{params[:id2]}" }
1430
+ end
1431
+ controller :voldemort, :map => "" do
1432
+ get(:url5) { "okay" }
1433
+ end
1434
+ end
1435
+
1436
+ url = @app.url(:ugly, :url3, :id => 1)
1437
+ assert_equal "/pretty/1/url3", url
1438
+ get url
1439
+ assert_equal "1", body
1440
+
1441
+ url = @app.url(:ugly, :url4, 3, 5)
1442
+ assert_equal "/pretty/3/test-5", url
1443
+ get url
1444
+ assert_equal "3, 5", body
1445
+
1446
+ url = @app.url(:voldemort, :url5)
1447
+ assert_equal "/url5", url
1448
+ get url
1449
+ assert_equal 'okay', body
1450
+ end
1451
+
1352
1452
  should 'use absolute and relative maps' do
1353
1453
  mock_app do
1354
1454
  controller :one do
@@ -1544,8 +1644,8 @@ describe "Routing" do
1544
1644
  end
1545
1645
 
1546
1646
  should "have overideable format" do
1647
+ ::Rack::Mime::MIME_TYPES[".other"] = "text/html"
1547
1648
  mock_app do
1548
- ::Rack::Mime::MIME_TYPES[".other"] = "text/html"
1549
1649
  before do
1550
1650
  params[:format] ||= :other
1551
1651
  end
@@ -1553,6 +1653,7 @@ describe "Routing" do
1553
1653
  end
1554
1654
  get "/format_test"
1555
1655
  assert_equal "other", body
1656
+ ::Rack::Mime::MIME_TYPES.delete('.other')
1556
1657
  end
1557
1658
 
1558
1659
  should 'invokes handlers registered with ::error when raised' do
@@ -1626,13 +1727,33 @@ describe "Routing" do
1626
1727
  assert_match /not found/, body
1627
1728
  end
1628
1729
 
1629
- should 'render a custom 404 page' do
1730
+ should 'render a custom 404 page using not_found' do
1630
1731
  mock_app do
1631
- error(404) { "not found" }
1732
+ not_found { "custom 404 not found" }
1632
1733
  end
1633
1734
  get "/"
1634
1735
  assert_equal 404, status
1635
- assert_match /not found/, body
1736
+ assert_equal "custom 404 not found", body
1737
+ end
1738
+
1739
+ should 'render a custom error page using error method' do
1740
+ skip
1741
+ mock_app do
1742
+ error(404) { "custom 404 error" }
1743
+ end
1744
+ get "/"
1745
+ assert_equal 404, status
1746
+ assert_equal "custom 404 error", body
1747
+ end
1748
+
1749
+ should 'render a custom 403 page' do
1750
+ mock_app do
1751
+ error(403) { "custom 403 not found" }
1752
+ get("/") { status 403 }
1753
+ end
1754
+ get "/"
1755
+ assert_equal 403, status
1756
+ assert_equal "custom 403 not found", body
1636
1757
  end
1637
1758
 
1638
1759
  should 'recognize paths' do
@@ -1692,4 +1813,12 @@ describe "Routing" do
1692
1813
  get @app.url(:index, :page => 10)
1693
1814
  assert_equal "/paginate/66", body
1694
1815
  end
1816
+
1817
+ should 'not route get :users, :with => :id to /users//' do
1818
+ mock_app do
1819
+ get(:users, :with => :id) { 'boo' }
1820
+ end
1821
+ get '/users//'
1822
+ assert_equal 404, status
1823
+ end
1695
1824
  end