formtastic 1.2.4 → 3.1.5

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 (189) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +46 -0
  5. data/.yardopts +1 -0
  6. data/Appraisals +43 -0
  7. data/CHANGELOG +54 -0
  8. data/DEPRECATIONS +52 -0
  9. data/Gemfile +3 -0
  10. data/README.md +629 -0
  11. data/RELEASE_PROCESS +6 -0
  12. data/Rakefile +35 -0
  13. data/app/assets/stylesheets/formtastic.css +289 -0
  14. data/app/assets/stylesheets/formtastic_ie6.css +33 -0
  15. data/app/assets/stylesheets/formtastic_ie7.css +23 -0
  16. data/formtastic.gemspec +42 -0
  17. data/gemfiles/rails_3.2.gemfile +9 -0
  18. data/gemfiles/rails_4.0.4.gemfile +8 -0
  19. data/gemfiles/rails_4.1.gemfile +8 -0
  20. data/gemfiles/rails_4.2.gemfile +8 -0
  21. data/gemfiles/rails_4.gemfile +8 -0
  22. data/gemfiles/rails_5.0.gemfile +8 -0
  23. data/gemfiles/rails_edge.gemfile +15 -0
  24. data/lib/formtastic.rb +40 -1945
  25. data/lib/formtastic/action_class_finder.rb +18 -0
  26. data/lib/formtastic/actions.rb +11 -0
  27. data/lib/formtastic/actions/base.rb +156 -0
  28. data/lib/formtastic/actions/button_action.rb +67 -0
  29. data/lib/formtastic/actions/buttonish.rb +17 -0
  30. data/lib/formtastic/actions/input_action.rb +70 -0
  31. data/lib/formtastic/actions/link_action.rb +88 -0
  32. data/lib/formtastic/deprecation.rb +42 -0
  33. data/lib/formtastic/engine.rb +11 -0
  34. data/lib/formtastic/form_builder.rb +124 -0
  35. data/lib/formtastic/helpers.rb +16 -0
  36. data/lib/formtastic/helpers/action_helper.rb +162 -0
  37. data/lib/formtastic/helpers/actions_helper.rb +168 -0
  38. data/lib/formtastic/helpers/enum.rb +13 -0
  39. data/lib/formtastic/helpers/errors_helper.rb +81 -0
  40. data/lib/formtastic/helpers/fieldset_wrapper.rb +80 -0
  41. data/lib/formtastic/helpers/file_column_detection.rb +16 -0
  42. data/lib/formtastic/helpers/form_helper.rb +203 -0
  43. data/lib/formtastic/helpers/input_helper.rb +407 -0
  44. data/lib/formtastic/helpers/inputs_helper.rb +411 -0
  45. data/lib/formtastic/helpers/reflection.rb +37 -0
  46. data/lib/formtastic/html_attributes.rb +32 -0
  47. data/lib/formtastic/i18n.rb +4 -2
  48. data/lib/formtastic/input_class_finder.rb +18 -0
  49. data/lib/formtastic/inputs.rb +39 -0
  50. data/lib/formtastic/inputs/base.rb +76 -0
  51. data/lib/formtastic/inputs/base/associations.rb +31 -0
  52. data/lib/formtastic/inputs/base/choices.rb +108 -0
  53. data/lib/formtastic/inputs/base/collections.rb +159 -0
  54. data/lib/formtastic/inputs/base/database.rb +22 -0
  55. data/lib/formtastic/inputs/base/datetime_pickerish.rb +85 -0
  56. data/lib/formtastic/inputs/base/errors.rb +58 -0
  57. data/lib/formtastic/inputs/base/fileish.rb +23 -0
  58. data/lib/formtastic/inputs/base/hints.rb +31 -0
  59. data/lib/formtastic/inputs/base/html.rb +53 -0
  60. data/lib/formtastic/inputs/base/labelling.rb +52 -0
  61. data/lib/formtastic/inputs/base/naming.rb +42 -0
  62. data/lib/formtastic/inputs/base/numeric.rb +50 -0
  63. data/lib/formtastic/inputs/base/options.rb +17 -0
  64. data/lib/formtastic/inputs/base/placeholder.rb +17 -0
  65. data/lib/formtastic/inputs/base/stringish.rb +38 -0
  66. data/lib/formtastic/inputs/base/timeish.rb +241 -0
  67. data/lib/formtastic/inputs/base/validations.rb +215 -0
  68. data/lib/formtastic/inputs/base/wrapping.rb +50 -0
  69. data/lib/formtastic/inputs/boolean_input.rb +118 -0
  70. data/lib/formtastic/inputs/check_boxes_input.rb +197 -0
  71. data/lib/formtastic/inputs/color_input.rb +42 -0
  72. data/lib/formtastic/inputs/country_input.rb +86 -0
  73. data/lib/formtastic/inputs/datalist_input.rb +41 -0
  74. data/lib/formtastic/inputs/date_picker_input.rb +93 -0
  75. data/lib/formtastic/inputs/date_select_input.rb +34 -0
  76. data/lib/formtastic/inputs/datetime_picker_input.rb +103 -0
  77. data/lib/formtastic/inputs/datetime_select_input.rb +12 -0
  78. data/lib/formtastic/inputs/email_input.rb +41 -0
  79. data/lib/formtastic/inputs/file_input.rb +42 -0
  80. data/lib/formtastic/inputs/hidden_input.rb +62 -0
  81. data/lib/formtastic/inputs/number_input.rb +88 -0
  82. data/lib/formtastic/inputs/password_input.rb +41 -0
  83. data/lib/formtastic/inputs/phone_input.rb +42 -0
  84. data/lib/formtastic/inputs/radio_input.rb +163 -0
  85. data/lib/formtastic/inputs/range_input.rb +95 -0
  86. data/lib/formtastic/inputs/search_input.rb +41 -0
  87. data/lib/formtastic/inputs/select_input.rb +235 -0
  88. data/lib/formtastic/inputs/string_input.rb +36 -0
  89. data/lib/formtastic/inputs/text_input.rb +48 -0
  90. data/lib/formtastic/inputs/time_picker_input.rb +99 -0
  91. data/lib/formtastic/inputs/time_select_input.rb +38 -0
  92. data/lib/formtastic/inputs/time_zone_input.rb +58 -0
  93. data/lib/formtastic/inputs/url_input.rb +41 -0
  94. data/lib/formtastic/localized_string.rb +17 -0
  95. data/lib/formtastic/localizer.rb +152 -0
  96. data/lib/formtastic/namespaced_class_finder.rb +99 -0
  97. data/lib/formtastic/util.rb +35 -16
  98. data/lib/formtastic/version.rb +3 -0
  99. data/lib/generators/formtastic/form/form_generator.rb +64 -37
  100. data/lib/generators/formtastic/input/input_generator.rb +46 -0
  101. data/lib/generators/formtastic/install/install_generator.rb +13 -5
  102. data/lib/generators/templates/_form.html.erb +10 -4
  103. data/lib/generators/templates/_form.html.haml +8 -4
  104. data/lib/generators/templates/_form.html.slim +8 -0
  105. data/lib/generators/templates/formtastic.rb +77 -44
  106. data/lib/generators/templates/input.rb +19 -0
  107. data/lib/locale/en.yml +3 -0
  108. data/sample/basic_inputs.html +224 -0
  109. data/sample/config.ru +69 -0
  110. data/sample/index.html +14 -0
  111. data/spec/action_class_finder_spec.rb +12 -0
  112. data/spec/actions/button_action_spec.rb +63 -0
  113. data/spec/actions/generic_action_spec.rb +521 -0
  114. data/spec/actions/input_action_spec.rb +59 -0
  115. data/spec/actions/link_action_spec.rb +92 -0
  116. data/spec/builder/custom_builder_spec.rb +116 -0
  117. data/spec/builder/error_proc_spec.rb +27 -0
  118. data/spec/builder/semantic_fields_for_spec.rb +142 -0
  119. data/spec/fast_spec_helper.rb +12 -0
  120. data/spec/generators/formtastic/form/form_generator_spec.rb +131 -0
  121. data/spec/generators/formtastic/input/input_generator_spec.rb +124 -0
  122. data/spec/generators/formtastic/install/install_generator_spec.rb +47 -0
  123. data/spec/helpers/action_helper_spec.rb +19 -0
  124. data/spec/helpers/actions_helper_spec.rb +143 -0
  125. data/spec/helpers/form_helper_spec.rb +218 -0
  126. data/spec/helpers/input_helper_spec.rb +6 -0
  127. data/spec/helpers/inputs_helper_spec.rb +655 -0
  128. data/spec/helpers/namespaced_action_helper_spec.rb +43 -0
  129. data/spec/helpers/namespaced_input_helper_spec.rb +36 -0
  130. data/spec/helpers/reflection_helper_spec.rb +32 -0
  131. data/spec/helpers/semantic_errors_helper_spec.rb +112 -0
  132. data/spec/i18n_spec.rb +210 -0
  133. data/spec/input_class_finder_spec.rb +10 -0
  134. data/spec/inputs/base/collections_spec.rb +76 -0
  135. data/spec/inputs/base/validations_spec.rb +342 -0
  136. data/spec/inputs/boolean_input_spec.rb +254 -0
  137. data/spec/inputs/check_boxes_input_spec.rb +546 -0
  138. data/spec/inputs/color_input_spec.rb +97 -0
  139. data/spec/inputs/country_input_spec.rb +133 -0
  140. data/spec/inputs/custom_input_spec.rb +55 -0
  141. data/spec/inputs/datalist_input_spec.rb +61 -0
  142. data/spec/inputs/date_picker_input_spec.rb +449 -0
  143. data/spec/inputs/date_select_input_spec.rb +235 -0
  144. data/spec/inputs/datetime_picker_input_spec.rb +490 -0
  145. data/spec/inputs/datetime_select_input_spec.rb +193 -0
  146. data/spec/inputs/email_input_spec.rb +85 -0
  147. data/spec/inputs/file_input_spec.rb +89 -0
  148. data/spec/inputs/hidden_input_spec.rb +135 -0
  149. data/spec/inputs/include_blank_spec.rb +78 -0
  150. data/spec/inputs/label_spec.rb +149 -0
  151. data/spec/inputs/number_input_spec.rb +815 -0
  152. data/spec/inputs/password_input_spec.rb +99 -0
  153. data/spec/inputs/phone_input_spec.rb +85 -0
  154. data/spec/inputs/placeholder_spec.rb +71 -0
  155. data/spec/inputs/radio_input_spec.rb +328 -0
  156. data/spec/inputs/range_input_spec.rb +505 -0
  157. data/spec/inputs/readonly_spec.rb +50 -0
  158. data/spec/inputs/search_input_spec.rb +84 -0
  159. data/spec/inputs/select_input_spec.rb +615 -0
  160. data/spec/inputs/string_input_spec.rb +260 -0
  161. data/spec/inputs/text_input_spec.rb +187 -0
  162. data/spec/inputs/time_picker_input_spec.rb +455 -0
  163. data/spec/inputs/time_select_input_spec.rb +248 -0
  164. data/spec/inputs/time_zone_input_spec.rb +143 -0
  165. data/spec/inputs/url_input_spec.rb +85 -0
  166. data/spec/inputs/with_options_spec.rb +43 -0
  167. data/spec/localizer_spec.rb +130 -0
  168. data/spec/namespaced_class_finder_spec.rb +79 -0
  169. data/spec/spec.opts +2 -0
  170. data/spec/spec_helper.rb +525 -0
  171. data/spec/support/custom_macros.rb +564 -0
  172. data/spec/support/deprecation.rb +6 -0
  173. data/spec/support/shared_examples.rb +1313 -0
  174. data/spec/support/specialized_class_finder_shared_example.rb +27 -0
  175. data/spec/support/test_environment.rb +31 -0
  176. data/spec/util_spec.rb +66 -0
  177. metadata +434 -161
  178. data/README.textile +0 -682
  179. data/generators/form/USAGE +0 -16
  180. data/generators/form/form_generator.rb +0 -111
  181. data/generators/formtastic/formtastic_generator.rb +0 -26
  182. data/init.rb +0 -5
  183. data/lib/formtastic/layout_helper.rb +0 -12
  184. data/lib/formtastic/railtie.rb +0 -14
  185. data/lib/generators/templates/formtastic.css +0 -145
  186. data/lib/generators/templates/formtastic_changes.css +0 -14
  187. data/lib/generators/templates/rails2/_form.html.erb +0 -5
  188. data/lib/generators/templates/rails2/_form.html.haml +0 -4
  189. data/rails/init.rb +0 -2
@@ -0,0 +1,564 @@
1
+ # encoding: utf-8
2
+
3
+ module CustomMacros
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+
11
+ def it_should_have_input_wrapper_with_class(class_name)
12
+ it "should have input wrapper with class '#{class_name}'" do
13
+ output_buffer.should have_tag("form li.#{class_name}")
14
+ end
15
+ end
16
+
17
+ def it_should_have_input_wrapper_with_id(id_string)
18
+ it "should have input wrapper with id '#{id_string}'" do
19
+ output_buffer.should have_tag("form li##{id_string}")
20
+ end
21
+ end
22
+
23
+ def it_should_not_have_a_label
24
+ it "should not have a label" do
25
+ output_buffer.should_not have_tag("form li label")
26
+ end
27
+ end
28
+
29
+ def it_should_have_a_nested_fieldset
30
+ it "should have a nested_fieldset" do
31
+ output_buffer.should have_tag("form li fieldset")
32
+ end
33
+ end
34
+
35
+ def it_should_have_a_nested_fieldset_with_class(klass)
36
+ it "should have a nested_fieldset with class #{klass}" do
37
+ output_buffer.should have_tag("form li fieldset.#{klass}")
38
+ end
39
+ end
40
+
41
+ def it_should_have_a_nested_ordered_list_with_class(klass)
42
+ it "should have a nested fieldset with class #{klass}" do
43
+ output_buffer.should have_tag("form li ol.#{klass}")
44
+ end
45
+ end
46
+
47
+ def it_should_have_label_with_text(string_or_regex)
48
+ it "should have a label with text '#{string_or_regex}'" do
49
+ output_buffer.should have_tag("form li label", string_or_regex)
50
+ end
51
+ end
52
+
53
+ def it_should_have_label_for(element_id)
54
+ it "should have a label for ##{element_id}" do
55
+ output_buffer.should have_tag("form li label.label[@for='#{element_id}']")
56
+ end
57
+ end
58
+
59
+ def it_should_have_an_inline_label_for(element_id)
60
+ it "should have a label for ##{element_id}" do
61
+ output_buffer.should have_tag("form li label[@for='#{element_id}']")
62
+ end
63
+ end
64
+
65
+ def it_should_have_input_with_id(element_id)
66
+ it "should have an input with id '#{element_id}'" do
67
+ output_buffer.should have_tag("form li input##{element_id}")
68
+ end
69
+ end
70
+
71
+ def it_should_have_select_with_id(element_id)
72
+ it "should have a select box with id '#{element_id}'" do
73
+ output_buffer.should have_tag("form li select##{element_id}")
74
+ end
75
+ end
76
+
77
+ # TODO use for many of the other macros
78
+ def it_should_have_tag_with(type, attribute_value_hash)
79
+ attribute_value_hash.each do |attribute, value|
80
+ it "should have a #{type} box with #{attribute} '#{value}'" do
81
+ output_buffer.should have_tag("form li #{type}[@#{attribute}=\"#{value}\"]")
82
+ end
83
+ end
84
+ end
85
+ def it_should_have_input_with(attribute_value_hash)
86
+ it_should_have_tag_with(:input, attribute_value_hash)
87
+ end
88
+
89
+ def it_should_have_many_tags(type, count)
90
+ it "should have #{count} #{type} tags" do
91
+ output_buffer.should have_tag("form li #{type}", count: count)
92
+ end
93
+ end
94
+
95
+ def it_should_have_input_with_type(input_type)
96
+ it "should have a #{input_type} input" do
97
+ output_buffer.should have_tag("form li input[@type=\"#{input_type}\"]")
98
+ end
99
+ end
100
+
101
+ def it_should_have_input_with_name(name)
102
+ it "should have an input named #{name}" do
103
+ output_buffer.should have_tag("form li input[@name=\"#{name}\"]")
104
+ end
105
+ end
106
+
107
+ def it_should_have_select_with_name(name)
108
+ it "should have an input named #{name}" do
109
+ output_buffer.should have_tag("form li select[@name=\"#{name}\"]")
110
+ end
111
+ end
112
+
113
+ def it_should_have_textarea_with_name(name)
114
+ it "should have an input named #{name}" do
115
+ output_buffer.should have_tag("form li textarea[@name=\"#{name}\"]")
116
+ end
117
+ end
118
+
119
+ def it_should_have_textarea_with_id(element_id)
120
+ it "should have an input with id '#{element_id}'" do
121
+ output_buffer.should have_tag("form li textarea##{element_id}")
122
+ end
123
+ end
124
+
125
+ def it_should_have_label_and_input_with_id(element_id)
126
+ it "should have an input with id '#{element_id}'" do
127
+ output_buffer.should have_tag("form li input##{element_id}")
128
+ output_buffer.should have_tag("form li label[@for='#{element_id}']")
129
+ end
130
+ end
131
+
132
+ def it_should_use_default_text_field_size_when_not_nil(as)
133
+ it 'should use default_text_field_size when not nil' do
134
+ with_config :default_text_field_size, 30 do
135
+ concat(semantic_form_for(@new_post) do |builder|
136
+ concat(builder.input(:title, :as => as))
137
+ end)
138
+ output_buffer.should have_tag("form li input[@size='#{Formtastic::FormBuilder.default_text_field_size}']")
139
+ end
140
+ end
141
+ end
142
+
143
+ def it_should_not_use_default_text_field_size_when_nil(as)
144
+ it 'should not use default_text_field_size when nil' do
145
+ with_config :default_text_field_size, nil do
146
+ concat(semantic_form_for(@new_post) do |builder|
147
+ concat(builder.input(:title, :as => as))
148
+ end)
149
+ output_buffer.should have_tag("form li input")
150
+ output_buffer.should_not have_tag("form li input[@size]")
151
+ end
152
+ end
153
+ end
154
+
155
+ def it_should_apply_custom_input_attributes_when_input_html_provided(as)
156
+ it 'it should apply custom input attributes when input_html provided' do
157
+ concat(semantic_form_for(@new_post) do |builder|
158
+ concat(builder.input(:title, :as => as, :input_html => { :class => 'myclass' }))
159
+ end)
160
+ output_buffer.should have_tag("form li input.myclass")
161
+ end
162
+ end
163
+
164
+ def it_should_apply_custom_for_to_label_when_input_html_id_provided(as)
165
+ it 'it should apply custom for to label when input_html :id provided' do
166
+ concat(semantic_form_for(@new_post) do |builder|
167
+ concat(builder.input(:title, :as => as, :input_html => { :id => 'myid' }))
168
+ end)
169
+ output_buffer.should have_tag('form li label[@for="myid"]')
170
+ end
171
+ end
172
+
173
+ def it_should_have_maxlength_matching_column_limit
174
+ it 'should have a maxlength matching column limit' do
175
+ @new_post.column_for_attribute(:title).limit.should == 50
176
+ output_buffer.should have_tag("form li input[@maxlength='50']")
177
+ end
178
+ end
179
+
180
+ def it_should_use_column_size_for_columns_shorter_than_default_text_field_size(as)
181
+ it 'should use the column size for columns shorter than default_text_field_size' do
182
+ column_limit_shorted_than_default = 1
183
+ @new_post.stub(:column_for_attribute).and_return(double('column', :type => as, :limit => column_limit_shorted_than_default))
184
+
185
+ concat(semantic_form_for(@new_post) do |builder|
186
+ concat(builder.input(:title, :as => as))
187
+ end)
188
+
189
+ output_buffer.should have_tag("form li input[@size='#{column_limit_shorted_than_default}']")
190
+ end
191
+ end
192
+
193
+ def it_should_apply_error_logic_for_input_type(type)
194
+ describe 'when there are errors on the object for this method' do
195
+ before do
196
+ @title_errors = ['must not be blank', 'must be longer than 10 characters', 'must be awesome']
197
+ @errors = double('errors')
198
+ @errors.stub(:[]).with(errors_matcher(:title)).and_return(@title_errors)
199
+ Formtastic::FormBuilder.file_metadata_suffixes.each do |suffix|
200
+ @errors.stub(:[]).with(errors_matcher("title_#{suffix}".to_sym)).and_return(nil)
201
+ end
202
+ @new_post.stub(:errors).and_return(@errors)
203
+ end
204
+
205
+ it 'should apply an errors class to the list item' do
206
+ concat(semantic_form_for(@new_post) do |builder|
207
+ concat(builder.input(:title, :as => type))
208
+ end)
209
+ output_buffer.should have_tag('form li.error')
210
+ end
211
+
212
+ it 'should not wrap the input with the Rails default error wrapping' do
213
+ concat(semantic_form_for(@new_post) do |builder|
214
+ concat(builder.input(:title, :as => type))
215
+ end)
216
+ output_buffer.should_not have_tag('div.fieldWithErrors')
217
+ end
218
+
219
+ it 'should render a paragraph for the errors' do
220
+ Formtastic::FormBuilder.inline_errors = :sentence
221
+ concat(semantic_form_for(@new_post) do |builder|
222
+ concat(builder.input(:title, :as => type))
223
+ end)
224
+ output_buffer.should have_tag('form li.error p.inline-errors')
225
+ end
226
+
227
+ it 'should not display an error list' do
228
+ Formtastic::FormBuilder.inline_errors = :list
229
+ concat(semantic_form_for(@new_post) do |builder|
230
+ concat(builder.input(:title, :as => type))
231
+ end)
232
+ output_buffer.should have_tag('form li.error ul.errors')
233
+ end
234
+ end
235
+
236
+ describe 'when there are no errors on the object for this method' do
237
+ before do
238
+ @form = semantic_form_for(@new_post) do |builder|
239
+ concat(builder.input(:title, :as => type))
240
+ end
241
+ end
242
+
243
+ it 'should not apply an errors class to the list item' do
244
+ output_buffer.should_not have_tag('form li.error')
245
+ end
246
+
247
+ it 'should not render a paragraph for the errors' do
248
+ output_buffer.should_not have_tag('form li.error p.inline-errors')
249
+ end
250
+
251
+ it 'should not display an error list' do
252
+ output_buffer.should_not have_tag('form li.error ul.errors')
253
+ end
254
+ end
255
+
256
+ describe 'when no object is provided' do
257
+ before do
258
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
259
+ concat(builder.input(:title, :as => type))
260
+ end)
261
+ end
262
+
263
+ it 'should not apply an errors class to the list item' do
264
+ output_buffer.should_not have_tag('form li.error')
265
+ end
266
+
267
+ it 'should not render a paragraph for the errors' do
268
+ output_buffer.should_not have_tag('form li.error p.inline-errors')
269
+ end
270
+
271
+ it 'should not display an error list' do
272
+ output_buffer.should_not have_tag('form li.error ul.errors')
273
+ end
274
+ end
275
+ end
276
+
277
+ def it_should_call_find_on_association_class_when_no_collection_is_provided(as)
278
+ it "should call find on the association class when no collection is provided" do
279
+ if Formtastic::Util.rails3?
280
+ ::Author.should_receive(:scoped)
281
+ else
282
+ ::Author.should_receive(:where)
283
+ end
284
+ concat(semantic_form_for(@new_post) do |builder|
285
+ concat(builder.input(:author, :as => as))
286
+ end)
287
+ end
288
+ end
289
+
290
+ def it_should_use_the_collection_when_provided(as, countable)
291
+ describe 'when the :collection option is provided' do
292
+
293
+ before do
294
+ @authors = ([::Author.all] * 2).flatten
295
+ output_buffer.replace ''
296
+ end
297
+
298
+ it 'should use the provided collection' do
299
+ concat(semantic_form_for(@new_post) do |builder|
300
+ concat(builder.input(:author, :as => as, :collection => @authors))
301
+ end)
302
+ output_buffer.should have_tag("form li.#{as} #{countable}", :count => @authors.size + (as == :select ? 1 : 0))
303
+ end
304
+
305
+ describe 'and the :collection is an array of strings' do
306
+ before do
307
+ @categories = [ 'General', 'Design', 'Development', 'Quasi-Serious Inventions' ]
308
+ end
309
+
310
+ it "should use the string as the label text and value for each #{countable}" do
311
+ concat(semantic_form_for(@new_post) do |builder|
312
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
313
+ end)
314
+
315
+ @categories.each do |value|
316
+ output_buffer.should have_tag("form li.#{as}", /#{value}/)
317
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value}']")
318
+ end
319
+ end
320
+
321
+ if as == :radio
322
+ it 'should generate a sanitized label for attribute' do
323
+ @bob.stub(:category_name).and_return(@categories)
324
+ concat(semantic_form_for(@new_post) do |builder|
325
+ fields = builder.semantic_fields_for(@bob) do |bob_builder|
326
+ concat(bob_builder.input(:category_name, :as => as, :collection => @categories))
327
+ end
328
+ concat(fields)
329
+ end)
330
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_general']")
331
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_design']")
332
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_development']")
333
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_quasi-serious_inventions']")
334
+ end
335
+ end
336
+ end
337
+
338
+ describe 'and the :collection is a hash of strings' do
339
+ before do
340
+ @categories = { 'General' => 'gen', 'Design' => 'des','Development' => 'dev' }
341
+ end
342
+
343
+ it "should use the key as the label text and the hash value as the value attribute for each #{countable}" do
344
+ concat(semantic_form_for(@new_post) do |builder|
345
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
346
+ end)
347
+
348
+ @categories.each do |label, value|
349
+ output_buffer.should have_tag("form li.#{as}", /#{label}/)
350
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value}']")
351
+ end
352
+ end
353
+ end
354
+
355
+ describe 'and the :collection is an array of arrays' do
356
+ before do
357
+ @categories = { 'General' => 'gen', 'Design' => 'des', 'Development' => 'dev' }.to_a
358
+ end
359
+
360
+ it "should use the first value as the label text and the last value as the value attribute for #{countable}" do
361
+ concat(semantic_form_for(@new_post) do |builder|
362
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
363
+ end)
364
+
365
+ @categories.each do |text, value|
366
+ label = as == :select ? :option : :label
367
+ output_buffer.should have_tag("form li.#{as} #{label}", /#{text}/i)
368
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value.to_s}']")
369
+ output_buffer.should have_tag("form li.#{as} #{countable}#post_category_name_#{value.to_s}") if as == :radio
370
+ end
371
+ end
372
+ end
373
+
374
+ if as == :radio
375
+ describe 'and the :collection is an array of arrays with boolean values' do
376
+ before do
377
+ @choices = { 'Yeah' => true, 'Nah' => false }.to_a
378
+ end
379
+
380
+ it "should use the first value as the label text and the last value as the value attribute for #{countable}" do
381
+ concat(semantic_form_for(@new_post) do |builder|
382
+ concat(builder.input(:category_name, :as => as, :collection => @choices))
383
+ end)
384
+
385
+ output_buffer.should have_tag("form li.#{as} #{countable}#post_category_name_true")
386
+ output_buffer.should have_tag("form li.#{as} #{countable}#post_category_name_false")
387
+ end
388
+ end
389
+ end
390
+
391
+ describe 'and the :collection is an array of symbols' do
392
+ before do
393
+ @categories = [ :General, :Design, :Development ]
394
+ end
395
+
396
+ it "should use the symbol as the label text and value for each #{countable}" do
397
+ concat(semantic_form_for(@new_post) do |builder|
398
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
399
+ end)
400
+
401
+ @categories.each do |value|
402
+ label = as == :select ? :option : :label
403
+ output_buffer.should have_tag("form li.#{as} #{label}", /#{value}/i)
404
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value.to_s}']")
405
+ end
406
+ end
407
+ end
408
+
409
+ describe 'and the :collection is an OrderedHash of strings' do
410
+ before do
411
+ @categories = ActiveSupport::OrderedHash.new('General' => 'gen', 'Design' => 'des','Development' => 'dev')
412
+ end
413
+
414
+ it "should use the key as the label text and the hash value as the value attribute for each #{countable}" do
415
+ concat(semantic_form_for(@new_post) do |builder|
416
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
417
+ end)
418
+
419
+ @categories.each do |label, value|
420
+ output_buffer.should have_tag("form li.#{as}", /#{label}/)
421
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value}']")
422
+ end
423
+ end
424
+
425
+ end
426
+
427
+ describe 'when the :member_label option is provided' do
428
+
429
+ describe 'as a symbol' do
430
+ before do
431
+ with_deprecation_silenced do
432
+ concat(semantic_form_for(@new_post) do |builder|
433
+ concat(builder.input(:author, :as => as, :member_label => :login))
434
+ end)
435
+ end
436
+ end
437
+
438
+ it 'should have options with text content from the specified method' do
439
+ ::Author.all.each do |author|
440
+ output_buffer.should have_tag("form li.#{as}", /#{author.login}/)
441
+ end
442
+ end
443
+ end
444
+
445
+ describe 'as a proc' do
446
+ before do
447
+ with_deprecation_silenced do
448
+ concat(semantic_form_for(@new_post) do |builder|
449
+ concat(builder.input(:author, :as => as, :member_label => Proc.new {|a| a.login.reverse }))
450
+ end)
451
+ end
452
+ end
453
+
454
+ it 'should have options with the proc applied to each' do
455
+ ::Author.all.each do |author|
456
+ output_buffer.should have_tag("form li.#{as}", /#{author.login.reverse}/)
457
+ end
458
+ end
459
+ end
460
+
461
+ describe 'as a method object' do
462
+ before do
463
+ def reverse_login(a)
464
+ a.login.reverse
465
+ end
466
+ with_deprecation_silenced do
467
+ concat(semantic_form_for(@new_post) do |builder|
468
+ concat(builder.input(:author, :as => as, :member_label => method(:reverse_login)))
469
+ end)
470
+ end
471
+ end
472
+
473
+ it 'should have options with the proc applied to each' do
474
+ ::Author.all.each do |author|
475
+ output_buffer.should have_tag("form li.#{as}", /#{author.login.reverse}/)
476
+ end
477
+ end
478
+ end
479
+ end
480
+
481
+ describe 'when the :member_label option is not provided' do
482
+ Formtastic::FormBuilder.collection_label_methods.each do |label_method|
483
+
484
+ describe "when the collection objects respond to #{label_method}" do
485
+ before do
486
+ @fred.stub(:respond_to?) { |m| m.to_s == label_method || m.to_s == 'id' }
487
+ [@fred, @bob].each { |a| a.stub(label_method).and_return('The Label Text') }
488
+
489
+ with_deprecation_silenced do
490
+ concat(semantic_form_for(@new_post) do |builder|
491
+ concat(builder.input(:author, :as => as))
492
+ end)
493
+ end
494
+ end
495
+
496
+ it "should render the options with #{label_method} as the label" do
497
+ ::Author.all.each do |author|
498
+ output_buffer.should have_tag("form li.#{as}", /The Label Text/)
499
+ end
500
+ end
501
+ end
502
+
503
+ end
504
+ end
505
+
506
+ describe 'when the :member_value option is provided' do
507
+
508
+ describe 'as a symbol' do
509
+ before do
510
+ with_deprecation_silenced do
511
+ concat(semantic_form_for(@new_post) do |builder|
512
+ concat(builder.input(:author, :as => as, :member_value => :login))
513
+ end)
514
+ end
515
+ end
516
+
517
+ it 'should have options with values from specified method' do
518
+ ::Author.all.each do |author|
519
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{author.login}']")
520
+ end
521
+ end
522
+ end
523
+
524
+ describe 'as a proc' do
525
+ before do
526
+ with_deprecation_silenced do
527
+ concat(semantic_form_for(@new_post) do |builder|
528
+ concat(builder.input(:author, :as => as, :member_value => Proc.new {|a| a.login.reverse }))
529
+ end)
530
+ end
531
+ end
532
+
533
+ it 'should have options with the proc applied to each value' do
534
+ ::Author.all.each do |author|
535
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{author.login.reverse}']")
536
+ end
537
+ end
538
+ end
539
+
540
+ describe 'as a method object' do
541
+ before do
542
+ def reverse_login(a)
543
+ a.login.reverse
544
+ end
545
+ with_deprecation_silenced do
546
+ concat(semantic_form_for(@new_post) do |builder|
547
+ concat(builder.input(:author, :as => as, :member_value => method(:reverse_login)))
548
+ end)
549
+ end
550
+ end
551
+
552
+ it 'should have options with the proc applied to each value' do
553
+ ::Author.all.each do |author|
554
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{author.login.reverse}']")
555
+ end
556
+ end
557
+ end
558
+ end
559
+
560
+ end
561
+ end
562
+
563
+ end
564
+ end