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,546 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe 'check_boxes input' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+ end
12
+
13
+ describe 'for a has_many association' do
14
+ before do
15
+ @output_buffer = ''
16
+ mock_everything
17
+
18
+ concat(semantic_form_for(@fred) do |builder|
19
+ concat(builder.input(:posts, :as => :check_boxes, :value_as_class => true, :required => true))
20
+ end)
21
+ end
22
+
23
+ it_should_have_input_wrapper_with_class("check_boxes")
24
+ it_should_have_input_wrapper_with_class(:input)
25
+ it_should_have_input_wrapper_with_id("author_posts_input")
26
+ it_should_have_a_nested_fieldset
27
+ it_should_have_a_nested_fieldset_with_class('choices')
28
+ it_should_have_a_nested_ordered_list_with_class('choices-group')
29
+ it_should_apply_error_logic_for_input_type(:check_boxes)
30
+ it_should_call_find_on_association_class_when_no_collection_is_provided(:check_boxes)
31
+ it_should_use_the_collection_when_provided(:check_boxes, 'input[@type="checkbox"]')
32
+
33
+ it 'should generate a legend containing a label with text for the input' do
34
+ output_buffer.should have_tag('form li fieldset legend.label label')
35
+ output_buffer.should have_tag('form li fieldset legend.label label', /Posts/)
36
+ end
37
+
38
+ it 'should not link the label within the legend to any input' do
39
+ output_buffer.should_not have_tag('form li fieldset legend label[@for^="author_post_ids_"]')
40
+ end
41
+
42
+ it 'should generate an ordered list with an li.choice for each choice' do
43
+ output_buffer.should have_tag('form li fieldset ol')
44
+ output_buffer.should have_tag('form li fieldset ol li.choice input[@type=checkbox]', :count => ::Post.all.size)
45
+ end
46
+
47
+ it 'should have one option with a "checked" attribute' do
48
+ output_buffer.should have_tag('form li input[@checked]', :count => 1)
49
+ end
50
+
51
+ it 'should not generate hidden inputs with default value blank' do
52
+ output_buffer.should_not have_tag("form li fieldset ol li label input[@type='hidden'][@value='']")
53
+ end
54
+
55
+ it 'should not render hidden inputs inside the ol' do
56
+ output_buffer.should_not have_tag("form li fieldset ol li input[@type='hidden']")
57
+ end
58
+
59
+ it 'should render one hidden input for each choice outside the ol' do
60
+ output_buffer.should have_tag("form li fieldset > input[@type='hidden']", :count => 1)
61
+ end
62
+
63
+ describe "each choice" do
64
+
65
+ it 'should not give the choice label the .label class' do
66
+ output_buffer.should_not have_tag('li.choice label.label')
67
+ end
68
+
69
+ it 'should not be marked as required' do
70
+ output_buffer.should_not have_tag('li.choice input[@required]')
71
+ end
72
+
73
+ it 'should contain a label for the radio input with a nested input and label text' do
74
+ ::Post.all.each do |post|
75
+ output_buffer.should have_tag('form li fieldset ol li label', /#{post.to_label}/)
76
+ output_buffer.should have_tag("form li fieldset ol li label[@for='author_post_ids_#{post.id}']")
77
+ end
78
+ end
79
+
80
+ it 'should use values as li.class when value_as_class is true' do
81
+ ::Post.all.each do |post|
82
+ output_buffer.should have_tag("form li fieldset ol li.post_#{post.id} label")
83
+ end
84
+ end
85
+
86
+ it 'should have a checkbox input but no hidden field for each post' do
87
+ ::Post.all.each do |post|
88
+ output_buffer.should have_tag("form li fieldset ol li label input#author_post_ids_#{post.id}")
89
+ output_buffer.should have_tag("form li fieldset ol li label input[@name='author[post_ids][]']", :count => 1)
90
+ end
91
+ end
92
+
93
+ it 'should have a hidden field with an empty array value for the collection to allow clearing of all checkboxes' do
94
+ output_buffer.should have_tag("form li fieldset > input[@type=hidden][@name='author[post_ids][]'][@value='']", :count => 1)
95
+ end
96
+
97
+ it 'the hidden field with an empty array value should be followed by the ol' do
98
+ output_buffer.should have_tag("form li fieldset > input[@type=hidden][@name='author[post_ids][]'][@value=''] + ol", :count => 1)
99
+ end
100
+
101
+ it 'should not have a hidden field with an empty string value for the collection' do
102
+ output_buffer.should_not have_tag("form li fieldset > input[@type=hidden][@name='author[post_ids]'][@value='']", :count => 1)
103
+ end
104
+
105
+ it 'should have a checkbox and a hidden field for each post with :hidden_field => true' do
106
+ output_buffer.replace ''
107
+
108
+ concat(semantic_form_for(@fred) do |builder|
109
+ concat(builder.input(:posts, :as => :check_boxes, :hidden_fields => true, :value_as_class => true))
110
+ end)
111
+
112
+ ::Post.all.each do |post|
113
+ output_buffer.should have_tag("form li fieldset ol li label input#author_post_ids_#{post.id}")
114
+ output_buffer.should have_tag("form li fieldset ol li label input[@name='author[post_ids][]']", :count => 2)
115
+ output_buffer.should have_tag('form li fieldset ol li label', /#{post.to_label}/)
116
+ end
117
+
118
+ end
119
+
120
+ it "should mark input as checked if it's the the existing choice" do
121
+ ::Post.all.include?(@fred.posts.first).should be_truthy
122
+ output_buffer.should have_tag("form li fieldset ol li label input[@checked='checked']")
123
+ end
124
+ end
125
+
126
+ describe 'and no object is given' do
127
+ before(:each) do
128
+ output_buffer.replace ''
129
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
130
+ concat(builder.input(:author_id, :as => :check_boxes, :collection => ::Author.all))
131
+ end)
132
+ end
133
+
134
+ it 'should generate a fieldset with legend' do
135
+ output_buffer.should have_tag('form li fieldset legend', /Author/)
136
+ end
137
+
138
+ it 'shold generate an li tag for each item in the collection' do
139
+ output_buffer.should have_tag('form li fieldset ol li input[@type=checkbox]', :count => ::Author.all.size)
140
+ end
141
+
142
+ it 'should generate labels for each item' do
143
+ ::Author.all.each do |author|
144
+ output_buffer.should have_tag('form li fieldset ol li label', /#{author.to_label}/)
145
+ output_buffer.should have_tag("form li fieldset ol li label[@for='project_author_id_#{author.id}']")
146
+ end
147
+ end
148
+
149
+ it 'should generate inputs for each item' do
150
+ ::Author.all.each do |author|
151
+ output_buffer.should have_tag("form li fieldset ol li label input#project_author_id_#{author.id}")
152
+ output_buffer.should have_tag("form li fieldset ol li label input[@type='checkbox']")
153
+ output_buffer.should have_tag("form li fieldset ol li label input[@value='#{author.id}']")
154
+ output_buffer.should have_tag("form li fieldset ol li label input[@name='project[author_id][]']")
155
+ end
156
+ end
157
+
158
+ it 'should html escape the label string' do
159
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
160
+ concat(builder.input(:author_id, :as => :check_boxes, :collection => [["<b>Item 1</b>", 1], ["<b>Item 2</b>", 2]]))
161
+ end)
162
+
163
+ output_buffer.should have_tag('form li fieldset ol li label') do |label|
164
+ label.body.should match /&lt;b&gt;Item [12]&lt;\/b&gt;$/
165
+ end
166
+ end
167
+ end
168
+
169
+ describe 'when :hidden_fields is set to false' do
170
+ before do
171
+ @output_buffer = ''
172
+ mock_everything
173
+
174
+ concat(semantic_form_for(@fred) do |builder|
175
+ concat(builder.input(:posts, :as => :check_boxes, :value_as_class => true, :hidden_fields => false))
176
+ end)
177
+ end
178
+
179
+ it 'should have a checkbox input for each post' do
180
+ ::Post.all.each do |post|
181
+ output_buffer.should have_tag("form li fieldset ol li label input#author_post_ids_#{post.id}")
182
+ output_buffer.should have_tag("form li fieldset ol li label input[@name='author[post_ids][]']", :count => ::Post.all.length)
183
+ end
184
+ end
185
+
186
+ it "should mark input as checked if it's the the existing choice" do
187
+ ::Post.all.include?(@fred.posts.first).should be_truthy
188
+ output_buffer.should have_tag("form li fieldset ol li label input[@checked='checked']")
189
+ end
190
+
191
+ it 'should not generate empty hidden inputs' do
192
+ output_buffer.should_not have_tag("form li fieldset ol li label input[@type='hidden'][@value='']", :count => ::Post.all.length)
193
+ end
194
+ end
195
+
196
+ describe 'when :disabled is set' do
197
+ before do
198
+ @output_buffer = ''
199
+ end
200
+
201
+ describe "no disabled items" do
202
+ before do
203
+ @new_post.stub(:author_ids).and_return(nil)
204
+
205
+ concat(semantic_form_for(@new_post) do |builder|
206
+ concat(builder.input(:authors, :as => :check_boxes, :disabled => nil))
207
+ end)
208
+ end
209
+
210
+ it 'should not have any disabled item(s)' do
211
+ output_buffer.should_not have_tag("form li fieldset ol li label input[@disabled='disabled']")
212
+ end
213
+ end
214
+
215
+ describe "single disabled item" do
216
+ before do
217
+ @new_post.stub(:author_ids).and_return(nil)
218
+
219
+ concat(semantic_form_for(@new_post) do |builder|
220
+ concat(builder.input(:authors, :as => :check_boxes, :disabled => @fred.id))
221
+ end)
222
+ end
223
+
224
+ it "should have one item disabled; the specified one" do
225
+ output_buffer.should have_tag("form li fieldset ol li label input[@disabled='disabled']", :count => 1)
226
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_ids_#{@fred.id}']", /fred/i)
227
+ output_buffer.should have_tag("form li fieldset ol li label input[@disabled='disabled'][@value='#{@fred.id}']")
228
+ end
229
+ end
230
+
231
+ describe "multiple disabled items" do
232
+ before do
233
+ @new_post.stub(:author_ids).and_return(nil)
234
+
235
+ concat(semantic_form_for(@new_post) do |builder|
236
+ concat(builder.input(:authors, :as => :check_boxes, :disabled => [@bob.id, @fred.id]))
237
+ end)
238
+ end
239
+
240
+ it "should have multiple items disabled; the specified ones" do
241
+ output_buffer.should have_tag("form li fieldset ol li label input[@disabled='disabled']", :count => 2)
242
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_ids_#{@bob.id}']", /bob/i)
243
+ output_buffer.should have_tag("form li fieldset ol li label input[@disabled='disabled'][@value='#{@bob.id}']")
244
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_ids_#{@fred.id}']", /fred/i)
245
+ output_buffer.should have_tag("form li fieldset ol li label input[@disabled='disabled'][@value='#{@fred.id}']")
246
+ end
247
+ end
248
+
249
+ end
250
+
251
+ describe "with i18n of the legend label" do
252
+
253
+ before do
254
+ ::I18n.backend.store_translations :en, :formtastic => { :labels => { :post => { :authors => "Translated!" }}}
255
+ with_config :i18n_lookups_by_default, true do
256
+ @new_post.stub(:author_ids).and_return(nil)
257
+ concat(semantic_form_for(@new_post) do |builder|
258
+ concat(builder.input(:authors, :as => :check_boxes))
259
+ end)
260
+ end
261
+ end
262
+
263
+ after do
264
+ ::I18n.backend.reload!
265
+ end
266
+
267
+ it "should do foo" do
268
+ output_buffer.should have_tag("legend.label label", /Translated/)
269
+ end
270
+
271
+ end
272
+
273
+ describe "when :label option is set" do
274
+ before do
275
+ @new_post.stub(:author_ids).and_return(nil)
276
+ concat(semantic_form_for(@new_post) do |builder|
277
+ concat(builder.input(:authors, :as => :check_boxes, :label => 'The authors'))
278
+ end)
279
+ end
280
+
281
+ it "should output the correct label title" do
282
+ output_buffer.should have_tag("legend.label label", /The authors/)
283
+ end
284
+ end
285
+
286
+ describe "when :label option is false" do
287
+ before do
288
+ @output_buffer = ''
289
+ @new_post.stub(:author_ids).and_return(nil)
290
+ concat(semantic_form_for(@new_post) do |builder|
291
+ concat(builder.input(:authors, :as => :check_boxes, :label => false))
292
+ end)
293
+ end
294
+
295
+ it "should not output the legend" do
296
+ output_buffer.should_not have_tag("legend.label")
297
+ end
298
+
299
+ it "should not cause escaped HTML" do
300
+ output_buffer.should_not include("&gt;")
301
+ end
302
+
303
+ end
304
+
305
+ describe "when :required option is true" do
306
+ before do
307
+ @new_post.stub(:author_ids).and_return(nil)
308
+ concat(semantic_form_for(@new_post) do |builder|
309
+ concat(builder.input(:authors, :as => :check_boxes, :required => true))
310
+ end)
311
+ end
312
+
313
+ it "should output the correct label title" do
314
+ output_buffer.should have_tag("legend.label label abbr")
315
+ end
316
+ end
317
+ end
318
+
319
+ describe 'for a enum column' do
320
+ before do
321
+ @new_post.stub(:status) { 'inactive' }
322
+ statuses = ActiveSupport::HashWithIndifferentAccess.new("active"=>0, "inactive"=>1)
323
+ @new_post.class.stub(:statuses) { statuses }
324
+ @new_post.stub(:defined_enums) { { "status" => statuses } }
325
+ end
326
+
327
+ it 'should have a select inside the wrapper' do
328
+ expect {
329
+ concat(semantic_form_for(@new_post) do |builder|
330
+ concat(builder.input(:status, :as => :check_boxes))
331
+ end)
332
+ }.to raise_error(Formtastic::UnsupportedEnumCollection)
333
+ end
334
+ end
335
+
336
+ describe 'for a has_and_belongs_to_many association' do
337
+
338
+ before do
339
+ @output_buffer = ''
340
+ mock_everything
341
+
342
+ concat(semantic_form_for(@freds_post) do |builder|
343
+ concat(builder.input(:authors, :as => :check_boxes))
344
+ end)
345
+ end
346
+
347
+ it 'should render checkboxes' do
348
+ # I'm aware these two lines test the same thing
349
+ output_buffer.should have_tag('input[type="checkbox"]', :count => 2)
350
+ output_buffer.should have_tag('input[type="checkbox"]', :count => ::Author.all.size)
351
+ end
352
+
353
+ it 'should only select checkboxes that are present in the association' do
354
+ # I'm aware these two lines test the same thing
355
+ output_buffer.should have_tag('input[checked="checked"]', :count => 1)
356
+ output_buffer.should have_tag('input[checked="checked"]', :count => @freds_post.authors.size)
357
+ end
358
+
359
+ end
360
+
361
+ describe ':collection for a has_and_belongs_to_many association' do
362
+
363
+ before do
364
+ @output_buffer = ''
365
+ mock_everything
366
+
367
+ concat(semantic_form_for(@freds_post) do |builder|
368
+ concat(builder.input(:authors, as: :check_boxes, collection: Author.all))
369
+ end)
370
+ end
371
+
372
+ it 'should render checkboxes' do
373
+ # I'm aware these two lines test the same thing
374
+ output_buffer.should have_tag('input[type="checkbox"]', :count => 2)
375
+ output_buffer.should have_tag('input[type="checkbox"]', :count => ::Author.all.size)
376
+ end
377
+
378
+ it 'should only select checkboxes that are present in the association' do
379
+ # I'm aware these two lines test the same thing
380
+ output_buffer.should have_tag('input[checked="checked"]', :count => 1)
381
+ output_buffer.should have_tag('input[checked="checked"]', :count => @freds_post.authors.size)
382
+ end
383
+
384
+ end
385
+
386
+ describe 'for an association when a :collection is provided' do
387
+ describe 'it should use the specified :member_value option' do
388
+ before do
389
+ @output_buffer = ''
390
+ mock_everything
391
+ end
392
+
393
+ it 'to set the right input value' do
394
+ item = double('item')
395
+ item.should_not_receive(:id)
396
+ item.stub(:custom_value).and_return('custom_value')
397
+ item.should_receive(:custom_value).exactly(3).times
398
+ @new_post.author.should_receive(:custom_value).exactly(1).times
399
+
400
+ with_deprecation_silenced do
401
+ concat(semantic_form_for(@new_post) do |builder|
402
+ concat(builder.input(:author, :as => :check_boxes, :member_value => :custom_value, :collection => [item, item, item]))
403
+ end)
404
+ end
405
+ output_buffer.should have_tag('input[@type=checkbox][@value="custom_value"]', :count => 3)
406
+ end
407
+ end
408
+ end
409
+
410
+ describe 'when :collection is provided as an array of arrays' do
411
+ before do
412
+ @output_buffer = ''
413
+ mock_everything
414
+ @fred.stub(:genres) { ['fiction', 'biography'] }
415
+
416
+ concat(semantic_form_for(@fred) do |builder|
417
+ concat(builder.input(:genres, :as => :check_boxes, :collection => [['Fiction', 'fiction'], ['Non-fiction', 'non_fiction'], ['Biography', 'biography']]))
418
+ end)
419
+ end
420
+
421
+ it 'should check the correct checkboxes' do
422
+ output_buffer.should have_tag("form li fieldset ol li label input[@value='fiction'][@checked='checked']")
423
+ output_buffer.should have_tag("form li fieldset ol li label input[@value='biography'][@checked='checked']")
424
+ end
425
+ end
426
+
427
+ describe 'when :collection is a set' do
428
+ before do
429
+ @output_buffer = ''
430
+ mock_everything
431
+ @fred.stub(:roles) { Set.new([:reviewer, :admin]) }
432
+
433
+ concat(semantic_form_for(@fred) do |builder|
434
+ concat(builder.input(:roles, :as => :check_boxes, :collection => [['User', :user], ['Reviewer', :reviewer], ['Administrator', :admin]]))
435
+ end)
436
+ end
437
+
438
+ it 'should check the correct checkboxes' do
439
+ output_buffer.should have_tag("form li fieldset ol li label input[@value='user']")
440
+ output_buffer.should have_tag("form li fieldset ol li label input[@value='admin'][@checked='checked']")
441
+ output_buffer.should have_tag("form li fieldset ol li label input[@value='reviewer'][@checked='checked']")
442
+ end
443
+ end
444
+
445
+ describe "when namespace is provided" do
446
+
447
+ before do
448
+ @output_buffer = ''
449
+ mock_everything
450
+
451
+ concat(semantic_form_for(@fred, :namespace => "context2") do |builder|
452
+ concat(builder.input(:posts, :as => :check_boxes))
453
+ end)
454
+ end
455
+
456
+ it "should have a label for #context2_author_post_ids_19" do
457
+ output_buffer.should have_tag("form li label[@for='context2_author_post_ids_19']")
458
+ end
459
+
460
+ it_should_have_input_with_id('context2_author_post_ids_19')
461
+ it_should_have_input_wrapper_with_id("context2_author_posts_input")
462
+ end
463
+
464
+ describe "when index is provided" do
465
+
466
+ before do
467
+ @output_buffer = ''
468
+ mock_everything
469
+
470
+ concat(semantic_form_for(@fred) do |builder|
471
+ concat(builder.fields_for(@fred.posts.first, :index => 3) do |author|
472
+ concat(author.input(:authors, :as => :check_boxes))
473
+ end)
474
+ end)
475
+ end
476
+
477
+ it 'should index the id of the wrapper' do
478
+ output_buffer.should have_tag("li#author_post_3_authors_input")
479
+ end
480
+
481
+ it 'should index the id of the input tag' do
482
+ output_buffer.should have_tag("input#author_post_3_author_ids_42")
483
+ end
484
+
485
+ it 'should index the name of the checkbox input' do
486
+ output_buffer.should have_tag("input[@type='checkbox'][@name='author[post][3][author_ids][]']")
487
+ end
488
+
489
+ end
490
+
491
+
492
+ describe "when collection is an array" do
493
+ before do
494
+ @output_buffer = ''
495
+ @_collection = [["First", 1], ["Second", 2]]
496
+ mock_everything
497
+
498
+ concat(semantic_form_for(@fred) do |builder|
499
+ concat(builder.input(:posts, :as => :check_boxes, :collection => @_collection))
500
+ end)
501
+ end
502
+
503
+ it "should use array items for labels and values" do
504
+ @_collection.each do |post|
505
+ output_buffer.should have_tag('form li fieldset ol li label', /#{post.first}/)
506
+ output_buffer.should have_tag("form li fieldset ol li label[@for='author_post_ids_#{post.last}']")
507
+ end
508
+ end
509
+
510
+ it "should not check any items" do
511
+ output_buffer.should have_tag('form li input[@checked]', :count => 0)
512
+ end
513
+
514
+ describe "and the attribute has values" do
515
+ before do
516
+ @fred.stub(:posts) { [1] }
517
+
518
+ concat(semantic_form_for(@fred) do |builder|
519
+ concat(builder.input(:posts, :as => :check_boxes, :collection => @_collection))
520
+ end)
521
+ end
522
+
523
+ it "should check the appropriate items" do
524
+ output_buffer.should have_tag("form li input[@value='1'][@checked]")
525
+ end
526
+ end
527
+
528
+ describe "and the collection includes html options" do
529
+ before do
530
+ @_collection = [["First", 1, {'data-test' => 'test-data'}], ["Second", 2, {'data-test2' => 'test-data2'}]]
531
+
532
+ concat(semantic_form_for(@fred) do |builder|
533
+ concat(builder.input(:posts, :as => :check_boxes, :collection => @_collection))
534
+ end)
535
+ end
536
+
537
+ it "should have injected the html attributes" do
538
+ @_collection.each do |v|
539
+ output_buffer.should have_tag("form li input[@value='#{v[1]}'][@#{v[2].keys[0]}='#{v[2].values[0]}']")
540
+ end
541
+ end
542
+ end
543
+ end
544
+
545
+ end
546
+