padrino-core 0.10.7 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
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