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,431 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require 'strscan' #StringScanner
3
+
4
+ class ArticlePost; end
5
+
6
+ module FormControlsSpecHelper
7
+ def setup_model_mock
8
+ # NOTE Uses OpenStruct so we can see meaningful
9
+ # class name to dom_id conversions.
10
+ @model = OpenStruct.new({
11
+ :title => "Chunky Bacon",
12
+ :intro => "It's the tastiest kind.",
13
+ :created_at => DateTime.parse("1963-11-22 12:30:00"),
14
+ :published_at => Time.now,
15
+ :version => 42,
16
+ :secret => 'should not be shown'
17
+ })
18
+ end
19
+ end
20
+
21
+ describe Merb::FormControls, "All Form Fields", :shared => true do
22
+
23
+ before do
24
+ @opts ||= {}
25
+ end
26
+
27
+ it "should render css class if specified" do
28
+ content = control_for( @model, :title, @control_type, :class => "TEST_CLASS" )
29
+ content.should match( /class="TEST_CLASS"/)
30
+ end
31
+
32
+ it "should render default DOM id" do
33
+ content = control_for(@model, :title, @control_type)
34
+ content.should match(/id="open_struct_title"/)
35
+ end
36
+
37
+ it "should override default DOM id if passed as argument" do
38
+ content = control_for(@model, :title, @control_type, :id => "porky")
39
+ content.should match(/id="porky"/)
40
+ end
41
+
42
+ it "should override default DOM name if passed as argument" do
43
+ content = control_for( @model, :title, @control_type, :name => "OVERRIDE")
44
+ content.should match( /name="OVERRIDE"/ )
45
+ end
46
+
47
+ it "should render a label" do
48
+ unless ( @opts[:skip_label] == true )
49
+ content = control_for( @model, :title, @control_type, :label => "LABEL" )
50
+ content.should match( /<label for="open_struct_title">LABEL<\/label>/)
51
+ end
52
+ end
53
+
54
+ it "should close the tag" do
55
+ content = control_for( @model, @control_type, :password )
56
+ content.clean.should match( /\/>\Z/ )
57
+ end
58
+
59
+
60
+
61
+ end
62
+
63
+
64
+ describe Merb::FormControls, "text input" do
65
+ include FormControlsSpecHelper
66
+
67
+ it_should_behave_like "Merb::FormControls All Form Fields"
68
+
69
+ before do
70
+ setup_model_mock
71
+ @control_type = :text
72
+ end
73
+
74
+ it "should render text input" do
75
+ content = control_for(@model, :title, :text)
76
+ content.should match(/type="text"/)
77
+ content.should match(/value="Chunky Bacon"/)
78
+ content.should match(/name="open_struct\[title\]"/)
79
+ end
80
+
81
+ end
82
+
83
+
84
+ describe Merb::FormControls, "textarea" do
85
+ include FormControlsSpecHelper
86
+
87
+ it_should_behave_like "Merb::FormControls All Form Fields"
88
+
89
+ before do
90
+ setup_model_mock
91
+ @control_type = :textarea
92
+ end
93
+
94
+ it "should render textarea" do
95
+ content = control_for(@model, :intro, :textarea)
96
+ content.should match(/textarea/)
97
+ content.should match(/>It's the tastiest kind.</)
98
+ end
99
+
100
+ end
101
+
102
+ describe Merb::FormControls, "number" do
103
+ include FormControlsSpecHelper
104
+
105
+ it_should_behave_like "Merb::FormControls All Form Fields"
106
+
107
+ before do
108
+ setup_model_mock
109
+ @control_type = :number
110
+ end
111
+
112
+ it "should render number" do
113
+ content = control_for(@model, :version, :number)
114
+ content.should match(/value="42"/)
115
+ content.should match(/type="text"/)
116
+ end
117
+
118
+ end
119
+
120
+
121
+ describe Merb::FormControls, "hidden" do
122
+ include FormControlsSpecHelper
123
+
124
+ it_should_behave_like "Merb::FormControls All Form Fields"
125
+
126
+ before do
127
+ setup_model_mock
128
+ @control_type = :hidden
129
+ @opts = { :skip_label => true }
130
+ end
131
+
132
+ it "should render hidden field" do
133
+ content = control_for(@model, :title, :hidden)
134
+ content.should match(/value="Chunky Bacon"/)
135
+ content.should match(/type="hidden"/)
136
+ end
137
+ end
138
+
139
+
140
+ describe Merb::FormControls, "password" do
141
+ include FormControlsSpecHelper
142
+
143
+ it_should_behave_like "Merb::FormControls All Form Fields"
144
+
145
+ before do
146
+ setup_model_mock
147
+ @control_type = :password
148
+ end
149
+
150
+ it "should render password field" do
151
+ content = control_for( @model, :title, :password )
152
+ content.should match( /<input/ )
153
+ content.should match( /type="password"/ )
154
+ end
155
+
156
+ it "should not put any value into the field even if it is in the hash" do
157
+ content = control_for( @model, :title, :password, :value => "OVERRIDE")
158
+ content.should_not match( /value="OVERRIDE"/ )
159
+ end
160
+
161
+ end
162
+
163
+
164
+ describe Merb::FormControls, "select" do
165
+ include FormControlsSpecHelper
166
+
167
+ it_should_behave_like "Merb::FormControls All Form Fields"
168
+
169
+ before do
170
+ setup_model_mock
171
+ @control_type = :select
172
+ end
173
+
174
+ it "should render the select tag with the correct id and name" do
175
+ content = control_for( @model, :version, :select )
176
+ content.should match( /<select/ )
177
+ content.should match( /id="open_struct_version"/ )
178
+ content.should match( /name="open_struct\[version\]"/ )
179
+ content.should match( /<\/select>/)
180
+ end
181
+
182
+ it "should include a blank option" do
183
+ content = control_for( @model, :version, :select, :include_blank => true )
184
+ content.should match( /<option><\/option>/ )
185
+ end
186
+
187
+ it "should render a select tag with options" do
188
+ content = control_for( @model, :version, :select, :class => 'class1 class2', :title => 'This is the title' )
189
+ content.should match( /class=\"class1 class2\"/)
190
+ content.should match( /title=\"This is the title\"/ )
191
+ end
192
+
193
+ it "should render a select tag with options and a blank option" do
194
+ content = control_for( @model, :version, :select, :title => "TITLE", :include_blank => true )
195
+ content.should match( /title=\"TITLE\"/ )
196
+ content.should match( /<option><\/option>/ )
197
+ end
198
+
199
+ it "should render the text as the value if no text_method is specified" do
200
+ content = control_for( @model, :version, :select, :collection => [@model] )
201
+ content.should match( /<option.*>42<\/option>/ )
202
+ end
203
+
204
+ it "should render a collection as option tags" do
205
+ @model2 = OpenStruct.new({
206
+ :version => 45
207
+ })
208
+ content = control_for( @model, :version, :select, :collection => [@model, @model2] )
209
+ doc = Hpricot( content )
210
+ (doc/"option").size.should == 2
211
+ (doc/"option").should_not be_empty
212
+ content.should match( /<option value="45">45<\/option>/ )
213
+ end
214
+
215
+ it "should select the object in the collection" do
216
+ @model2 = @model2 = OpenStruct.new({
217
+ :version => 45
218
+ })
219
+ content = control_for( @model, :version, :select, :collection => [@model, @model2] )
220
+ content.should match( /<option selected="selected" value="42">42<\/option>/ )
221
+ end
222
+
223
+ it "should render a collection with a text method specified" do
224
+ @model2 = OpenStruct.new({ :version => 45, :title => "TITLE" })
225
+ content = control_for( @model, :version, :select, :collection => [@model, @model2], :text_method => :title )
226
+ content.should match( /<option.*value="42".*>Chunky Bacon<\/option>.*<option.*value="45".*>TITLE<\/option/ )
227
+ end
228
+
229
+ it "should render a hash of arrays as a grouped select box" do
230
+ @model1 = OpenStruct.new({ :make => "Ford", :model => "Mustang", :code => 1 } )
231
+ @model2 = OpenStruct.new({ :make => "Ford", :model => "Falcon", :code => 2 } )
232
+ @model3 = OpenStruct.new({ :make => "Holden", :model => "Comodore", :code => 3 } )
233
+
234
+ collection = [ @model1, @model2, @model3].group_by( &:make )
235
+
236
+ content = control_for( @model1, :code, :select, :collection => collection, :text_method => :model )
237
+ content.should match( /<optgroup label="Ford">/ )
238
+ content.should match( /<option selected="selected" value="1">Mustang<\/option>/ )
239
+ content.should match( /<option value="2">Falcon<\/option>/ )
240
+ content.should match( /<optgroup label="Holden">/ )
241
+ content.should match( /<option value="3">Comodore<\/option>/ )
242
+ content.should match( /<\/optgroup>/)
243
+ end
244
+
245
+ it "should humanize and titlize keys in the label for the option group" do
246
+ collection = { :some_snake_case_key => [@model] }
247
+ content = control_for( @model, :version, :select, :collection => collection )
248
+ content.should match( /<optgroup label="Some Snake Case Key">/ )
249
+ end
250
+
251
+ end
252
+
253
+ describe Merb::FormControls, "time and date" do
254
+ include FormControlsSpecHelper
255
+
256
+ before(:each) do
257
+ setup_model_mock
258
+ end
259
+
260
+ it "should render time" do
261
+ content = control_for(@model, :created_at, :time)
262
+ content.should match(/<select .*\[created_at\]\[day\]/)
263
+ content.should match(/<select .*\[created_at\]\[month\]/)
264
+ content.should match(/<select .*\[created_at\]\[year\]/)
265
+ content.should match(/<select .*\[created_at\]\[hour\]/)
266
+ content.should match(/<select .*\[created_at\]\[minute\]/)
267
+ content.should match(/<select .*\[created_at\]\[second\]/)
268
+ end
269
+
270
+ it "should render date" do
271
+ content = control_for(@model, :created_at, :date)
272
+ content.should match(/<select .*\[created_at\]\[day\]/)
273
+ content.should match(/<select .*\[created_at\]\[month\]/)
274
+ content.should match(/<select .*\[created_at\]\[year\]/)
275
+ content.should_not match(/<select .*\[created_at\]\[hour\]/)
276
+ content.should_not match(/<select .*\[created_at\]\[minute\]/)
277
+ content.should_not match(/<select .*\[created_at\]\[second\]/)
278
+ end
279
+
280
+ it "should select objects time" do
281
+ content = control_for(@model, :created_at, :time)
282
+ s = StringScanner.new(content)
283
+ part = s.scan_until(/<\/select>/)
284
+ part.should match(/day/)
285
+ part.should match(/selected="selected" value="#{@model.created_at.day}"/)
286
+ part = s.scan_until(/<\/select>/)
287
+ part.should match(/month/)
288
+ part.should match(/selected="selected" value="#{@model.created_at.month}"/)
289
+ part = s.scan_until(/<\/select>/)
290
+ part.should match(/year/)
291
+ part.should match(/selected="selected" value="#{@model.created_at.year}"/)
292
+ part = s.scan_until(/<\/select>/)
293
+ part.should match(/hour/)
294
+ part.should match(/selected="selected" value="#{@model.created_at.hour}"/)
295
+ part = s.scan_until(/<\/select>/)
296
+ part.should match(/minute/)
297
+ part.should match(/selected="selected" value="#{@model.created_at.min}"/)
298
+ part = s.scan_until(/<\/select>/)
299
+ part.should match(/second/)
300
+ part.should match(/selected="selected" value="#{@model.created_at.sec}"/)
301
+ end
302
+
303
+ it "should default to 1950..2050" do
304
+ content = control_for(@model, :created_at, :date)
305
+ s = StringScanner.new(content)
306
+ s.skip_until /<select .*\[created_at\]\[year\]/
307
+ part = s.scan_until(/<\/select>/)
308
+ part.should_not match(/>1949<\/option>/)
309
+ part.should match(/>1950<\/option>/)
310
+ part.should match(/>2050<\/option>/)
311
+ part.should_not match(/>2051<\/option>/)
312
+ end
313
+
314
+ it "should accept min_year" do
315
+ content = control_for(@model, :created_at, :date, :min_year => 1980)
316
+ s = StringScanner.new(content)
317
+ s.skip_until /<select .*\[created_at\]\[year\]/
318
+ part = s.scan_until(/<\/select>/)
319
+ part.should_not match(/>1979<\/option>/)
320
+ part.should match(/>1980<\/option>/)
321
+ part.should match(/>2050<\/option>/)
322
+ part.should_not match(/>2051<\/option>/)
323
+ end
324
+
325
+ it "should accept max_year" do
326
+ content = control_for(@model, :created_at, :date, :max_year => 2010)
327
+ s = StringScanner.new(content)
328
+ s.skip_until /<select .*\[created_at\]\[year\]/
329
+ part = s.scan_until(/<\/select>/)
330
+ part.should_not match(/>1949<\/option>/)
331
+ part.should match(/>1950<\/option>/)
332
+ part.should match(/>2010<\/option>/)
333
+ part.should_not match(/>2011<\/option>/)
334
+ end
335
+
336
+ it "should accept min_year and max_year" do
337
+ content = control_for(@model, :created_at, :date, :min_year => 1980, :max_year => 2010)
338
+ s = StringScanner.new(content)
339
+ s.skip_until /<select .*\[created_at\]\[year\]/
340
+ part = s.scan_until(/<\/select>/)
341
+ part.should_not match(/>1979<\/option>/)
342
+ part.should match(/>1980<\/option>/)
343
+ part.should match(/>2010<\/option>/)
344
+ part.should_not match(/>2011<\/option>/)
345
+ end
346
+
347
+ it "should render a label for date" do
348
+ content = control_for( @model, :created_at, :date, :label => "LABEL" )
349
+ content.should match( /<label for="open_struct_created_at">LABEL<\/label>/)
350
+ end
351
+
352
+ it "should render a label for time" do
353
+ content = control_for( @model, :created_at, :time, :label => "LABEL" )
354
+ content.should match( /<label for="open_struct_created_at">LABEL<\/label>/)
355
+ end
356
+ end
357
+
358
+
359
+ describe Merb::FormControls, "Missing time and day" do
360
+
361
+ before do
362
+ @post = OpenStruct.new(
363
+ :stringdate => "",
364
+ :stringtime => "",
365
+ :nildate => nil,
366
+ :niltime => nil
367
+ )
368
+ end
369
+
370
+ it "should handle date as string" do
371
+ control_for(@post, :stringdate, :date)
372
+ end
373
+
374
+ it "should handle time as string" do
375
+ control_for(@post, :stringtime, :time)
376
+ end
377
+
378
+ it "should handle date as nil" do
379
+ control_for(@post, :nildate, :date)
380
+ end
381
+
382
+ it "should handle time as nil" do
383
+ control_for(@post, :niltime, :time)
384
+ end
385
+ end
386
+
387
+
388
+ describe Merb::FormControls, "monthnames" do
389
+ include FormControlsSpecHelper
390
+
391
+ before do
392
+ setup_model_mock
393
+ end
394
+
395
+ it "should include default monthnames" do
396
+ content = control_for(@model, :created_at, :date, :monthnames => true)
397
+ s = StringScanner.new(content)
398
+ s.skip_until /<select .*\[created_at\]\[month\]/
399
+ part = s.scan_until(/<\/select>/)
400
+ (1..12).each do |m|
401
+ if m == @model.created_at.month
402
+ part.should match(/selected="selected" value="#{m}"\>#{Date::MONTHNAMES[m]}/)
403
+ else
404
+ part.should match(/value="#{m}"\>#{Date::MONTHNAMES[m]}/)
405
+ end
406
+ end
407
+ part.should_not match(/value="0"/)
408
+ part.should_not match(/value="13"/)
409
+ end
410
+
411
+ it "should include custom monthnames" do
412
+ french_months = [nil] + %w(janvier février mars avril mai juin
413
+ juillet août septembre octobre novembre décembre)
414
+ content = control_for(@model, :created_at, :date, :monthnames => french_months)
415
+ s = StringScanner.new(content)
416
+ s.skip_until /<select .*\[created_at\]\[month\]/
417
+ part = s.scan_until(/<\/select>/)
418
+ (1..12).each do |m|
419
+ if m == @model.created_at.month
420
+ part.should match(/selected="selected" value="#{m}"\>#{french_months[m]}/)
421
+ else
422
+ part.should match(/value="#{m}"\>#{french_months[m]}/)
423
+ end
424
+ end
425
+ part.should_not match(/value="0"/)
426
+ part.should_not match(/value="13"/)
427
+ end
428
+ end
429
+
430
+
431
+
@@ -0,0 +1,121 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require File.dirname(__FILE__) + '/../spec_generator_helper'
3
+
4
+ module Kernel
5
+ undef dependency
6
+ end
7
+
8
+ describe "an app generator" do
9
+ include RubiGen::GeneratorTestHelper
10
+
11
+ before do
12
+ @generator = build_generator('merb', [APP_ROOT], sources, {})
13
+ end
14
+
15
+ after do
16
+ bare_teardown # Cleans up the temporary application directory that gets created as part of the test.
17
+ end
18
+
19
+ it "should be get created" do
20
+ @generator.should_not be_nil
21
+ end
22
+
23
+ it "should be a MerbGenerator" do
24
+ @generator.should be_an_instance_of(MerbGenerator)
25
+ end
26
+
27
+ it "should create directory structure" do
28
+ @generator.command(:create).invoke!
29
+ %w{
30
+ app
31
+ app/controllers
32
+ app/helpers
33
+ app/mailers
34
+ app/mailers/helpers
35
+ app/mailers/views/layout
36
+ app/mailers/views
37
+ app/models
38
+ app/views
39
+ app/views/layout
40
+ config
41
+ config/environments
42
+ lib
43
+ log
44
+ public
45
+ public/images
46
+ public/javascripts
47
+ public/stylesheets
48
+ script
49
+ test
50
+ }.each{|dir| directory_should_be_created(dir)}
51
+ end
52
+
53
+ it "should create files from templates" do
54
+ @generator.command(:create).invoke!
55
+ %w{
56
+ app/controllers/application.rb
57
+ app/helpers/global_helper.rb
58
+ app/mailers/views/layout/application.html.erb
59
+ app/views/layout/application.html.erb
60
+ config/environments/development.rb
61
+ config/environments/production.rb
62
+ config/environments/test.rb
63
+ config/merb.yml
64
+ config/merb_init.rb
65
+ config/router.rb
66
+ config/dependencies.rb
67
+ config/upload.conf
68
+ Rakefile
69
+ script/stop_merb
70
+ script/generate
71
+ script/destroy
72
+ }.each{|file| file_should_be_created(file)}
73
+ end
74
+
75
+ it "should create files from rubigen dependency" do
76
+ @generator.command(:create).invoke!
77
+ %w{
78
+ script/generate
79
+ script/destroy
80
+ }.each{|file| file_should_be_created(file)}
81
+ end
82
+
83
+ it "should make script files executable" do
84
+ @generator.command(:create).invoke!
85
+
86
+ %w{
87
+ script/stop_merb
88
+ script/generate
89
+ script/destroy
90
+ }.each{|file| file_should_be_executable(file)}
91
+ end
92
+
93
+
94
+
95
+
96
+
97
+ def directory_should_be_created(directory)
98
+ File.should be_exist(File.join(APP_ROOT, directory))
99
+ File.should be_directory(File.join(APP_ROOT, directory))
100
+ end
101
+
102
+ def file_should_be_created(file)
103
+ File.should be_exist(File.join(APP_ROOT, file))
104
+ File.should be_file(File.join(APP_ROOT, file))
105
+ end
106
+
107
+ def file_should_be_executable(file)
108
+ File.should be_executable(File.join(APP_ROOT, file))
109
+ end
110
+
111
+
112
+ def sources
113
+ [RubiGen::PathSource.new(:test, File.join(File.dirname(__FILE__),"../../", generator_path))
114
+ ]
115
+ end
116
+
117
+ def generator_path
118
+ "app_generators"
119
+ end
120
+
121
+ end