tennpipes-base 3.6.6

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 (101) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.rdoc +294 -0
  4. data/Rakefile +1 -0
  5. data/bin/tennpipes +8 -0
  6. data/lib/tennpipes-base.rb +196 -0
  7. data/lib/tennpipes-base/application.rb +175 -0
  8. data/lib/tennpipes-base/application/application_setup.rb +202 -0
  9. data/lib/tennpipes-base/application/authenticity_token.rb +25 -0
  10. data/lib/tennpipes-base/application/flash.rb +229 -0
  11. data/lib/tennpipes-base/application/params_protection.rb +129 -0
  12. data/lib/tennpipes-base/application/routing.rb +1002 -0
  13. data/lib/tennpipes-base/application/show_exceptions.rb +50 -0
  14. data/lib/tennpipes-base/caller.rb +53 -0
  15. data/lib/tennpipes-base/cli/adapter.rb +33 -0
  16. data/lib/tennpipes-base/cli/base.rb +105 -0
  17. data/lib/tennpipes-base/cli/console.rb +20 -0
  18. data/lib/tennpipes-base/cli/launcher.rb +103 -0
  19. data/lib/tennpipes-base/cli/rake.rb +50 -0
  20. data/lib/tennpipes-base/cli/rake_tasks.rb +72 -0
  21. data/lib/tennpipes-base/command.rb +38 -0
  22. data/lib/tennpipes-base/ext/sinatra.rb +29 -0
  23. data/lib/tennpipes-base/filter.rb +52 -0
  24. data/lib/tennpipes-base/images/404.png +0 -0
  25. data/lib/tennpipes-base/images/500.png +0 -0
  26. data/lib/tennpipes-base/loader.rb +202 -0
  27. data/lib/tennpipes-base/logger.rb +492 -0
  28. data/lib/tennpipes-base/module.rb +58 -0
  29. data/lib/tennpipes-base/mounter.rb +308 -0
  30. data/lib/tennpipes-base/path_router.rb +119 -0
  31. data/lib/tennpipes-base/path_router/compiler.rb +110 -0
  32. data/lib/tennpipes-base/path_router/error_handler.rb +8 -0
  33. data/lib/tennpipes-base/path_router/matcher.rb +123 -0
  34. data/lib/tennpipes-base/path_router/route.rb +169 -0
  35. data/lib/tennpipes-base/reloader.rb +309 -0
  36. data/lib/tennpipes-base/reloader/rack.rb +26 -0
  37. data/lib/tennpipes-base/reloader/storage.rb +55 -0
  38. data/lib/tennpipes-base/router.rb +98 -0
  39. data/lib/tennpipes-base/server.rb +119 -0
  40. data/lib/tennpipes-base/tasks.rb +21 -0
  41. data/lib/tennpipes-base/version.rb +20 -0
  42. data/lib/tennpipes-base/version.rb~ +20 -0
  43. data/test/fixtures/app_gem/Gemfile +4 -0
  44. data/test/fixtures/app_gem/app/app.rb +3 -0
  45. data/test/fixtures/app_gem/app_gem.gemspec +17 -0
  46. data/test/fixtures/app_gem/lib/app_gem.rb +7 -0
  47. data/test/fixtures/app_gem/lib/app_gem/version.rb +3 -0
  48. data/test/fixtures/apps/complex.rb +32 -0
  49. data/test/fixtures/apps/demo_app.rb +7 -0
  50. data/test/fixtures/apps/demo_demo.rb +7 -0
  51. data/test/fixtures/apps/demo_project/api/app.rb +7 -0
  52. data/test/fixtures/apps/demo_project/api/lib/api_lib.rb +3 -0
  53. data/test/fixtures/apps/demo_project/app.rb +7 -0
  54. data/test/fixtures/apps/external_apps/fake_lib.rb +1 -0
  55. data/test/fixtures/apps/external_apps/fake_root.rb +2 -0
  56. data/test/fixtures/apps/helpers/class_methods_helpers.rb +4 -0
  57. data/test/fixtures/apps/helpers/instance_methods_helpers.rb +4 -0
  58. data/test/fixtures/apps/helpers/support.rb +1 -0
  59. data/test/fixtures/apps/helpers/system_helpers.rb +8 -0
  60. data/test/fixtures/apps/kiq.rb +3 -0
  61. data/test/fixtures/apps/lib/myklass.rb +2 -0
  62. data/test/fixtures/apps/lib/myklass/mysubklass.rb +4 -0
  63. data/test/fixtures/apps/models/child.rb +2 -0
  64. data/test/fixtures/apps/models/parent.rb +5 -0
  65. data/test/fixtures/apps/mountable_apps/rack_apps.rb +15 -0
  66. data/test/fixtures/apps/mountable_apps/static.html +1 -0
  67. data/test/fixtures/apps/precompiled_app.rb +19 -0
  68. data/test/fixtures/apps/simple.rb +32 -0
  69. data/test/fixtures/apps/static.rb +10 -0
  70. data/test/fixtures/apps/system.rb +13 -0
  71. data/test/fixtures/apps/system_class_methods_demo.rb +7 -0
  72. data/test/fixtures/apps/system_instance_methods_demo.rb +7 -0
  73. data/test/fixtures/dependencies/a.rb +9 -0
  74. data/test/fixtures/dependencies/b.rb +4 -0
  75. data/test/fixtures/dependencies/c.rb +1 -0
  76. data/test/fixtures/dependencies/circular/e.rb +13 -0
  77. data/test/fixtures/dependencies/circular/f.rb +2 -0
  78. data/test/fixtures/dependencies/circular/g.rb +2 -0
  79. data/test/fixtures/dependencies/d.rb +4 -0
  80. data/test/fixtures/reloadable_apps/external/app/app.rb +6 -0
  81. data/test/fixtures/reloadable_apps/external/app/controllers/base.rb +6 -0
  82. data/test/fixtures/reloadable_apps/main/app.rb +10 -0
  83. data/test/helper.rb +30 -0
  84. data/test/test_application.rb +185 -0
  85. data/test/test_core.rb +93 -0
  86. data/test/test_csrf_protection.rb +208 -0
  87. data/test/test_dependencies.rb +57 -0
  88. data/test/test_filters.rb +389 -0
  89. data/test/test_flash.rb +168 -0
  90. data/test/test_locale.rb +21 -0
  91. data/test/test_logger.rb +295 -0
  92. data/test/test_mounter.rb +302 -0
  93. data/test/test_params_protection.rb +195 -0
  94. data/test/test_reloader_complex.rb +74 -0
  95. data/test/test_reloader_external.rb +21 -0
  96. data/test/test_reloader_simple.rb +101 -0
  97. data/test/test_reloader_system.rb +113 -0
  98. data/test/test_restful_routing.rb +33 -0
  99. data/test/test_router.rb +281 -0
  100. data/test/test_routing.rb +2328 -0
  101. metadata +301 -0
@@ -0,0 +1,302 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+
3
+ describe "Mounter" do
4
+ class ::TestApp < Tennpipes::Application; end
5
+
6
+ def setup
7
+ $VERBOSE, @_verbose_was = nil, $VERBOSE
8
+ Tennpipes.clear!
9
+ end
10
+
11
+ def teardown
12
+ $VERBOSE = @_verbose_was
13
+ end
14
+
15
+ describe 'for mounter functionality' do
16
+ it 'should check methods' do
17
+ mounter = Tennpipes::Mounter.new("test_app", :app_file => "/path/to/test.rb")
18
+ mounter.to("/test_app")
19
+ assert_kind_of Tennpipes::Mounter, mounter
20
+ assert_respond_to Tennpipes::Mounter, :new
21
+ assert_respond_to mounter, :to
22
+ assert_respond_to mounter, :map_onto
23
+ assert_equal "test_app", mounter.name
24
+ assert_equal "TestApp", mounter.app_class
25
+ assert_equal "/path/to/test.rb", mounter.app_file
26
+ assert_equal "/test_app", mounter.uri_root
27
+ assert_equal Tennpipes.root, mounter.app_root
28
+ end
29
+
30
+ it 'should use app.root if available' do
31
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/kiq')
32
+ mounter = Tennpipes::Mounter.new("kiq", :app_class => "Kiq")
33
+ mounter.to("/test_app")
34
+ assert_equal '/weird', mounter.app_root
35
+ end
36
+
37
+ it 'should check locate_app_file with __FILE__' do
38
+ mounter = Tennpipes::Mounter.new("test_app", :app_file => __FILE__)
39
+ mounter.to("/test_app")
40
+ assert_equal "test_app", mounter.name
41
+ assert_equal "TestApp", mounter.app_class
42
+ assert_equal __FILE__, mounter.app_file
43
+ assert_equal "/test_app", mounter.uri_root
44
+ assert_equal File.dirname(mounter.app_file), mounter.app_root
45
+ end
46
+
47
+ it 'should mount an app' do
48
+ class ::AnApp < Tennpipes::Application; end
49
+ Tennpipes.mount("an_app").to("/")
50
+ assert_equal AnApp, Tennpipes.mounted_apps.first.app_obj
51
+ assert_equal ["an_app"], Tennpipes.mounted_apps.map(&:name)
52
+ end
53
+
54
+ it 'should correctly mount an app in a namespace' do
55
+ module ::SomeNamespace
56
+ class AnApp < Tennpipes::Application; end
57
+ end
58
+ Tennpipes.mount("some_namespace/an_app").to("/")
59
+ assert_equal SomeNamespace::AnApp, Tennpipes.mounted_apps.first.app_obj
60
+ assert_equal ["some_namespace/an_app"], Tennpipes.mounted_apps.map(&:name)
61
+ end
62
+
63
+ it 'should correctly set a name of a namespaced app' do
64
+ module ::SomeNamespace2
65
+ class AnApp < Tennpipes::Application
66
+ get(:index) { settings.app_name }
67
+ end
68
+ end
69
+ Tennpipes.mount("SomeNamespace2::AnApp").to("/")
70
+ res = Rack::MockRequest.new(Tennpipes.application).get("/")
71
+ assert_equal "some_namespace2/an_app", res.body
72
+ end
73
+
74
+ it 'should mount a primary app to root uri' do
75
+ mounter = Tennpipes.mount("test_app", :app_file => __FILE__).to("/")
76
+ assert_equal "test_app", mounter.name
77
+ assert_equal "TestApp", mounter.app_class
78
+ assert_equal TestApp, mounter.app_obj
79
+ assert_equal __FILE__, mounter.app_file
80
+ assert_equal "/", mounter.uri_root
81
+ assert_equal File.dirname(mounter.app_file), mounter.app_root
82
+ end
83
+
84
+ it 'should mount a primary app to sub_uri' do
85
+ mounter = Tennpipes.mount("test_app", :app_file => __FILE__).to('/me')
86
+ assert_equal "test_app", mounter.name
87
+ assert_equal "TestApp", mounter.app_class
88
+ assert_equal TestApp, mounter.app_obj
89
+ assert_equal __FILE__, mounter.app_file
90
+ assert_equal "/me", mounter.uri_root
91
+ assert_equal File.dirname(mounter.app_file), mounter.app_root
92
+ end
93
+
94
+ it 'should raise error when app has no located file' do
95
+ # TODO enabling this screws minitest
96
+ # assert_raises(Tennpipes::Mounter::MounterException) { Tennpipes.mount("tester_app").to('/test') }
97
+ assert_equal 0, Tennpipes.mounted_apps.size
98
+ end
99
+
100
+ it 'should raise error when app has no located object' do
101
+ assert_raises(Tennpipes::Mounter::MounterException) { Tennpipes.mount("tester_app", :app_file => "/path/to/file.rb").to('/test') }
102
+ assert_equal 0, Tennpipes.mounted_apps.size
103
+ end
104
+
105
+ it 'should mount multiple apps' do
106
+ class ::OneApp < Tennpipes::Application; end
107
+ class ::TwoApp < Tennpipes::Application; end
108
+
109
+ Tennpipes.mount("one_app").to("/one_app")
110
+ Tennpipes.mount("two_app").to("/two_app")
111
+ # And testing no duplicates
112
+ Tennpipes.mount("one_app").to("/one_app")
113
+ Tennpipes.mount("two_app").to("/two_app")
114
+
115
+ assert_equal OneApp, Tennpipes.mounted_apps[0].app_obj
116
+ assert_equal TwoApp, Tennpipes.mounted_apps[1].app_obj
117
+ assert_equal 2, Tennpipes.mounted_apps.size, "should not mount duplicate apps"
118
+ assert_equal ["one_app", "two_app"], Tennpipes.mounted_apps.map(&:name)
119
+ end
120
+
121
+ it 'should mount app with the same name as the module' do
122
+ Tennpipes.mount("Demo::App", :app_file => File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/demo_app.rb')).to("/app")
123
+ Tennpipes.mount("Demo::Demo", :app_file => File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/demo_demo.rb')).to("/")
124
+
125
+ Tennpipes.mounted_apps.each do |app|
126
+ assert_equal app.app_obj.setup_application!, true
127
+ end
128
+ end
129
+
130
+ it 'should change mounted_root' do
131
+ Tennpipes.mounted_root = "fixtures"
132
+ assert_equal Tennpipes.root("fixtures", "test", "app.rb"), Tennpipes.mounted_root("test", "app.rb")
133
+ Tennpipes.mounted_root = "apps"
134
+ assert_equal Tennpipes.root("apps", "test", "app.rb"), Tennpipes.mounted_root("test", "app.rb")
135
+ Tennpipes.mounted_root = nil
136
+ assert_equal Tennpipes.root("test", "app.rb"), Tennpipes.mounted_root("test", "app.rb")
137
+ end
138
+
139
+ it 'should be able to access routes data for mounted apps' do
140
+ class ::OneApp < Tennpipes::Application
141
+ get("/test") { "test" }
142
+ get(:index, :provides => [:js, :json]) { "index" }
143
+ get(%r{/foo|/baz}) { "regexp" }
144
+ controllers :posts do
145
+ get(:index) { "index" }
146
+ get(:new, :provides => :js) { "new" }
147
+ get(:show, :provides => [:js, :html], :with => :id) { "show" }
148
+ post(:create, :provides => :js, :with => :id) { "create" }
149
+ get(:regexp, :map => %r{/foo|/baz}) { "regexp" }
150
+ end
151
+ end
152
+ class ::TwoApp < Tennpipes::Application
153
+ controllers :users do
154
+ get(:index) { "users" }
155
+ get(:new) { "users new" }
156
+ post(:create) { "users create" }
157
+ put(:update) { "users update" }
158
+ delete(:destroy) { "users delete" }
159
+ end
160
+ controllers :foo_bar do
161
+ get(:index) { "foo bar index" }
162
+ get(:new) { "foo bar new" }
163
+ post(:create) { "foo bar create" }
164
+ put(:update) { "foo bar update" }
165
+ delete(:destroy) { "foo bar delete" }
166
+ end
167
+ controllers :test, :nested do
168
+ get(:test1){ "test1" }
169
+ end
170
+ end
171
+
172
+ Tennpipes.mount("one_app").to("/")
173
+ Tennpipes.mount("two_app").to("/two_app")
174
+
175
+ assert_equal 15, Tennpipes.mounted_apps[0].routes.size
176
+ assert_equal 16, Tennpipes.mounted_apps[1].routes.size
177
+ assert_equal 6, Tennpipes.mounted_apps[0].named_routes.size
178
+ assert_equal 11, Tennpipes.mounted_apps[1].named_routes.size
179
+
180
+ first_route = Tennpipes.mounted_apps[0].named_routes[3]
181
+ assert_equal "posts show", first_route.identifier.to_s
182
+ assert_equal "(:posts, :show)", first_route.name
183
+ assert_equal "GET", first_route.verb
184
+ assert_equal "/posts/show/:id(.:format)?", first_route.path
185
+ another_route = Tennpipes.mounted_apps[1].named_routes[2]
186
+ assert_equal "users create", another_route.identifier.to_s
187
+ assert_equal "(:users, :create)", another_route.name
188
+ assert_equal "POST", another_route.verb
189
+ assert_equal "/two_app/users/create", another_route.path
190
+ regexp_route = Tennpipes.mounted_apps[0].named_routes[5]
191
+ assert_equal "posts regexp", regexp_route.identifier.to_s
192
+ assert_equal "(:posts, :regexp)", regexp_route.name
193
+ assert_equal "/\\/foo|\\/baz/", regexp_route.path
194
+ foo_bar_route = Tennpipes.mounted_apps[1].named_routes[5]
195
+ assert_equal "(:foo_bar, :index)", foo_bar_route.name
196
+ nested_route = Tennpipes.mounted_apps[1].named_routes[10]
197
+ assert_equal "(:test_nested, :test1)", nested_route.name
198
+ end
199
+
200
+ it 'should configure cascade apps' do
201
+ class ::App1 < Tennpipes::Application
202
+ get(:index) { halt 404, 'index1' }
203
+ end
204
+ class ::App2 < Tennpipes::Application
205
+ get(:index) { halt 404, 'index2' }
206
+ end
207
+ class ::App3 < Tennpipes::Application
208
+ get(:index) { halt 404, 'index3' }
209
+ end
210
+ Tennpipes.mount('app1', :cascade => true).to('/foo')
211
+ Tennpipes.mount('app2').to('/foo')
212
+ Tennpipes.mount('app3').to('/foo')
213
+ res = Rack::MockRequest.new(Tennpipes.application).get("/foo")
214
+ assert_equal 'index2', res.body
215
+ end
216
+
217
+ it 'should correctly instantiate a new tennpipes application' do
218
+ mock_app do
219
+ get("/demo_1"){ "Im Demo 1" }
220
+ get("/demo_2"){ "Im Demo 2" }
221
+ end
222
+
223
+ get '/demo_1'
224
+ assert_equal "Im Demo 1", response.body
225
+ get '/demo_2'
226
+ assert_equal "Im Demo 2", response.body
227
+ end
228
+
229
+ it 'should not clobber the public setting when mounting an app' do
230
+ class ::PublicApp < Tennpipes::Application
231
+ set :root, "/root"
232
+ set :public_folder, File.expand_path(File.dirname(__FILE__))
233
+ end
234
+
235
+ Tennpipes.mount("public_app").to("/public")
236
+ res = Rack::MockRequest.new(Tennpipes.application).get("/public/test_mounter.rb")
237
+ assert res.ok?
238
+ assert_equal File.read(__FILE__), res.body
239
+ end
240
+
241
+ it 'should load apps from gems' do
242
+ spec_file = Tennpipes.root("fixtures", "app_gem", "app_gem.gemspec")
243
+ spec = Gem::Specification.load(spec_file)
244
+ spec.activate
245
+ def spec.full_gem_path
246
+ Tennpipes.root("fixtures", "app_gem")
247
+ end
248
+
249
+ require Tennpipes.root("fixtures", "app_gem", "lib", "app_gem")
250
+
251
+ Tennpipes.mount("AppGem::App").to("/from_gem")
252
+ mounter = Tennpipes.mounted_apps[0]
253
+ assert_equal AppGem::App, mounter.app_obj
254
+ assert_equal Tennpipes.root('public'), mounter.app_obj.public_folder
255
+ end
256
+
257
+ it 'should support the Rack Application' do
258
+ path = File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/mountable_apps/rack_apps')
259
+ require path
260
+ Tennpipes.mount('rack_app', :app_class => 'RackApp', :app_file => path).to('/rack_app')
261
+ Tennpipes.mount('rack_app2', :app_class => 'RackApp2', :app_file => path).to('/rack_app2')
262
+ Tennpipes.mount('sinatra_app', :app_class => 'SinatraApp', :app_file => path).to('/sinatra_app')
263
+ app = Tennpipes.application
264
+ res = Rack::MockRequest.new(app).get("/rack_app")
265
+ assert_equal "hello rack app", res.body
266
+ res = Rack::MockRequest.new(app).get("/rack_app2")
267
+ assert_equal "hello rack app2", res.body
268
+ res = Rack::MockRequest.new(app).get("/sinatra_app")
269
+ assert_equal "hello sinatra app", res.body
270
+ res = Rack::MockRequest.new(app).get("/sinatra_app/static.html")
271
+ assert_equal "hello static file\n", res.body
272
+ end
273
+
274
+ it 'should support the Rack Application inside tennpipes project' do
275
+ path = File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/demo_project/app')
276
+ api_path = File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/demo_project/api/app')
277
+ require path
278
+ require api_path
279
+ Tennpipes.mount('api_app', :app_class => 'DemoProject::API', :app_file => api_path).to('/api')
280
+ Tennpipes.mount('main_app', :app_class => 'DemoProject::App').to('/')
281
+ app = Tennpipes.application
282
+ res = Rack::MockRequest.new(app).get("/")
283
+ assert_equal "tennpipes app", res.body
284
+ res = Rack::MockRequest.new(app).get("/api/hey")
285
+ assert_equal "api app", res.body
286
+ assert defined?(DemoProject::APILib)
287
+ end
288
+
289
+ it "should not load dependency files if app's root isn't started with Tennpipes.root" do
290
+ path = File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/demo_project/app')
291
+ fake_path = File.expand_path(File.dirname(__FILE__) + "/fixtures/apps/external_apps/fake_root")
292
+ require path
293
+ require fake_path
294
+ Tennpipes.mount("fake_root", :app_class => "FakeRoot").to('/fake_root')
295
+ Tennpipes.mount('main_app', :app_class => 'DemoProject::App').to('/')
296
+ Tennpipes.stub(:root, File.expand_path(File.dirname(__FILE__) + "/fixtures/apps/demo_project")) do
297
+ Tennpipes.application
298
+ end
299
+ assert !defined?(FakeLib)
300
+ end
301
+ end
302
+ end
@@ -0,0 +1,195 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+ require 'active_support/core_ext/hash/conversions'
3
+
4
+ describe "Tennpipes::ParamsProtection" do
5
+ before do
6
+ @teri = { 'name' => 'Teri Bauer', 'position' => 'baby' }
7
+ @kim = { 'name' => 'Kim Bauer', 'position' => 'daughter', 'child' => @teri }
8
+ @jack = { 'name' => 'Jack Bauer', 'position' => 'terrorist', 'child' => @kim }
9
+ @family = { 'name' => 'Bauer', 'persons' => { 1 => @teri, 2 => @kim, 3 => @jack } }
10
+ end
11
+
12
+ it 'should drop all parameters except allowed ones' do
13
+ result = nil
14
+ mock_app do
15
+ post :basic, :params => [ :name ] do
16
+ result = params
17
+ ''
18
+ end
19
+ end
20
+ post '/basic?' + @jack.to_query
21
+ assert_equal({ 'name' => @jack['name'] }, result)
22
+ end
23
+
24
+ it 'should preserve original params' do
25
+ result = nil
26
+ mock_app do
27
+ post :basic, :params => [ :name ] do
28
+ result = original_params
29
+ ''
30
+ end
31
+ end
32
+ post '/basic?' + @jack.to_query
33
+ assert_equal(@jack, result)
34
+ end
35
+
36
+ it 'should work with recursive data' do
37
+ result = nil
38
+ mock_app do
39
+ post :basic, :params => [ :name, :child => [ :name, :child => [ :name ] ] ] do
40
+ result = [params, original_params]
41
+ ''
42
+ end
43
+ end
44
+ post '/basic?' + @jack.to_query
45
+ assert_equal(
46
+ [
47
+ { 'name' => @jack['name'], 'child' => { 'name' => @kim['name'], 'child' => { 'name' => @teri['name'] } } },
48
+ @jack
49
+ ],
50
+ result
51
+ )
52
+ end
53
+
54
+ it 'should be able to process the data' do
55
+ result = nil
56
+ mock_app do
57
+ post :basic, :params => [ :name, :position => proc{ |v| 'anti-'+v } ] do
58
+ result = params
59
+ ''
60
+ end
61
+ end
62
+ post '/basic?' + @jack.to_query
63
+ assert_equal({ 'name' => @jack['name'], 'position' => 'anti-terrorist' }, result)
64
+ end
65
+
66
+ it 'should pass :with parameters' do
67
+ result = nil
68
+ mock_app do
69
+ post :basic, :with => [:id, :tag], :params => [ :name ] do
70
+ result = params
71
+ ''
72
+ end
73
+ end
74
+ post '/basic/24/42?' + @jack.to_query
75
+ assert_equal({ 'name' => @jack['name'], 'id' => '24', 'tag' => '42' }, result)
76
+ end
77
+
78
+ it 'should not fail if :with is not an Array' do
79
+ result = nil
80
+ mock_app do
81
+ post :basic, :with => :id, :params => [ :id ] do
82
+ result = params
83
+ ''
84
+ end
85
+ end
86
+ post '/basic/24?' + @jack.to_query
87
+ assert_equal({ 'id' => '24' }, result)
88
+ end
89
+
90
+ it 'should understand true or false values' do
91
+ result = nil
92
+ mock_app do
93
+ get :hide, :with => [ :id ], :params => false do
94
+ result = params
95
+ ''
96
+ end
97
+ get :show, :with => [ :id ], :params => true do
98
+ result = params
99
+ ''
100
+ end
101
+ end
102
+ get '/hide/1?' + @jack.to_query
103
+ assert_equal({"id"=>"1"}, result)
104
+ get '/show/1?' + @jack.to_query
105
+ assert_equal({"id"=>"1"}.merge(@jack), result)
106
+ end
107
+
108
+ it 'should be configurable with controller options' do
109
+ result = nil
110
+ mock_app do
111
+ controller :persons, :params => [ :name ] do
112
+ post :create, :params => [ :name, :position ] do
113
+ result = params
114
+ ''
115
+ end
116
+ post :update, :with => [ :id ] do
117
+ result = params
118
+ ''
119
+ end
120
+ post :delete, :params => true do
121
+ result = params
122
+ ''
123
+ end
124
+ post :destroy, :with => [ :id ], :params => false do
125
+ result = params
126
+ ''
127
+ end
128
+ end
129
+ controller :noparam, :params => false do
130
+ get :index do
131
+ result = params
132
+ ''
133
+ end
134
+ end
135
+ end
136
+ post '/persons/create?' + @jack.to_query
137
+ assert_equal({ 'name' => @jack['name'], 'position' => 'terrorist' }, result)
138
+ post '/persons/update/1?name=Chloe+O\'Brian&position=hacker'
139
+ assert_equal({ 'id' => '1', 'name' => 'Chloe O\'Brian' }, result)
140
+ post '/persons/delete?' + @jack.to_query
141
+ assert_equal(@jack, result)
142
+ post '/persons/destroy/1?' + @jack.to_query
143
+ assert_equal({"id"=>"1"}, result)
144
+ get '/noparam?a=1;b=2'
145
+ assert_equal({}, result)
146
+ end
147
+
148
+ it 'should successfully filter hashes' do
149
+ result = nil
150
+ mock_app do
151
+ post :family, :params => [ :persons => [ :name ] ] do
152
+ result = params
153
+ ''
154
+ end
155
+ end
156
+ post '/family?' + @family.to_query
157
+ assert_equal({"persons" => {"3" => {"name" => @jack["name"]}, "2" => {"name" => @kim["name"]}, "1" => {"name" => @teri["name"]}}}, result)
158
+ end
159
+
160
+ it 'should pass arrays' do
161
+ result = nil
162
+ mock_app do
163
+ post :family, :params => [ :names => [] ] do
164
+ result = params
165
+ ''
166
+ end
167
+ end
168
+ post '/family?' + { :names => %w{Jack Kim Teri} }.to_query
169
+ assert_equal({"names" => %w[Jack Kim Teri]}, result)
170
+ end
171
+
172
+ it 'should tolerate weird inflections' do
173
+ result = nil
174
+ mock_app do
175
+ post :i, :params => [ :gotta => [ :what ] ] do
176
+ result = params
177
+ ''
178
+ end
179
+ end
180
+ post '/i?' + { :gotta => { :what => 'go', :who => 'self' } }.to_query
181
+ assert_equal({"gotta" => {"what" => "go"}}, result)
182
+ end
183
+
184
+ it 'should drop the key if the data type does not match route configuration' do
185
+ result = nil
186
+ mock_app do
187
+ post :i, :params => [ :gotta => [ :what ] ] do
188
+ result = params
189
+ ''
190
+ end
191
+ end
192
+ post '/i?gotta=go'
193
+ assert_equal({}, result)
194
+ end
195
+ end