merb 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. data/README +23 -160
  2. data/Rakefile +15 -14
  3. data/app_generators/merb/merb_generator.rb +4 -3
  4. data/app_generators/merb/templates/Rakefile +1 -6
  5. data/app_generators/merb/templates/app/mailers/views/layout/{application.erb → application.html.erb} +0 -0
  6. data/app_generators/merb/templates/app/mailers/views/layout/application.text.erb +1 -0
  7. data/app_generators/merb/templates/app/parts/views/layout/application.html.erb +1 -0
  8. data/app_generators/merb/templates/app/views/layout/application.html.erb +2 -2
  9. data/app_generators/merb/templates/config/dependencies.rb +1 -1
  10. data/app_generators/merb/templates/config/router.rb +4 -1
  11. data/app_generators/merb/templates/spec/spec_helper.rb +2 -3
  12. data/lib/autotest/merb_rspec.rb +1 -0
  13. data/lib/merb/abstract_controller.rb +31 -2
  14. data/lib/merb/controller.rb +5 -5
  15. data/lib/merb/core_ext/get_args.rb +5 -1
  16. data/lib/merb/exceptions.rb +17 -0
  17. data/lib/merb/generators/merb_app/merb_app.rb +4 -1
  18. data/lib/merb/generators/merb_plugin.rb +4 -1
  19. data/lib/merb/logger.rb +5 -1
  20. data/lib/merb/mail_controller.rb +1 -1
  21. data/lib/merb/mailer.rb +2 -2
  22. data/lib/merb/mixins/controller.rb +5 -1
  23. data/lib/merb/mixins/render.rb +57 -27
  24. data/lib/merb/part_controller.rb +1 -1
  25. data/lib/merb/request.rb +2 -2
  26. data/lib/merb/server.rb +33 -5
  27. data/lib/merb/template/erubis.rb +1 -1
  28. data/lib/merb.rb +15 -5
  29. data/merb_generators/resource/resource_generator.rb +9 -2
  30. data/spec/fixtures/config/merb.yml +18 -0
  31. data/spec/fixtures/controllers/dispatch_spec_controllers.rb +227 -0
  32. data/spec/fixtures/controllers/render_spec_controllers.rb +115 -0
  33. data/spec/fixtures/foo.rb +3 -0
  34. data/spec/fixtures/mailers/views/layout/application.html.erb +3 -0
  35. data/spec/fixtures/mailers/views/layout/application.text.erb +3 -0
  36. data/spec/fixtures/mailers/views/test_mail_controller/eighth.html.erb +1 -0
  37. data/spec/fixtures/mailers/views/test_mail_controller/eighth.text.erb +1 -0
  38. data/spec/fixtures/mailers/views/test_mail_controller/first.html.erb +1 -0
  39. data/spec/fixtures/mailers/views/test_mail_controller/first.text.erb +1 -0
  40. data/spec/fixtures/mailers/views/test_mail_controller/ninth.html.erb +1 -0
  41. data/spec/fixtures/mailers/views/test_mail_controller/ninth.text.erb +1 -0
  42. data/spec/fixtures/mailers/views/test_mail_controller/second.text.erb +1 -0
  43. data/spec/fixtures/mailers/views/test_mail_controller/third.html.erb +1 -0
  44. data/spec/fixtures/models/router_spec_models.rb +20 -0
  45. data/spec/fixtures/parts/views/layout/todo_part.html.erb +3 -0
  46. data/spec/fixtures/parts/views/layout/todo_part.xml.erb +3 -0
  47. data/spec/fixtures/parts/views/todo_part/formatted_output.html.erb +1 -0
  48. data/spec/fixtures/parts/views/todo_part/formatted_output.js.erb +1 -0
  49. data/spec/fixtures/parts/views/todo_part/formatted_output.xml.erb +1 -0
  50. data/spec/fixtures/parts/views/todo_part/list.html.erb +3 -0
  51. data/spec/fixtures/sample.txt +1 -0
  52. data/spec/fixtures/views/erubis.html.erb +1 -0
  53. data/spec/fixtures/views/examples/_erubis.html.erb +1 -0
  54. data/spec/fixtures/views/examples/_haml.html.haml +1 -0
  55. data/spec/fixtures/views/examples/_markaby.html.mab +1 -0
  56. data/spec/fixtures/views/examples/_throw_content.html.erb +6 -0
  57. data/spec/fixtures/views/examples/hello.xml.builder +1 -0
  58. data/spec/fixtures/views/examples/js.js.erb +1 -0
  59. data/spec/fixtures/views/examples/template_catch_content.html.erb +15 -0
  60. data/spec/fixtures/views/examples/template_catch_content_from_partial.html.erb +6 -0
  61. data/spec/fixtures/views/examples/template_throw_content.html.erb +10 -0
  62. data/spec/fixtures/views/exceptions/admin_access_required.html.erb +1 -0
  63. data/spec/fixtures/views/extension_template_controller/_nested_js.js.erb +1 -0
  64. data/spec/fixtures/views/extension_template_controller/_nested_xml.xml.erb +1 -0
  65. data/spec/fixtures/views/extension_template_controller/_render_partial_multiple_times.html.erb +1 -0
  66. data/spec/fixtures/views/extension_template_controller/erubis_templates.html.erb +1 -0
  67. data/spec/fixtures/views/extension_template_controller/erubis_templates.js.erb +1 -0
  68. data/spec/fixtures/views/extension_template_controller/erubis_templates.rhtml +1 -0
  69. data/spec/fixtures/views/extension_template_controller/erubis_templates.xml.erb +1 -0
  70. data/spec/fixtures/views/extension_template_controller/haml_index.html.haml +0 -0
  71. data/spec/fixtures/views/extension_template_controller/haml_templates.html.haml +1 -0
  72. data/spec/fixtures/views/extension_template_controller/haml_templates.js.haml +1 -0
  73. data/spec/fixtures/views/extension_template_controller/haml_templates.xml.haml +1 -0
  74. data/spec/fixtures/views/extension_template_controller/index.html.erb +0 -0
  75. data/spec/fixtures/views/extension_template_controller/markaby_index.html.mab +0 -0
  76. data/spec/fixtures/views/extension_template_controller/markaby_templates.html.mab +1 -0
  77. data/spec/fixtures/views/extension_template_controller/markaby_templates.js.mab +1 -0
  78. data/spec/fixtures/views/extension_template_controller/markaby_templates.xml.mab +1 -0
  79. data/spec/fixtures/views/extension_template_controller/render_multiple_partials.html.erb +4 -0
  80. data/spec/fixtures/views/extension_template_controller/render_nested_js.js.erb +1 -0
  81. data/spec/fixtures/views/extension_template_controller/render_nested_xml.xml.erb +1 -0
  82. data/spec/fixtures/views/haml.html.haml +1 -0
  83. data/spec/fixtures/views/haml.xml.haml +2 -0
  84. data/spec/fixtures/views/layout/application.html.erb +1 -0
  85. data/spec/fixtures/views/layout/application.xml.erb +1 -0
  86. data/spec/fixtures/views/layout/nested/example.html.erb +1 -0
  87. data/spec/fixtures/views/markaby.html.mab +1 -0
  88. data/spec/fixtures/views/nested/example/test.html.erb +1 -0
  89. data/spec/fixtures/views/partials/_erubis.html.erb +1 -0
  90. data/spec/fixtures/views/partials/_erubis_collection.html.erb +1 -0
  91. data/spec/fixtures/views/partials/_erubis_collection_with_locals.html.erb +1 -0
  92. data/spec/fixtures/views/partials/_erubis_new.html.erb +1 -0
  93. data/spec/fixtures/views/partials/_haml.html.haml +1 -0
  94. data/spec/fixtures/views/partials/_haml_collection.html.haml +1 -0
  95. data/spec/fixtures/views/partials/_haml_collection_with_locals.html.haml +1 -0
  96. data/spec/fixtures/views/partials/_haml_new.html.haml +1 -0
  97. data/spec/fixtures/views/partials/_markaby.html.mab +1 -0
  98. data/spec/fixtures/views/partials/_markaby_collection.html.mab +1 -0
  99. data/spec/fixtures/views/partials/_markaby_collection_with_locals.html.mab +1 -0
  100. data/spec/fixtures/views/partials/_markaby_new.html.mab +1 -0
  101. data/spec/fixtures/views/render_object_controller/render_object_with_template.html.erb +1 -0
  102. data/spec/fixtures/views/render_object_controller/render_object_with_template.js.erb +1 -0
  103. data/spec/fixtures/views/render_object_controller/render_object_with_template.xml.erb +1 -0
  104. data/spec/fixtures/views/template_views/interface__buffer_erubis.html.erb +4 -0
  105. data/spec/fixtures/views/template_views/interface__buffer_haml.html.haml +7 -0
  106. data/spec/fixtures/views/template_views/interface__buffer_markaby.html.mab +7 -0
  107. data/spec/fixtures/views/template_views/interface_capture_erubis.html.erb +15 -0
  108. data/spec/fixtures/views/template_views/interface_capture_haml.html.haml +15 -0
  109. data/spec/fixtures/views/template_views/interface_capture_markaby.html.mab +4 -0
  110. data/spec/fixtures/views/template_views/interface_concat_erubis.html.erb +12 -0
  111. data/spec/fixtures/views/template_views/interface_concat_haml.html.haml +11 -0
  112. data/spec/fixtures/views/template_views/interface_concat_markaby.html.mab +14 -0
  113. data/spec/fixtures/views/test.dir/the_template.html.erb +1 -0
  114. data/spec/merb/abstract_controller_spec.rb +37 -0
  115. data/spec/merb/caching_spec.rb +102 -0
  116. data/spec/merb/config_spec.rb +29 -0
  117. data/spec/merb/controller_filters_spec.rb +188 -0
  118. data/spec/merb/controller_spec.rb +144 -0
  119. data/spec/merb/cookie_store_spec.rb +85 -0
  120. data/spec/merb/core_ext_spec.rb +430 -0
  121. data/spec/merb/dispatch_spec.rb +514 -0
  122. data/spec/merb/fake_request_spec.rb +72 -0
  123. data/spec/merb/form_control_mixin_spec.rb +431 -0
  124. data/spec/merb/generator_spec.rb +121 -0
  125. data/spec/merb/handler_spec.rb +169 -0
  126. data/spec/merb/mail_controller_spec.rb +144 -0
  127. data/spec/merb/mailer_spec.rb +87 -0
  128. data/spec/merb/multipart_spec.rb +49 -0
  129. data/spec/merb/part_controller_spec.rb +92 -0
  130. data/spec/merb/plugins_spec.rb +80 -0
  131. data/spec/merb/render_spec.rb +378 -0
  132. data/spec/merb/request_spec.rb +243 -0
  133. data/spec/merb/responder_spec.rb +561 -0
  134. data/spec/merb/router_spec.rb +726 -0
  135. data/spec/merb/template_spec.rb +41 -0
  136. data/spec/merb/upload_handler_spec.rb +101 -0
  137. data/spec/merb/view_context_spec.rb +148 -0
  138. data/spec/spec_generator_helper.rb +19 -0
  139. data/spec/spec_helper.rb +88 -0
  140. metadata +203 -65
  141. data/lib/merb/caching/store/memcache.rb +0 -20
  142. data/script/destroy +0 -14
  143. data/script/generate +0 -14
@@ -0,0 +1,378 @@
1
+ require 'stringio'
2
+ require File.dirname(__FILE__) + '/../spec_helper'
3
+ require File.dirname(__FILE__) + '/../fixtures/controllers/render_spec_controllers'
4
+
5
+ describe "rendering engines except XMLBuilder", :shared => true do
6
+ it "should render a template" do
7
+ c = new_controller
8
+ content = c.render :template => "#{@engine}", :layout => :none
9
+ content.clean.should == "Hello!"
10
+ end
11
+
12
+ it "should render a partial" do
13
+ c = new_controller
14
+ content = c.partial "partials/#{@engine}"
15
+ content.clean.should == "No Locals!"
16
+ end
17
+
18
+ it "should render a partial with locals" do
19
+ c = new_controller
20
+ content = c.partial "partials/#{@engine}", :yo => "Locals!"
21
+ content.clean.should == "Locals!"
22
+ end
23
+
24
+ it "should render a partial using the :partial method" do
25
+ c = new_controller
26
+ content = c.partial("partials/#{@engine}")
27
+ content.clean.should == "No Locals!"
28
+ end
29
+
30
+ it "should render a partial using the :partial method with locals" do
31
+ c = new_controller
32
+ content = c.partial("partials/#{@engine}", :yo => "Locals!")
33
+ content.clean.should == "Locals!"
34
+ end
35
+
36
+ it "should render a partial iterating over a collection" do
37
+ c = new_controller
38
+ content = c.partial("partials/#{@engine}_collection",
39
+ :with => (1..10).to_a)
40
+ content.clean.should == (1..10).to_a.join("\n")
41
+ end
42
+
43
+ it "should render a partial with an object" do
44
+ c = new_controller
45
+ content = c.partial("partials/#{@engine}_collection", :with => 1)
46
+ content.clean.should == '1'
47
+ end
48
+
49
+ it "should allow you to overwrite the local var using :as when rendering a collection" do
50
+ c = new_controller
51
+ content = c.partial("partials/#{@engine}_collection_with_locals", :with => (1..10).to_a, :as => :number)
52
+ content.clean.should == (1..10).to_a.join("\n")
53
+ end
54
+
55
+ it "should allow you to overwrite the local var using :as when render an object" do
56
+ c = new_controller
57
+ content = c.partial("partials/#{@engine}_collection_with_locals", :with => 1, :as => :number)
58
+ content.clean.should == '1'
59
+ end
60
+
61
+ it "should render a partial iterating over a collection with extra locals" do
62
+ c = new_controller
63
+ content = c.partial("partials/#{@engine}_collection_with_locals", :with => (1..10).to_a, :number => 'Locals!')
64
+ content.clean.should == (1..10).to_a.map { |i| "Locals!" }.join("\n")
65
+ end
66
+
67
+ it "should render a partial using the .format.engine convention" do
68
+ c = new_controller
69
+ content = c.partial "partials/#{@engine}_new"
70
+ content.clean.should == "No Locals!"
71
+ end
72
+
73
+ it "should render a template without a layout" do
74
+ c = new_controller
75
+ content = c.render_no_layout(:template => "#{@engine}")
76
+ content.clean.should == "Hello!"
77
+ end
78
+
79
+ it "should raise an exception without a template" do
80
+ c = new_controller(nil, Examples)
81
+ lambda {
82
+ c.render_no_layout(:template => nil)
83
+ }.should raise_error(Merb::ControllerExceptions::TemplateNotFound)
84
+ end
85
+
86
+ it "should find a snake case partial" do
87
+ c = new_controller(nil, Examples)
88
+ content = c.partial("#{@engine}")
89
+ content.clean.should == "Hello!"
90
+ end
91
+
92
+ it "should implement a _buffer method" do
93
+ c = new_controller
94
+ content = c.render :template => "template_views/interface__buffer_#{@engine}", :layout => :none
95
+ content.should match( /respond_to\?\(\s*\:_buffer\s*\)\s+\=\s+TRUE/ )
96
+ content.should match( /Text for the view buffer/ )
97
+ end
98
+
99
+ it "should implement a concat( text, binding ) method" do
100
+ c = new_controller
101
+ content = c.render :template => "template_views/interface_concat_#{@engine}", :layout => :none
102
+ content.should match( /Concat Text/ )
103
+ end
104
+
105
+ it "should bind the concat to a block" do
106
+ c = new_controller
107
+ content = c.render :template => "template_views/interface_concat_#{@engine}", :layout => :none
108
+ content.should match( /Start Tester Block\s*In Tester Block\s*Finish Tester Block/m)
109
+ end
110
+
111
+ it "should implement a capture( &block ) method" do
112
+ c = new_controller
113
+ content = c.render :template => "template_views/interface_capture_#{@engine}", :layout => :none
114
+ content.should match( /Capture Text Without Args/m)
115
+ end
116
+
117
+ it "should render #{@engine} partial using .format.engine convention#{" (caching on)" if defined?(cache) && cache}" do
118
+ c = new_controller
119
+ content = c.partial "partials/#{@engine}_new"
120
+ content.clean.should == "No Locals!"
121
+ end
122
+
123
+ # # These cannot be implemented at this stage with Markaby without instance_exec which will
124
+ # # not be available until Ruby 1.9
125
+ # it "should implement capture and yield arguments to the block for #{@engine}" do
126
+ # c = new_controller
127
+ # content = c.render :template => "template_views/interface_capture_#{@engine}", :layout => :none
128
+ # content.should match( /capture text from yielded object/im)
129
+ # end
130
+ #
131
+ # # This cannot be specced until Ruby 1.9 is available due to instance_exec
132
+ # # unless markaby can be made to accept arguments for this method.
133
+ # it "should capture content in a block for #{@engine}" do
134
+ # c = new_controller
135
+ # content = c.render :template => "template_views/interface_capture_#{@engine}", :layout => :none
136
+ # content.should match( /BEFORE\s*capture text from yielded object\s*AFTER/im)
137
+ # end
138
+ end
139
+
140
+ [true, false].each do |cache|
141
+ Merb::Server.config[:cache_templates] = cache
142
+
143
+ describe "Merb rendering in general#{" (caching enabled)" if cache}" do
144
+ it "should render inline with Erubis" do
145
+ c = new_controller
146
+ content = c.render :inline => "<%= 'Inline' %>", :layout => :none
147
+ content.clean.should == "Inline"
148
+ end
149
+
150
+ it "should render an XML string" do
151
+ c = new_controller(nil, Examples)
152
+ content = c.render :xml => "<hello>world</hello>"
153
+ content.clean.should == "<hello>world</hello>"
154
+ c.headers["Content-Type"].should == "application/xml"
155
+ c.headers["Encoding"].should == "UTF-8"
156
+ end
157
+
158
+ it "should render a javascript string" do
159
+ c = new_controller(nil, Examples)
160
+ content = c.render(:js => "alert('Hello, world!');")
161
+ content.clean.should == %{alert('Hello, world!');}
162
+ end
163
+
164
+ it "should raise an TemplateNotFound error if a template is called that does not exist" do
165
+ c = new_controller(nil, Examples)
166
+ lambda do
167
+ c.render(:template => "does_not_exist", :format => :html)
168
+ end.should raise_error(Merb::ControllerExceptions::TemplateNotFound)
169
+ end
170
+
171
+ it "should render a template from a directory with a . in it's path" do
172
+ c = new_controller(nil, Examples)
173
+ lambda do
174
+ c.render(:template => "test.dir/the_template", :format => :html)
175
+ end.should_not raise_error(Merb::ControllerExceptions::TemplateNotFound)
176
+ end
177
+
178
+ end
179
+
180
+ describe "Merb rendering with the Erubis engine#{" (caching enabled)" if cache}" do
181
+ before(:all) { @engine = "erubis" }
182
+ it_should_behave_like "rendering engines except XMLBuilder"
183
+
184
+ it "should render a nested controller's views" do
185
+ c = new_controller(nil, Nested::Example)
186
+ content = c.render(:action => "test")
187
+ content.clean.should == "Hello!"
188
+ end
189
+
190
+ it "should report the selected template in controller._template" do
191
+ c = new_controller
192
+ content = c.render(:template => "erubis")
193
+ c.template.should == "erubis.html.erb"
194
+ end
195
+
196
+ it "should raise LayoutNotFound if the layout is missing" do
197
+ c = new_controller
198
+ lambda {
199
+ c.render(:template => "erubis", :layout => "this_is_not_a_layout")
200
+ }.should raise_error(Merb::ControllerExceptions::LayoutNotFound)
201
+ end
202
+
203
+ it "should render the index action using index.html.erb" do
204
+ c = new_spec_controller
205
+ c.dispatch(:index)
206
+ c.template.should == "index.html.erb"
207
+ end
208
+
209
+ it "should render an erubis .html.erb template" do
210
+ c = new_spec_controller(:format => 'html')
211
+ c.dispatch(:erubis_templates)
212
+ c.template.should == "erubis_templates.html.erb"
213
+ end
214
+
215
+ it "should render an .html.erb template in front of a erubis_templates.rhtml" do
216
+ c = new_spec_controller(:format => 'html')
217
+ c.dispatch(:erubis_templates)
218
+ c.template.should == "erubis_templates.html.erb"
219
+ end
220
+
221
+ it "should render an erubis .js.erb template" do
222
+ c = new_spec_controller(:format => 'js')
223
+ c.dispatch(:erubis_templates)
224
+ c.template.should == "erubis_templates.js.erb"
225
+ end
226
+
227
+ it "should render an erubis .xml.erb template" do
228
+ c = new_spec_controller(:format => 'xml')
229
+ c.dispatch(:erubis_templates)
230
+ c.template.should == "erubis_templates.xml.erb"
231
+ end
232
+
233
+ it "should render js in nested partials when the format is javascript" do
234
+ c = new_spec_controller
235
+ c.dispatch(:render_nested_js)
236
+ c.body.should match(/nested_js_partial/m)
237
+ end
238
+
239
+ it "should render xml in nested partials when the format is xml" do
240
+ c = new_spec_controller
241
+ c.dispatch(:render_nested_xml)
242
+ c.body.should match(/nested_xml_partial/m)
243
+ end
244
+
245
+ it "should render multiple partials with locals" do
246
+ c = new_spec_controller(:controller => "ExtensionTemplateController")
247
+ c.dispatch(:render_multiple_partials)
248
+ (1..10).each do |i|
249
+ c.body.should match(/#{i}/)
250
+ end
251
+ end
252
+
253
+ end
254
+
255
+ describe "Merb rendering with the Markaby engine#{" (caching enabled)" if cache}" do
256
+ before(:all) { @engine = "markaby" }
257
+ it_should_behave_like "rendering engines except XMLBuilder"
258
+
259
+ it "should render markaby_index using markaby_index.html.mab" do
260
+ c = new_spec_controller
261
+ c.dispatch(:markaby_index)
262
+ c.template.should == "markaby_index.html.mab"
263
+ end
264
+
265
+ it "should render a markaby .html.mab template" do
266
+ c = new_spec_controller(:format => 'html')
267
+ c.dispatch(:markaby_templates)
268
+ c.template.should == "markaby_templates.html.mab"
269
+ end
270
+
271
+ it "should render a markaby .js.mab template" do
272
+ c = new_spec_controller(:format => 'js')
273
+ c.dispatch(:markaby_templates)
274
+ c.template.should == "markaby_templates.js.mab"
275
+ end
276
+
277
+ it "should render a markaby .xml.mab template" do
278
+ c = new_spec_controller(:format => 'xml')
279
+ c.dispatch(:markaby_templates)
280
+ c.template.should == "markaby_templates.xml.mab"
281
+ end
282
+ end
283
+
284
+ # XMLBuilder and Haml templates aren't supported under JRuby yet
285
+ unless RUBY_PLATFORM =~ /java/
286
+ describe "Merb rendering with the Haml engine#{" (caching enabled)" if cache}" do
287
+ before(:all) { @engine = "haml" }
288
+ it_should_behave_like "rendering engines except XMLBuilder"
289
+
290
+ it "should render haml_index using haml_index.html.haml" do
291
+ c = new_spec_controller
292
+ c.dispatch(:haml_index)
293
+ c.template.should == "haml_index.html.haml"
294
+ end
295
+
296
+ it "should render an haml .html.haml template" do
297
+ c = new_spec_controller(:format => 'html')
298
+ c.dispatch(:haml_templates)
299
+ c.template.should == "haml_templates.html.haml"
300
+ end
301
+
302
+ it "should render an haml .js.haml template" do
303
+ c = new_spec_controller(:format => 'js')
304
+ c.dispatch(:haml_templates)
305
+ c.template.should == "haml_templates.js.haml"
306
+ end
307
+
308
+ it "should render an haml .xml.haml template" do
309
+ c = new_spec_controller(:format => 'xml')
310
+ c.dispatch(:haml_templates)
311
+ c.template.should == "haml_templates.xml.haml"
312
+ end
313
+
314
+ end
315
+
316
+ describe "Merb rendering with the XMLBuilder engine#{" (caching enabled)" if cache}" do
317
+ before(:all) { @engine = "builder" }
318
+
319
+ it "should render an XML template from a symbol" do
320
+ c = new_controller(nil, Examples)
321
+ content = c.render :xml => :hello
322
+ content.clean.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hello>world</hello>"
323
+ c.headers["Content-Type"].should == "application/xml"
324
+ end
325
+
326
+ it "should render an XML template from an action" do
327
+ c = new_controller(nil, Examples)
328
+ content = c.render :xml => true, :action => "hello"
329
+ content.clean.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hello>world</hello>"
330
+ c.headers["Content-Type"].should == "application/xml"
331
+ end
332
+
333
+ end
334
+ end
335
+
336
+ end
337
+
338
+ describe "Merb rendering with an object calls to_json or to_xml on the object" do
339
+ it "render @foo should call @foo.to_json when json is requested" do
340
+ c = new_spec_controller(:format => 'json', :controller => 'RenderObjectController')
341
+ c.dispatch(:render_object)
342
+ c.body.should == "{'foo':'bar'}"
343
+ end
344
+
345
+ it "render @foo should call @foo.to_xml when json is requested" do
346
+ c = new_spec_controller(:format => 'xml', :controller => 'RenderObjectController')
347
+ c.dispatch(:render_object)
348
+ c.body.should == "<foo>bar</foo>"
349
+ end
350
+
351
+ it "should render the template for the action when called with an object and the template exists" do
352
+ c = new_spec_controller(:format => :html, :controller => 'RenderObjectController')
353
+ c.dispatch(:render_object_with_template)
354
+ c.body.should match(/object with template html format/)
355
+ end
356
+
357
+ it "should render the template for the action when called with an object and the template exists" do
358
+ c = new_spec_controller(:format => :xml, :controller => 'RenderObjectController')
359
+ c.dispatch(:render_object_with_template)
360
+ c.body.should match(/object with template xml format/)
361
+ end
362
+
363
+ it "should render the template for the action when called with an object and the template exists" do
364
+ c = new_spec_controller(:format => :js, :controller => 'RenderObjectController')
365
+ c.dispatch(:render_object_with_template)
366
+ c.body.should match(/object with template js format/)
367
+ end
368
+
369
+ end
370
+
371
+ def new_spec_controller(options={})
372
+ params = {:controller => 'ExtensionTemplateController'}
373
+ params.update(:format => options.delete(:format)) if options[:format]
374
+ params.update(:controller => options[:controller]) if options[:controller]
375
+ @request = Merb::Test::FakeRequest.new(options)
376
+ @request.params.merge!(params)
377
+ Object.const_get(params[:controller].to_sym).build(@request, @request.body)
378
+ end
@@ -0,0 +1,243 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Merb::Request do
4
+ include Mocha::SetupAndTeardown
5
+
6
+ class GoodPosts < Merb::Controller
7
+ def show() end
8
+ end
9
+
10
+ before(:each) do
11
+ setup_stubs
12
+ @in = Merb::Test::FakeRequest.new
13
+ Merb::Request.any_instance.stubs(:route_params).returns({})
14
+ end
15
+
16
+ after(:each) do
17
+ teardown_stubs
18
+ end
19
+
20
+ it "should parse POST body into params" do
21
+ @in.post_body = "title=hello%20there&body=some%20text&user[roles][]=admin&user[roles][]=superuser&commit=Submit"
22
+ @in['REQUEST_METHOD'] = 'POST'
23
+ @in['CONTENT_TYPE'] = "application/x-www-form-urlencoded"
24
+ request = Merb::Request.new(@in)
25
+ request.params[:title].should == "hello there"
26
+ request.params[:body].should == "some text"
27
+ request.params[:commit].should == "Submit"
28
+ request.params[:user][:roles].class.should == Array
29
+ request.params[:user][:roles][0].should == "admin"
30
+ request.params[:user][:roles][1].should == "superuser"
31
+ end
32
+
33
+ it "should parse POST body into params unless Content-Type header is set explicitly" do
34
+ input = "title=hello%20there&body=some%20text&commit=Submit"
35
+ @in.post_body = input
36
+ @in['REQUEST_METHOD'] = 'POST'
37
+ @in['CONTENT_TYPE'] = 'text/plain'
38
+ request = Merb::Request.new(@in)
39
+ request.params[:title].should be_nil
40
+ request.params[:body].should be_nil
41
+ request.params[:commit].should be_nil
42
+ request.raw_post.should == input
43
+ end
44
+
45
+ it "should parse PUT body into params" do
46
+ @in.post_body = "title=hello%20there&body=some%20text&commit=Submit"
47
+ @in['REQUEST_METHOD'] = 'PUT'
48
+ @in['CONTENT_TYPE'] = "application/x-www-form-urlencoded"
49
+ request = Merb::Request.new(@in)
50
+ request.params[:title].should == "hello there"
51
+ request.params[:body].should == "some text"
52
+ request.params[:commit].should == "Submit"
53
+ end
54
+
55
+ it "should parse PUT body into params unless Content-Type header is set explicitly" do
56
+ input = "title=hello%20there&body=some%20text&commit=Submit"
57
+ @in.post_body = input
58
+ @in['REQUEST_METHOD'] = 'PUT'
59
+ @in['CONTENT_TYPE'] = 'text/plain'
60
+ request = Merb::Request.new(@in)
61
+ request.params[:title].should be_nil
62
+ request.params[:body].should be_nil
63
+ request.params[:commit].should be_nil
64
+ request.raw_post.should == input
65
+ end
66
+
67
+ it "should parse Query String into params" do
68
+ @in['QUERY_STRING'] = "title=hello%20there&body=some%20text&commit=Submit"
69
+ request = Merb::Request.new(@in)
70
+ request.params[:title].should == "hello there"
71
+ request.params[:body].should == "some text"
72
+ request.params[:commit].should == "Submit"
73
+ end
74
+
75
+ it "shouldn't explode on key only query" do
76
+ @in['QUERY_STRING'] = "pop"
77
+ request = Merb::Request.new(@in)
78
+ request.params.has_key?(:pop).should be_true
79
+ end
80
+
81
+ it "shouldn't explode on value only query" do
82
+ @in['QUERY_STRING'] = "=bang"
83
+ request = Merb::Request.new(@in)
84
+ request.params.has_value?('bang').should be_true
85
+ end
86
+
87
+ it "should handle file upload for multipart/form-data posts" do
88
+ m = Merb::Test::Multipart::Post.new :file => File.open(FIXTURES / 'sample.txt')
89
+ body, head = m.to_multipart
90
+ @in['REQUEST_METHOD'] = 'POST'
91
+ @in['CONTENT_TYPE'] = head
92
+ @in['CONTENT_LENGTH'] = body.length
93
+ @in.post_body = body
94
+ request = Merb::Request.new(@in)
95
+ request.params[:file].should_not be_nil
96
+ request.params[:file][:tempfile].class.should == Tempfile
97
+ request.params[:file][:content_type].should == 'text/plain'
98
+ end
99
+
100
+ # it "multipart/form-data handles multiple form fields" do
101
+ # m = Merb::Test::Multipart::Post.new :foo => 'bario', 'files[]' => File.open(FIXTURES / 'sample.txt')
102
+ # m.push_params 'files[]' => File.open(FIXTURES / 'foo.rb')
103
+ # body, head = m.to_multipart
104
+ # @in['REQUEST_METHOD'] = 'POST'
105
+ # @in['CONTENT_TYPE'] = head
106
+ # @in['CONTENT_LENGTH'] = body.length
107
+ # @in.post_body = body
108
+ # request = Merb::Request.new(@in)
109
+ # params[:foo].should == 'bario'
110
+ # params[:files].should_not be_nil
111
+ # params[:files].should be_kind_of(Array)
112
+ # params[:files].first[:tempfile].class.should == Tempfile
113
+ # end
114
+
115
+ it "Json Post Body is parsed into params" do
116
+ @in.post_body = "{\"title\":\"hello there\",\"body\":\"some text\"}"
117
+ @in['REQUEST_METHOD'] = 'POST'
118
+ @in['CONTENT_TYPE'] = "text/x-json"
119
+ request = Merb::Request.new(@in)
120
+ request.params[:title].should == "hello there"
121
+ request.params[:body].should == "some text"
122
+ end
123
+
124
+ it "Json Post Body is not parsed into params if Merb::Request::parse_json_params = false" do
125
+ Merb::Request::parse_json_params = false
126
+ @in.post_body = "{\"title\":\"hello there\",\"body\":\"some text\"}"
127
+ @in['REQUEST_METHOD'] = 'POST'
128
+ @in['CONTENT_TYPE'] = "text/x-json"
129
+ request = Merb::Request.new(@in)
130
+ request.params[:title].should be_nil
131
+ request.params[:body].should be_nil
132
+ Merb::Request::parse_json_params = true
133
+ end
134
+
135
+ it "should handle hash-style form fields in multipart/form-data" do
136
+ m = Merb::Test::Multipart::Post.new :foo => 'bario',
137
+ 'files[foo][file]' => File.open(FIXTURES / 'foo.rb'),
138
+ 'files[foo][name]' => "Foo",
139
+ 'files[bar][file]' => File.open(FIXTURES / 'foo.rb'),
140
+ 'files[bar][name]' => "Bar",
141
+ 'deep[files][foobar][]' => File.open(FIXTURES / 'foo.rb'),
142
+ 'regular_fields[user][name]' => "John Doe",
143
+ 'regular_fields[user][email]' => "jdoe@example.com"
144
+ body, head = m.to_multipart
145
+ @in['REQUEST_METHOD'] = 'POST'
146
+ @in['CONTENT_TYPE'] = head
147
+ @in['CONTENT_LENGTH'] = body.length
148
+ @in.post_body = body
149
+ request = Merb::Request.new(@in)
150
+
151
+ request.params.should_not include(:"files[foo]")
152
+ request.params.should_not include(:"files[bar]")
153
+ request.params.should_not include(:"regular_fields[user]")
154
+ request.params.should_not include(:"deep[files]")
155
+
156
+ request.params[:files][:foo][:name].should == "Foo"
157
+ request.params[:files][:foo][:file].should include(:filename)
158
+ request.params[:files][:foo][:file][:tempfile].class.should == Tempfile
159
+ request.params[:files][:bar][:name].should == "Bar"
160
+ request.params[:files][:bar][:file].should include(:filename)
161
+ request.params[:files][:bar][:file][:tempfile].class.should == Tempfile
162
+
163
+ request.params[:deep][:files][:foobar].class.should == Array
164
+ request.params[:deep][:files][:foobar].size.should == 1
165
+
166
+ request.params[:regular_fields][:user][:name].should == "John Doe"
167
+ end
168
+
169
+ it "should understand PUT if passed as _method in query string for RESTful form dispatch" do
170
+ @in.post_body = "title=hello"
171
+ @in['QUERY_STRING'] = '_method=put'
172
+ @in['REQUEST_METHOD'] = 'POST'
173
+ @in['CONTENT_TYPE'] = "application/x-www-form-urlencoded"
174
+ request = Merb::Request.new(@in)
175
+ request.method.should == :put
176
+ request.params[:title].should == "hello"
177
+ end
178
+
179
+ it "should understand DELETE if passed as _method in query string for RESTful form dispatch" do
180
+ @in.post_body = "title=hello"
181
+ @in['QUERY_STRING'] = '_method=delete'
182
+ @in['REQUEST_METHOD'] = 'POST'
183
+ @in['CONTENT_TYPE'] = "application/x-www-form-urlencoded"
184
+ request = Merb::Request.new(@in)
185
+ request.method.should == :delete
186
+ request.params[:title].should == "hello"
187
+ end
188
+
189
+ it "should understand PUT if passed as _method in request body for RESTful form dispatch" do
190
+ @in.post_body = "_method=put&title=hello"
191
+ @in['REQUEST_METHOD'] = 'POST'
192
+ @in['CONTENT_TYPE'] = "application/x-www-form-urlencoded"
193
+ request = Merb::Request.new(@in)
194
+ request.method.should == :put
195
+ request.params[:title].should == "hello"
196
+ end
197
+
198
+ it "should understand DELETE if passed as _method in request body for RESTful form dispatch" do
199
+ @in.post_body = "_method=delete&title=hello"
200
+ @in['REQUEST_METHOD'] = 'POST'
201
+ @in['CONTENT_TYPE'] = "application/x-www-form-urlencoded"
202
+ request = Merb::Request.new(@in)
203
+ request.env['REQUEST_METHOD'].should == 'POST'
204
+ request.method.should == :delete
205
+ request.params[:title].should == "hello"
206
+ end
207
+
208
+ it "should not raise a NotFound exception when the controller class exists" do
209
+ @in['REQUEST_URI'] = "/good_posts/show/1"
210
+ @in['REQUEST_METHOD'] = 'GET'
211
+ @in['CONTENT_TYPE'] = "application/x-www-form-urlencoded"
212
+ request = Merb::Request.new(@in)
213
+ request.stubs(:controller_name).returns("good_posts")
214
+ lambda { request.controller_class }.should_not raise_error(Merb::ControllerExceptions::NotFound)
215
+ end
216
+
217
+ it "should raise a NotFound exception when the controller does not exist" do
218
+ @in['REQUEST_URI'] = "/bad_posts/show/1"
219
+ @in['REQUEST_METHOD'] = 'GET'
220
+ @in['CONTENT_TYPE'] = "application/x-www-form-urlencoded"
221
+ request = Merb::Request.new(@in)
222
+ request.stubs(:controller_name).returns("bad_posts")
223
+ lambda { request.controller_class }.should raise_error(Merb::ControllerExceptions::NotFound)
224
+ end
225
+
226
+ it "should set accept to '*/*' when HTTP_ACCEPT is blank" do
227
+ @in['HTTP_ACCEPT'] = ""
228
+ request = Merb::Request.new(@in)
229
+ request.accept.should == "*/*"
230
+ end
231
+
232
+ it "should set accept to '*/*' when HTTP_ACCEPT is empty" do
233
+ @in['HTTP_ACCEPT'] = nil
234
+ request = Merb::Request.new(@in)
235
+ request.accept.should == "*/*"
236
+ end
237
+
238
+ it "should set accept to '*/*' when HTTP_ACCEPT is not set" do
239
+ @in.env.delete('HTTP_ACCEPT')
240
+ request = Merb::Request.new(@in)
241
+ request.accept.should == "*/*"
242
+ end
243
+ end