tennpipes-base 3.6.6

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