ShadowBelmolve-formtastic 0.2.1 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/README.textile +191 -176
  2. data/Rakefile +65 -22
  3. data/generators/form/USAGE +16 -0
  4. data/generators/form/form_generator.rb +120 -0
  5. data/generators/form/templates/view__form.html.erb +5 -0
  6. data/generators/form/templates/view__form.html.haml +4 -0
  7. data/generators/formtastic/formtastic_generator.rb +24 -0
  8. data/generators/{formtastic_stylesheets → formtastic}/templates/formtastic.css +2 -0
  9. data/generators/formtastic/templates/formtastic.rb +51 -0
  10. data/generators/{formtastic_stylesheets → formtastic}/templates/formtastic_changes.css +0 -0
  11. data/generators/formtastic_stylesheets/formtastic_stylesheets_generator.rb +5 -10
  12. data/lib/formtastic.rb +1234 -895
  13. data/lib/formtastic/i18n.rb +32 -0
  14. data/lib/locale/en.yml +2 -2
  15. data/rails/init.rb +1 -1
  16. data/spec/buttons_spec.rb +149 -0
  17. data/spec/commit_button_spec.rb +344 -0
  18. data/spec/custom_builder_spec.rb +62 -0
  19. data/spec/custom_macros.rb +561 -0
  20. data/spec/defaults_spec.rb +20 -0
  21. data/spec/error_proc_spec.rb +27 -0
  22. data/spec/errors_spec.rb +85 -0
  23. data/spec/form_helper_spec.rb +120 -0
  24. data/spec/i18n_spec.rb +131 -0
  25. data/spec/include_blank_spec.rb +70 -0
  26. data/spec/input_spec.rb +608 -0
  27. data/spec/inputs/boolean_input_spec.rb +93 -0
  28. data/spec/inputs/check_boxes_input_spec.rb +162 -0
  29. data/spec/inputs/country_input_spec.rb +80 -0
  30. data/spec/inputs/date_input_spec.rb +45 -0
  31. data/spec/inputs/datetime_input_spec.rb +155 -0
  32. data/spec/inputs/file_input_spec.rb +33 -0
  33. data/spec/inputs/hidden_input_spec.rb +52 -0
  34. data/spec/inputs/numeric_input_spec.rb +44 -0
  35. data/spec/inputs/password_input_spec.rb +46 -0
  36. data/spec/inputs/radio_input_spec.rb +149 -0
  37. data/spec/inputs/select_input_spec.rb +459 -0
  38. data/spec/inputs/string_input_spec.rb +47 -0
  39. data/spec/inputs/text_input_spec.rb +33 -0
  40. data/spec/inputs/time_input_spec.rb +44 -0
  41. data/spec/inputs/time_zone_input_spec.rb +102 -0
  42. data/spec/inputs_spec.rb +395 -0
  43. data/spec/label_spec.rb +48 -0
  44. data/spec/nested_forms_spec.rb +50 -0
  45. data/spec/semantic_fields_for_spec.rb +44 -0
  46. data/spec/spec.opts +2 -0
  47. data/spec/spec_helper.rb +212 -0
  48. metadata +121 -16
  49. data/lib/justin_french/formtastic.rb +0 -10
  50. data/spec/formtastic_spec.rb +0 -3072
  51. data/spec/test_helper.rb +0 -14
@@ -0,0 +1,62 @@
1
+ # coding: utf-8
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+
4
+ describe 'Formtastic::SemanticFormHelper.builder' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ class MyCustomFormBuilder < ::Formtastic::SemanticFormBuilder
9
+ def awesome_input(method, options)
10
+ self.text_field(method)
11
+ end
12
+ end
13
+
14
+ before do
15
+ @output_buffer = ''
16
+ mock_everything
17
+ end
18
+
19
+ it 'is the Formtastic::SemanticFormBuilder by default' do
20
+ ::Formtastic::SemanticFormHelper.builder.should == ::Formtastic::SemanticFormBuilder
21
+ end
22
+
23
+ it 'can be configured to use your own custom form builder' do
24
+ # Set it to a custom builder class
25
+ ::Formtastic::SemanticFormHelper.builder = MyCustomFormBuilder
26
+ ::Formtastic::SemanticFormHelper.builder.should == MyCustomFormBuilder
27
+
28
+ # Reset it to the default
29
+ ::Formtastic::SemanticFormHelper.builder = ::Formtastic::SemanticFormBuilder
30
+ ::Formtastic::SemanticFormHelper.builder.should == ::Formtastic::SemanticFormBuilder
31
+ end
32
+
33
+ describe "when using a custom builder" do
34
+
35
+ before do
36
+ @new_post.stub!(:title)
37
+ ::Formtastic::SemanticFormHelper.builder = MyCustomFormBuilder
38
+ end
39
+
40
+ after do
41
+ ::Formtastic::SemanticFormHelper.builder = ::Formtastic::SemanticFormBuilder
42
+ end
43
+
44
+ describe "semantic_form_for" do
45
+
46
+ it "should yeild and instance of the custom builder" do
47
+ semantic_form_for(@new_post) do |builder|
48
+ builder.class.should == MyCustomFormBuilder
49
+ end
50
+ end
51
+
52
+ it "should allow me to call my custom input" do
53
+ semantic_form_for(@new_post) do |builder|
54
+ concat(builder.input(:title, :as => :awesome))
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+
62
+ end
@@ -0,0 +1,561 @@
1
+ module CustomMacros
2
+
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ def it_should_have_input_wrapper_with_class(class_name)
10
+ it "should have input wrapper with class '#{class_name}'" do
11
+ output_buffer.should have_tag("form li.#{class_name}")
12
+ end
13
+ end
14
+
15
+ def it_should_have_input_wrapper_with_id(id_string)
16
+ it "should have input wrapper with id '#{id_string}'" do
17
+ output_buffer.should have_tag("form li##{id_string}")
18
+ end
19
+ end
20
+
21
+ def it_should_not_have_a_label
22
+ it "should not have a label" do
23
+ output_buffer.should_not have_tag("form li label")
24
+ end
25
+ end
26
+
27
+ def it_should_have_a_nested_fieldset
28
+ it "should have a nested_fieldset" do
29
+ output_buffer.should have_tag("form li fieldset")
30
+ end
31
+ end
32
+
33
+ def it_should_have_label_with_text(string_or_regex)
34
+ it "should have a label with text '#{string_or_regex}'" do
35
+ output_buffer.should have_tag("form li label", string_or_regex)
36
+ end
37
+ end
38
+
39
+ def it_should_have_label_for(element_id)
40
+ it "should have a label for ##{element_id}" do
41
+ output_buffer.should have_tag("form li label[@for='#{element_id}']")
42
+ end
43
+ end
44
+
45
+ def it_should_have_input_with_id(element_id)
46
+ it "should have an input with id '#{element_id}'" do
47
+ output_buffer.should have_tag("form li input##{element_id}")
48
+ end
49
+ end
50
+
51
+ def it_should_have_input_with_type(input_type)
52
+ it "should have a #{input_type} input" do
53
+ output_buffer.should have_tag("form li input[@type=\"#{input_type}\"]")
54
+ end
55
+ end
56
+
57
+ def it_should_have_input_with_name(name)
58
+ it "should have an input named #{name}" do
59
+ output_buffer.should have_tag("form li input[@name=\"#{name}\"]")
60
+ end
61
+ end
62
+
63
+ def it_should_have_textarea_with_name(name)
64
+ it "should have an input named #{name}" do
65
+ output_buffer.should have_tag("form li textarea[@name=\"#{name}\"]")
66
+ end
67
+ end
68
+
69
+ def it_should_have_textarea_with_id(element_id)
70
+ it "should have an input with id '#{element_id}'" do
71
+ output_buffer.should have_tag("form li textarea##{element_id}")
72
+ end
73
+ end
74
+
75
+ def it_should_use_default_text_field_size_when_method_has_no_database_column(as)
76
+ it 'should use default_text_field_size when method has no database column' do
77
+ @new_post.stub!(:column_for_attribute).and_return(nil) # Return a nil column
78
+
79
+ semantic_form_for(@new_post) do |builder|
80
+ concat(builder.input(:title, :as => as))
81
+ end
82
+ output_buffer.should have_tag("form li input[@size='#{Formtastic::SemanticFormBuilder.default_text_field_size}']")
83
+ end
84
+ end
85
+
86
+ def it_should_apply_custom_input_attributes_when_input_html_provided(as)
87
+ it 'it should apply custom input attributes when input_html provided' do
88
+ semantic_form_for(@new_post) do |builder|
89
+ concat(builder.input(:title, :as => as, :input_html => { :class => 'myclass' }))
90
+ end
91
+ output_buffer.should have_tag("form li input.myclass")
92
+ end
93
+ end
94
+
95
+ def it_should_apply_custom_for_to_label_when_input_html_id_provided(as)
96
+ it 'it should apply custom for to label when input_html :id provided' do
97
+ semantic_form_for(@new_post) do |builder|
98
+ concat(builder.input(:title, :as => as, :input_html => { :id => 'myid' }))
99
+ end
100
+ output_buffer.should have_tag('form li label[@for="myid"]')
101
+ end
102
+ end
103
+
104
+ def it_should_have_maxlength_matching_column_limit
105
+ it 'should have a maxlength matching column limit' do
106
+ @new_post.column_for_attribute(:title).limit.should == 50
107
+ output_buffer.should have_tag("form li input[@maxlength='50']")
108
+ end
109
+ end
110
+
111
+ def it_should_use_default_text_field_size_for_columns_longer_than_default_text_field_size(as)
112
+ it 'should use default_text_field_size for columns longer than default_text_field_size' do
113
+ default_size = Formtastic::SemanticFormBuilder.default_text_field_size
114
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => as, :limit => default_size * 2))
115
+
116
+ semantic_form_for(@new_post) do |builder|
117
+ concat(builder.input(:title, :as => as))
118
+ end
119
+
120
+ output_buffer.should have_tag("form li input[@size='#{default_size}']")
121
+ end
122
+ end
123
+
124
+ def it_should_use_column_size_for_columns_shorter_than_default_text_field_size(as)
125
+ it 'should use the column size for columns shorter than default_text_field_size' do
126
+ column_limit_shorted_than_default = 1
127
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => as, :limit => column_limit_shorted_than_default))
128
+
129
+ semantic_form_for(@new_post) do |builder|
130
+ concat(builder.input(:title, :as => as))
131
+ end
132
+
133
+ output_buffer.should have_tag("form li input[@size='#{column_limit_shorted_than_default}']")
134
+ end
135
+ end
136
+
137
+ def it_should_apply_error_logic_for_input_type(type)
138
+ describe 'when there are errors on the object for this method' do
139
+ before do
140
+ @title_errors = ['must not be blank', 'must be longer than 10 characters', 'must be awesome']
141
+ @errors = mock('errors')
142
+ @errors.stub!(:[]).with(:title).and_return(@title_errors)
143
+ @new_post.stub!(:errors).and_return(@errors)
144
+ end
145
+
146
+ it 'should apply an errors class to the list item' do
147
+ semantic_form_for(@new_post) do |builder|
148
+ concat(builder.input(:title, :as => type))
149
+ end
150
+ output_buffer.should have_tag('form li.error')
151
+ end
152
+
153
+ it 'should not wrap the input with the Rails default error wrapping' do
154
+ semantic_form_for(@new_post) do |builder|
155
+ concat(builder.input(:title, :as => type))
156
+ end
157
+ output_buffer.should_not have_tag('div.fieldWithErrors')
158
+ end
159
+
160
+ it 'should render a paragraph for the errors' do
161
+ ::Formtastic::SemanticFormBuilder.inline_errors = :sentence
162
+ semantic_form_for(@new_post) do |builder|
163
+ concat(builder.input(:title, :as => type))
164
+ end
165
+ output_buffer.should have_tag('form li.error p.inline-errors')
166
+ end
167
+
168
+ it 'should not display an error list' do
169
+ ::Formtastic::SemanticFormBuilder.inline_errors = :list
170
+ semantic_form_for(@new_post) do |builder|
171
+ concat(builder.input(:title, :as => type))
172
+ end
173
+ output_buffer.should have_tag('form li.error ul.errors')
174
+ end
175
+ end
176
+
177
+ describe 'when there are no errors on the object for this method' do
178
+ before do
179
+ semantic_form_for(@new_post) do |builder|
180
+ concat(builder.input(:title, :as => type))
181
+ end
182
+ end
183
+
184
+ it 'should not apply an errors class to the list item' do
185
+ output_buffer.should_not have_tag('form li.error')
186
+ end
187
+
188
+ it 'should not render a paragraph for the errors' do
189
+ output_buffer.should_not have_tag('form li.error p.inline-errors')
190
+ end
191
+
192
+ it 'should not display an error list' do
193
+ output_buffer.should_not have_tag('form li.error ul.errors')
194
+ end
195
+ end
196
+
197
+ describe 'when no object is provided' do
198
+ before do
199
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
200
+ concat(builder.input(:title, :as => type))
201
+ end
202
+ end
203
+
204
+ it 'should not apply an errors class to the list item' do
205
+ output_buffer.should_not have_tag('form li.error')
206
+ end
207
+
208
+ it 'should not render a paragraph for the errors' do
209
+ output_buffer.should_not have_tag('form li.error p.inline-errors')
210
+ end
211
+
212
+ it 'should not display an error list' do
213
+ output_buffer.should_not have_tag('form li.error ul.errors')
214
+ end
215
+ end
216
+ end
217
+
218
+ def it_should_call_find_on_association_class_when_no_collection_is_provided(as)
219
+ it "should call find on the association class when no collection is provided" do
220
+ ::Author.should_receive(:find)
221
+ semantic_form_for(@new_post) do |builder|
222
+ concat(builder.input(:author, :as => as))
223
+ end
224
+ end
225
+ end
226
+
227
+ def it_should_select_existing_datetime_else_current(*datetime_parts)
228
+ describe "default value" do
229
+ before do
230
+ @new_post.should_receive(:publish_at=).any_number_of_times
231
+ end
232
+
233
+ describe "when attribute value is present" do
234
+ before do
235
+ @output_buffer = ''
236
+ publish_at_value = 1.year.ago + 2.month + 3.day + 4.hours + 5.minutes # No comment =)
237
+ @new_post.stub!(:publish_at).and_return(publish_at_value)
238
+
239
+ semantic_form_for(@new_post) do |builder|
240
+ concat(builder.input(:publish_at, :as => :datetime))
241
+ end
242
+ end
243
+
244
+ it "should select the present value by default" do
245
+ # puts output_buffer
246
+ output_buffer.should have_tag("form li select#post_publish_at_1i option[@selected='selected'][@value='#{@new_post.publish_at.year}']") if datetime_parts.include?(:year)
247
+ output_buffer.should have_tag("form li select#post_publish_at_2i option[@selected='selected'][@value='#{@new_post.publish_at.month}']") if datetime_parts.include?(:month)
248
+ output_buffer.should have_tag("form li select#post_publish_at_3i option[@selected='selected'][@value='#{@new_post.publish_at.day}']") if datetime_parts.include?(:day)
249
+ output_buffer.should have_tag("form li select#post_publish_at_4i option[@selected='selected'][@value='#{@new_post.publish_at.strftime("%H")}']") if datetime_parts.include?(:hour)
250
+ output_buffer.should have_tag("form li select#post_publish_at_5i option[@selected='selected'][@value='#{@new_post.publish_at.strftime("%M")}']") if datetime_parts.include?(:minute)
251
+ #output_buffer.should have_tag("form li select#post_publish_at_6i option[@selected='selected'][@value='#{@new_post.publish_at.sec}']") if datetime_parts.include?(:second)
252
+ end
253
+ end
254
+
255
+ describe "when no attribute value is present" do
256
+ before do
257
+ @output_buffer = ''
258
+ @new_post.stub!(:publish_at).and_return(nil)
259
+ @current_time = ::Time.now
260
+
261
+ semantic_form_for(@new_post) do |builder|
262
+ concat(builder.input(:publish_at, :as => :datetime))
263
+ end
264
+ end
265
+
266
+ it "should select the current day/time by default" do
267
+ # puts output_buffer
268
+ output_buffer.should have_tag("form li select#post_publish_at_1i option[@selected='selected'][@value='#{@current_time.year}']") if datetime_parts.include?(:year)
269
+ output_buffer.should have_tag("form li select#post_publish_at_2i option[@selected='selected'][@value='#{@current_time.month}']") if datetime_parts.include?(:month)
270
+ output_buffer.should have_tag("form li select#post_publish_at_3i option[@selected='selected'][@value='#{@current_time.day}']") if datetime_parts.include?(:day)
271
+ output_buffer.should have_tag("form li select#post_publish_at_4i option[@selected='selected'][@value='#{@current_time.strftime("%H")}']") if datetime_parts.include?(:hour)
272
+ output_buffer.should have_tag("form li select#post_publish_at_5i option[@selected='selected'][@value='#{@current_time.strftime("%M")}']") if datetime_parts.include?(:minute)
273
+ #output_buffer.should have_tag("form li select#post_publish_at_6i option[@selected='selected'][@value='#{@custom_default_time.sec}']") if datetime_parts.include?(:second)
274
+ end
275
+
276
+ # TODO: Scenario when current time is not a possible choice (because of specified date/time ranges)?
277
+ end
278
+ end
279
+ end
280
+
281
+ def it_should_select_explicit_default_value_if_set(*datetime_parts)
282
+ describe 'when :selected is set' do
283
+ before do
284
+ @output_buffer = ''
285
+ end
286
+
287
+ # Note: Not possible to override default selected value for time_zone input
288
+ # without overriding Rails core helper. This Rails helper works "a bit different". =/
289
+ #
290
+ describe "no selected items" do
291
+ before do
292
+ @default_time = 2.days.ago
293
+ @new_post.stub!(:publish_at).and_return(@default_time)
294
+
295
+ semantic_form_for(@new_post) do |builder|
296
+ concat(builder.input(:publish_at, :as => :time_zone, :selected => nil))
297
+ end
298
+ end
299
+
300
+ it 'should not have any selected item(s)' do
301
+ output_buffer.should_not have_tag("form li select#post_publish_at_1i option[@selected='selected']")
302
+ end
303
+ end
304
+
305
+ describe "single selected item" do
306
+ before do
307
+ @custom_default_time = 5.days.ago
308
+ @new_post.stub!(:publish_at).and_return(2.days.ago)
309
+
310
+ semantic_form_for(@new_post) do |builder|
311
+ concat(builder.input(:publish_at, :as => :datetime, :selected => @custom_default_time))
312
+ end
313
+ end
314
+
315
+ it "should select the specified value" do
316
+ output_buffer.should have_tag("form li select#post_publish_at_1i option[@selected='selected'][@value='#{@custom_default_time.year}']") if datetime_parts.include?(:year)
317
+ output_buffer.should have_tag("form li select#post_publish_at_2i option[@selected='selected'][@value='#{@custom_default_time.month}']") if datetime_parts.include?(:month)
318
+ output_buffer.should have_tag("form li select#post_publish_at_3i option[@selected='selected'][@value='#{@custom_default_time.day}']") if datetime_parts.include?(:day)
319
+ output_buffer.should have_tag("form li select#post_publish_at_4i option[@selected='selected'][@value='#{@custom_default_time.strftime("%H")}']") if datetime_parts.include?(:hour)
320
+ output_buffer.should have_tag("form li select#post_publish_at_5i option[@selected='selected'][@value='#{@custom_default_time.strftime("%M")}']") if datetime_parts.include?(:minute)
321
+ #output_buffer.should have_tag("form li select#post_publish_at_6i option[@selected='selected'][@value='#{@custom_default_time.sec}']") if datetime_parts.include?(:second)
322
+ end
323
+ end
324
+
325
+ end
326
+ end
327
+
328
+ def it_should_use_the_collection_when_provided(as, countable)
329
+ describe 'when the :collection option is provided' do
330
+
331
+ before do
332
+ @authors = ::Author.find(:all) * 2
333
+ output_buffer.replace '' # clears the output_buffer from the before block, hax!
334
+ end
335
+
336
+ it 'should not call find() on the parent class' do
337
+ ::Author.should_not_receive(:find)
338
+ semantic_form_for(@new_post) do |builder|
339
+ concat(builder.input(:author, :as => as, :collection => @authors))
340
+ end
341
+ end
342
+
343
+ it 'should use the provided collection' do
344
+ semantic_form_for(@new_post) do |builder|
345
+ concat(builder.input(:author, :as => as, :collection => @authors))
346
+ end
347
+ output_buffer.should have_tag("form li.#{as} #{countable}", :count => @authors.size + (as == :select ? 1 : 0))
348
+ end
349
+
350
+ describe 'and the :collection is an array of strings' do
351
+ before do
352
+ @categories = [ 'General', 'Design', 'Development', 'Quasi-Serious Inventions' ]
353
+ end
354
+
355
+ it "should use the string as the label text and value for each #{countable}" do
356
+ semantic_form_for(@new_post) do |builder|
357
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
358
+ end
359
+
360
+ @categories.each do |value|
361
+ output_buffer.should have_tag("form li.#{as}", /#{value}/)
362
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value}']")
363
+ end
364
+ end
365
+
366
+ if as == :radio
367
+ it 'should generate a sanitized label for attribute' do
368
+ @bob.stub!(:category_name).and_return(@categories)
369
+ semantic_form_for(@new_post) do |builder|
370
+ builder.semantic_fields_for(@bob) do |bob_builder|
371
+ concat(bob_builder.input(:category_name, :as => as, :collection => @categories))
372
+ end
373
+ end
374
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_general']")
375
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_design']")
376
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_development']")
377
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_quasiserious_inventions']")
378
+ end
379
+ end
380
+ end
381
+
382
+ describe 'and the :collection is a hash of strings' do
383
+ before do
384
+ @categories = { 'General' => 'gen', 'Design' => 'des','Development' => 'dev' }
385
+ end
386
+
387
+ it "should use the key as the label text and the hash value as the value attribute for each #{countable}" do
388
+ semantic_form_for(@new_post) do |builder|
389
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
390
+ end
391
+
392
+ @categories.each do |label, value|
393
+ output_buffer.should have_tag("form li.#{as}", /#{label}/)
394
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value}']")
395
+ end
396
+ end
397
+ end
398
+
399
+ describe 'and the :collection is an array of arrays' do
400
+ before do
401
+ @categories = { 'General' => 'gen', 'Design' => 'des', 'Development' => 'dev' }.to_a
402
+ end
403
+
404
+ it "should use the first value as the label text and the last value as the value attribute for #{countable}" do
405
+ semantic_form_for(@new_post) do |builder|
406
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
407
+ end
408
+
409
+ @categories.each do |text, value|
410
+ label = as == :select ? :option : :label
411
+ output_buffer.should have_tag("form li.#{as} #{label}", /#{text}/i)
412
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value.to_s}']")
413
+ output_buffer.should have_tag("form li.#{as} #{countable}#post_category_name_#{value.to_s}") if as == :radio
414
+ end
415
+ end
416
+ end
417
+
418
+ if as == :radio
419
+ describe 'and the :collection is an array of arrays with boolean values' do
420
+ before do
421
+ @choices = { 'Yeah' => true, 'Nah' => false }.to_a
422
+ end
423
+
424
+ it "should use the first value as the label text and the last value as the value attribute for #{countable}" do
425
+ semantic_form_for(@new_post) do |builder|
426
+ concat(builder.input(:category_name, :as => as, :collection => @choices))
427
+ end
428
+
429
+ output_buffer.should have_tag("form li.#{as} #{countable}#post_category_name_true")
430
+ output_buffer.should have_tag("form li.#{as} #{countable}#post_category_name_false")
431
+ end
432
+ end
433
+ end
434
+
435
+ describe 'and the :collection is an array of symbols' do
436
+ before do
437
+ @categories = [ :General, :Design, :Development ]
438
+ end
439
+
440
+ it "should use the symbol as the label text and value for each #{countable}" do
441
+ semantic_form_for(@new_post) do |builder|
442
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
443
+ end
444
+
445
+ @categories.each do |value|
446
+ label = as == :select ? :option : :label
447
+ output_buffer.should have_tag("form li.#{as} #{label}", /#{value}/i)
448
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value.to_s}']")
449
+ end
450
+ end
451
+ end
452
+
453
+ describe 'and the :collection is an OrderedHash of strings' do
454
+ before do
455
+ @categories = ActiveSupport::OrderedHash.new('General' => 'gen', 'Design' => 'des','Development' => 'dev')
456
+ end
457
+
458
+ it "should use the key as the label text and the hash value as the value attribute for each #{countable}" do
459
+ semantic_form_for(@new_post) do |builder|
460
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
461
+ end
462
+
463
+ @categories.each do |label, value|
464
+ output_buffer.should have_tag("form li.#{as}", /#{label}/)
465
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value}']")
466
+ end
467
+ end
468
+
469
+ end
470
+
471
+ describe 'when the :label_method option is provided' do
472
+
473
+ describe 'as a symbol' do
474
+ before do
475
+ semantic_form_for(@new_post) do |builder|
476
+ concat(builder.input(:author, :as => as, :label_method => :login))
477
+ end
478
+ end
479
+
480
+ it 'should have options with text content from the specified method' do
481
+ ::Author.find(:all).each do |author|
482
+ output_buffer.should have_tag("form li.#{as}", /#{author.login}/)
483
+ end
484
+ end
485
+ end
486
+
487
+ describe 'as a proc' do
488
+ before do
489
+ semantic_form_for(@new_post) do |builder|
490
+ concat(builder.input(:author, :as => as, :label_method => Proc.new {|a| a.login.reverse }))
491
+ end
492
+ end
493
+
494
+ it 'should have options with the proc applied to each' do
495
+ ::Author.find(:all).each do |author|
496
+ output_buffer.should have_tag("form li.#{as}", /#{author.login.reverse}/)
497
+ end
498
+ end
499
+ end
500
+
501
+ end
502
+
503
+ describe 'when the :label_method option is not provided' do
504
+ ::Formtastic::SemanticFormBuilder.collection_label_methods.each do |label_method|
505
+
506
+ describe "when the collection objects respond to #{label_method}" do
507
+ before do
508
+ @fred.stub!(:respond_to?).and_return { |m| m.to_s == label_method }
509
+ ::Author.find(:all).each { |a| a.stub!(label_method).and_return('The Label Text') }
510
+
511
+ semantic_form_for(@new_post) do |builder|
512
+ concat(builder.input(:author, :as => as))
513
+ end
514
+ end
515
+
516
+ it "should render the options with #{label_method} as the label" do
517
+ ::Author.find(:all).each do |author|
518
+ output_buffer.should have_tag("form li.#{as}", /The Label Text/)
519
+ end
520
+ end
521
+ end
522
+
523
+ end
524
+ end
525
+
526
+ describe 'when the :value_method option is provided' do
527
+
528
+ describe 'as a symbol' do
529
+ before do
530
+ semantic_form_for(@new_post) do |builder|
531
+ concat(builder.input(:author, :as => as, :value_method => :login))
532
+ end
533
+ end
534
+
535
+ it 'should have options with values from specified method' do
536
+ ::Author.find(:all).each do |author|
537
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{author.login}']")
538
+ end
539
+ end
540
+ end
541
+
542
+ describe 'as a proc' do
543
+ before do
544
+ semantic_form_for(@new_post) do |builder|
545
+ concat(builder.input(:author, :as => as, :value_method => Proc.new {|a| a.login.reverse }))
546
+ end
547
+ end
548
+
549
+ it 'should have options with the proc applied to each value' do
550
+ ::Author.find(:all).each do |author|
551
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{author.login.reverse}']")
552
+ end
553
+ end
554
+ end
555
+ end
556
+
557
+ end
558
+ end
559
+
560
+ end
561
+ end