ehoch_simple_form 2.0.2.dev

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 (97) hide show
  1. data/CHANGELOG.md +257 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +797 -0
  4. data/lib/generators/simple_form/USAGE +3 -0
  5. data/lib/generators/simple_form/install_generator.rb +32 -0
  6. data/lib/generators/simple_form/templates/README +12 -0
  7. data/lib/generators/simple_form/templates/_form.html.erb +13 -0
  8. data/lib/generators/simple_form/templates/_form.html.haml +10 -0
  9. data/lib/generators/simple_form/templates/_form.html.slim +10 -0
  10. data/lib/generators/simple_form/templates/config/initializers/simple_form.rb.tt +181 -0
  11. data/lib/generators/simple_form/templates/config/locales/simple_form.en.yml +26 -0
  12. data/lib/simple_form.rb +215 -0
  13. data/lib/simple_form/action_view_extensions/builder.rb +338 -0
  14. data/lib/simple_form/action_view_extensions/form_helper.rb +74 -0
  15. data/lib/simple_form/components.rb +20 -0
  16. data/lib/simple_form/components/errors.rb +35 -0
  17. data/lib/simple_form/components/hints.rb +18 -0
  18. data/lib/simple_form/components/html5.rb +26 -0
  19. data/lib/simple_form/components/label_input.rb +15 -0
  20. data/lib/simple_form/components/labels.rb +79 -0
  21. data/lib/simple_form/components/maxlength.rb +41 -0
  22. data/lib/simple_form/components/min_max.rb +50 -0
  23. data/lib/simple_form/components/pattern.rb +34 -0
  24. data/lib/simple_form/components/placeholders.rb +16 -0
  25. data/lib/simple_form/components/readonly.rb +22 -0
  26. data/lib/simple_form/core_ext/hash.rb +16 -0
  27. data/lib/simple_form/error_notification.rb +48 -0
  28. data/lib/simple_form/form_builder.rb +472 -0
  29. data/lib/simple_form/helpers.rb +12 -0
  30. data/lib/simple_form/helpers/autofocus.rb +11 -0
  31. data/lib/simple_form/helpers/disabled.rb +15 -0
  32. data/lib/simple_form/helpers/readonly.rb +15 -0
  33. data/lib/simple_form/helpers/required.rb +35 -0
  34. data/lib/simple_form/helpers/validators.rb +44 -0
  35. data/lib/simple_form/i18n_cache.rb +22 -0
  36. data/lib/simple_form/inputs.rb +21 -0
  37. data/lib/simple_form/inputs/base.rb +162 -0
  38. data/lib/simple_form/inputs/block_input.rb +14 -0
  39. data/lib/simple_form/inputs/boolean_input.rb +64 -0
  40. data/lib/simple_form/inputs/collection_check_boxes_input.rb +21 -0
  41. data/lib/simple_form/inputs/collection_input.rb +101 -0
  42. data/lib/simple_form/inputs/collection_radio_buttons_input.rb +63 -0
  43. data/lib/simple_form/inputs/collection_select_input.rb +14 -0
  44. data/lib/simple_form/inputs/date_time_input.rb +28 -0
  45. data/lib/simple_form/inputs/file_input.rb +9 -0
  46. data/lib/simple_form/inputs/grouped_collection_select_input.rb +41 -0
  47. data/lib/simple_form/inputs/hidden_input.rb +17 -0
  48. data/lib/simple_form/inputs/numeric_input.rb +24 -0
  49. data/lib/simple_form/inputs/password_input.rb +12 -0
  50. data/lib/simple_form/inputs/priority_input.rb +24 -0
  51. data/lib/simple_form/inputs/range_input.rb +14 -0
  52. data/lib/simple_form/inputs/string_input.rb +23 -0
  53. data/lib/simple_form/inputs/text_input.rb +11 -0
  54. data/lib/simple_form/map_type.rb +16 -0
  55. data/lib/simple_form/version.rb +3 -0
  56. data/lib/simple_form/wrappers.rb +8 -0
  57. data/lib/simple_form/wrappers/builder.rb +103 -0
  58. data/lib/simple_form/wrappers/many.rb +69 -0
  59. data/lib/simple_form/wrappers/root.rb +34 -0
  60. data/lib/simple_form/wrappers/single.rb +18 -0
  61. data/test/action_view_extensions/builder_test.rb +577 -0
  62. data/test/action_view_extensions/form_helper_test.rb +104 -0
  63. data/test/components/label_test.rb +310 -0
  64. data/test/form_builder/association_test.rb +177 -0
  65. data/test/form_builder/button_test.rb +47 -0
  66. data/test/form_builder/error_notification_test.rb +79 -0
  67. data/test/form_builder/error_test.rb +121 -0
  68. data/test/form_builder/general_test.rb +356 -0
  69. data/test/form_builder/hint_test.rb +139 -0
  70. data/test/form_builder/input_field_test.rb +63 -0
  71. data/test/form_builder/label_test.rb +71 -0
  72. data/test/form_builder/wrapper_test.rb +149 -0
  73. data/test/generators/simple_form_generator_test.rb +32 -0
  74. data/test/inputs/boolean_input_test.rb +108 -0
  75. data/test/inputs/collection_check_boxes_input_test.rb +224 -0
  76. data/test/inputs/collection_radio_buttons_input_test.rb +326 -0
  77. data/test/inputs/collection_select_input_test.rb +241 -0
  78. data/test/inputs/datetime_input_test.rb +99 -0
  79. data/test/inputs/disabled_test.rb +38 -0
  80. data/test/inputs/discovery_test.rb +61 -0
  81. data/test/inputs/file_input_test.rb +16 -0
  82. data/test/inputs/general_test.rb +69 -0
  83. data/test/inputs/grouped_collection_select_input_test.rb +118 -0
  84. data/test/inputs/hidden_input_test.rb +30 -0
  85. data/test/inputs/numeric_input_test.rb +173 -0
  86. data/test/inputs/priority_input_test.rb +43 -0
  87. data/test/inputs/readonly_test.rb +61 -0
  88. data/test/inputs/required_test.rb +113 -0
  89. data/test/inputs/string_input_test.rb +140 -0
  90. data/test/inputs/text_input_test.rb +24 -0
  91. data/test/simple_form_test.rb +9 -0
  92. data/test/support/discovery_inputs.rb +21 -0
  93. data/test/support/misc_helpers.rb +102 -0
  94. data/test/support/mock_controller.rb +24 -0
  95. data/test/support/models.rb +210 -0
  96. data/test/test_helper.rb +90 -0
  97. metadata +210 -0
@@ -0,0 +1,69 @@
1
+ module SimpleForm
2
+ module Wrappers
3
+ # A wrapper is an object that holds several components and render them.
4
+ # A component may either be a symbol or any object that responds to `render`.
5
+ # This API allows inputs/components to be easily wrapped, removing the
6
+ # need to modify the code only to wrap input in an extra tag.
7
+ #
8
+ # `Many` represents a wrapper around several components at the same time.
9
+ # It may optionally receive a namespace, allowing it to be configured
10
+ # on demand on input generation.
11
+ class Many
12
+ attr_reader :namespace, :defaults, :components
13
+ alias :to_sym :namespace
14
+
15
+ def initialize(namespace, components, defaults={})
16
+ @namespace = namespace
17
+ @components = components
18
+ @defaults = defaults
19
+ @defaults[:tag] = :div unless @defaults.key?(:tag)
20
+ @defaults[:class] = Array.wrap(@defaults[:class])
21
+ end
22
+
23
+ def render(input)
24
+ content = "".html_safe
25
+ options = input.options
26
+
27
+ components.each do |component|
28
+ next if options[component] == false
29
+ rendered = component.respond_to?(:render) ? component.render(input) : input.send(component)
30
+ content.safe_concat rendered.to_s if rendered
31
+ end
32
+
33
+ wrap(input, options, content)
34
+ end
35
+
36
+ def find(name)
37
+ return self if namespace == name
38
+
39
+ @components.each do |c|
40
+ if c.is_a?(Symbol)
41
+ return nil if c == namespace
42
+ elsif value = c.find(name)
43
+ return value
44
+ end
45
+ end
46
+
47
+ nil
48
+ end
49
+
50
+ private
51
+
52
+ def wrap(input, options, content)
53
+ return content if options[namespace] == false
54
+
55
+ tag = (namespace && options[:"#{namespace}_tag"]) || @defaults[:tag]
56
+ return content unless tag
57
+
58
+ klass = html_classes(input, options)
59
+ opts = options[:"#{namespace}_html"] || {}
60
+ opts[:class] = (klass << opts[:class]).join(' ').strip unless klass.empty?
61
+ input.template.content_tag(tag, content, opts)
62
+ end
63
+
64
+ def html_classes(input, options)
65
+ @defaults[:class].dup
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,34 @@
1
+ module SimpleForm
2
+ module Wrappers
3
+ # `Root` is the root wrapper for all components. It is special cased to
4
+ # always have a namespace and to add special html classes.
5
+ class Root < Many
6
+ attr_reader :options
7
+
8
+ def initialize(*args)
9
+ super(:wrapper, *args)
10
+ @options = @defaults.except(:tag, :class, :error_class, :hint_class)
11
+ end
12
+
13
+ def render(input)
14
+ input.options.reverse_merge!(@options)
15
+ super
16
+ end
17
+
18
+ # Provide a fallback if name cannot be found.
19
+ def find(name)
20
+ super || SimpleForm::Wrappers::Many.new(name, [name])
21
+ end
22
+
23
+ private
24
+
25
+ def html_classes(input, options)
26
+ css = options[:wrapper_class] ? Array.wrap(options[:wrapper_class]) : @defaults[:class]
27
+ css += SimpleForm.additional_classes_for(:wrapper) { input.html_classes }
28
+ css << (options[:wrapper_error_class] || @defaults[:error_class]) if input.has_errors?
29
+ css << (options[:wrapper_hint_class] || @defaults[:hint_class]) if input.has_hint?
30
+ css
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,18 @@
1
+ module SimpleForm
2
+ module Wrappers
3
+ # `Single` is an optimization for a wrapper that has only one component.
4
+ class Single < Many
5
+ def initialize(name, options={})
6
+ super(name, [name], options)
7
+ end
8
+
9
+ def render(input)
10
+ options = input.options
11
+ if options[namespace] != false
12
+ content = input.send(namespace)
13
+ wrap(input, options, content) if content
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,577 @@
1
+ require 'test_helper'
2
+
3
+ class BuilderTest < ActionView::TestCase
4
+ def with_custom_form_for(object, *args, &block)
5
+ with_concat_custom_form_for(object) do |f|
6
+ assert f.instance_of?(CustomFormBuilder)
7
+ yield f
8
+ end
9
+ end
10
+
11
+ def with_collection_radio_buttons(object, attribute, collection, value_method, text_method, options={}, html_options={}, &block)
12
+ with_concat_form_for(object) do |f|
13
+ f.collection_radio_buttons attribute, collection, value_method, text_method, options, html_options, &block
14
+ end
15
+ end
16
+
17
+ def with_collection_check_boxes(object, attribute, collection, value_method, text_method, options={}, html_options={}, &block)
18
+ with_concat_form_for(object) do |f|
19
+ f.collection_check_boxes attribute, collection, value_method, text_method, options, html_options, &block
20
+ end
21
+ end
22
+
23
+ # COLLECTION RADIO
24
+ test 'collection radio accepts a collection and generate inputs from value method' do
25
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
26
+
27
+ assert_select 'form input[type=radio][value=true]#user_active_true'
28
+ assert_select 'form input[type=radio][value=false]#user_active_false'
29
+ end
30
+
31
+ test 'collection radio accepts a collection and generate inputs from label method' do
32
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
33
+
34
+ assert_select 'form label.collection_radio_buttons[for=user_active_true]', 'true'
35
+ assert_select 'form label.collection_radio_buttons[for=user_active_false]', 'false'
36
+ end
37
+
38
+ test 'collection radio handles camelized collection values for labels correctly' do
39
+ with_collection_radio_buttons @user, :active, ['Yes', 'No'], :to_s, :to_s
40
+
41
+ assert_select 'form label.collection_radio_buttons[for=user_active_yes]', 'Yes'
42
+ assert_select 'form label.collection_radio_buttons[for=user_active_no]', 'No'
43
+ end
44
+
45
+ test 'collection radio should sanitize collection values for labels correctly' do
46
+ with_collection_radio_buttons @user, :name, ['$0.99', '$1.99'], :to_s, :to_s
47
+ assert_select 'label.collection_radio_buttons[for=user_name_099]', '$0.99'
48
+ assert_select 'label.collection_radio_buttons[for=user_name_199]', '$1.99'
49
+ end
50
+
51
+ test 'collection radio checks the correct value to local variables' do
52
+ user = User.new
53
+ user.active = false
54
+ with_collection_radio_buttons user, :active, [true, false], :to_s, :to_s
55
+
56
+ assert_select 'form input[type=radio][value=true]'
57
+ assert_select 'form input[type=radio][value=false][checked=checked]'
58
+ end
59
+
60
+ test 'collection radio accepts checked item' do
61
+ with_collection_radio_buttons @user, :active, [[1, true], [0, false]], :last, :first, :checked => true
62
+
63
+ assert_select 'form input[type=radio][value=true][checked=checked]'
64
+ assert_no_select 'form input[type=radio][value=false][checked=checked]'
65
+ end
66
+
67
+ test 'collection radio accepts checked item which has a value of false' do
68
+ with_collection_radio_buttons @user, :active, [[1, true], [0, false]], :last, :first, :checked => false
69
+ assert_no_select 'form input[type=radio][value=true][checked=checked]'
70
+ assert_select 'form input[type=radio][value=false][checked=checked]'
71
+ end
72
+
73
+ test 'collection radio accepts multiple disabled items' do
74
+ collection = [[1, true], [0, false], [2, 'other']]
75
+ with_collection_radio_buttons @user, :active, collection, :last, :first, :disabled => [true, false]
76
+
77
+ assert_select 'form input[type=radio][value=true][disabled=disabled]'
78
+ assert_select 'form input[type=radio][value=false][disabled=disabled]'
79
+ assert_no_select 'form input[type=radio][value=other][disabled=disabled]'
80
+ end
81
+
82
+ test 'collection radio accepts single disable item' do
83
+ collection = [[1, true], [0, false]]
84
+ with_collection_radio_buttons @user, :active, collection, :last, :first, :disabled => true
85
+
86
+ assert_select 'form input[type=radio][value=true][disabled=disabled]'
87
+ assert_no_select 'form input[type=radio][value=false][disabled=disabled]'
88
+ end
89
+
90
+ test 'collection radio accepts html options as input' do
91
+ collection = [[1, true], [0, false]]
92
+ with_collection_radio_buttons @user, :active, collection, :last, :first, {}, :class => 'special-radio'
93
+
94
+ assert_select 'form input[type=radio][value=true].special-radio#user_active_true'
95
+ assert_select 'form input[type=radio][value=false].special-radio#user_active_false'
96
+ end
97
+
98
+ test 'collection radio wraps the collection in the given collection wrapper tag' do
99
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => :ul
100
+
101
+ assert_select 'form ul input[type=radio]', :count => 2
102
+ end
103
+
104
+ test 'collection radio does not render any wrapper tag by default' do
105
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
106
+
107
+ assert_select 'form input[type=radio]', :count => 2
108
+ assert_no_select 'form ul'
109
+ end
110
+
111
+ test 'collection radio does not wrap the collection when given falsy values' do
112
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => false
113
+
114
+ assert_select 'form input[type=radio]', :count => 2
115
+ assert_no_select 'form ul'
116
+ end
117
+
118
+ test 'collection radio uses the given class for collection wrapper tag' do
119
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
120
+ :collection_wrapper_tag => :ul, :collection_wrapper_class => "items-list"
121
+
122
+ assert_select 'form ul.items-list input[type=radio]', :count => 2
123
+ end
124
+
125
+ test 'collection radio uses no class for collection wrapper tag when no wrapper tag is given' do
126
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
127
+ :collection_wrapper_class => "items-list"
128
+
129
+ assert_select 'form input[type=radio]', :count => 2
130
+ assert_no_select 'form ul'
131
+ assert_no_select '.items-list'
132
+ end
133
+
134
+ test 'collection radio uses no class for collection wrapper tag by default' do
135
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => :ul
136
+
137
+ assert_select 'form ul'
138
+ assert_no_select 'form ul[class]'
139
+ end
140
+
141
+ test 'collection radio wrap items in a span tag by default' do
142
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
143
+
144
+ assert_select 'form span input[type=radio][value=true]#user_active_true + label'
145
+ assert_select 'form span input[type=radio][value=false]#user_active_false + label'
146
+ end
147
+
148
+ test 'collection radio wraps each item in the given item wrapper tag' do
149
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, :item_wrapper_tag => :li
150
+
151
+ assert_select 'form li input[type=radio]', :count => 2
152
+ end
153
+
154
+ test 'collection radio does not wrap each item when given explicitly falsy value' do
155
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, :item_wrapper_tag => false
156
+
157
+ assert_select 'form input[type=radio]'
158
+ assert_no_select 'form span input[type=radio]'
159
+ end
160
+
161
+ test 'collection radio uses the given class for item wrapper tag' do
162
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
163
+ :item_wrapper_tag => :li, :item_wrapper_class => "inline"
164
+
165
+ assert_select "form li.inline input[type=radio]", :count => 2
166
+ end
167
+
168
+ test 'collection radio uses no class for item wrapper tag when no wrapper tag is given' do
169
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
170
+ :item_wrapper_tag => nil, :item_wrapper_class => "inline"
171
+
172
+ assert_select 'form input[type=radio]', :count => 2
173
+ assert_no_select 'form li'
174
+ assert_no_select '.inline'
175
+ end
176
+
177
+ test 'collection radio uses no class for item wrapper tag by default' do
178
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
179
+ :item_wrapper_tag => :li
180
+
181
+ assert_select "form li", :count => 2
182
+ assert_no_select "form li[class]"
183
+ end
184
+
185
+ test 'collection radio does not wrap input inside the label' do
186
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
187
+
188
+ assert_select 'form input[type=radio] + label'
189
+ assert_no_select 'form label input'
190
+ end
191
+
192
+ test 'collection radio accepts a block to render the label as radio button wrapper' do
193
+ with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b|
194
+ b.label { b.radio_button }
195
+ end
196
+
197
+ assert_select 'label[for=user_active_true] > input#user_active_true[type=radio]'
198
+ assert_select 'label[for=user_active_false] > input#user_active_false[type=radio]'
199
+ end
200
+
201
+ test 'collection radio accepts a block to change the order of label and radio button' do
202
+ with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b|
203
+ b.label + b.radio_button
204
+ end
205
+
206
+ assert_select 'label[for=user_active_true] + input#user_active_true[type=radio]'
207
+ assert_select 'label[for=user_active_false] + input#user_active_false[type=radio]'
208
+ end
209
+
210
+ test 'collection radio with block helpers accept extra html options' do
211
+ with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b|
212
+ b.label(:class => "radio_button") + b.radio_button(:class => "radio_button")
213
+ end
214
+
215
+ assert_select 'label.radio_button[for=user_active_true] + input#user_active_true.radio_button[type=radio]'
216
+ assert_select 'label.radio_button[for=user_active_false] + input#user_active_false.radio_button[type=radio]'
217
+ end
218
+
219
+ test 'collection radio with block helpers allows access to current text and value' do
220
+ with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b|
221
+ b.label(:"data-value" => b.value) { b.radio_button + b.text }
222
+ end
223
+
224
+ assert_select 'label[for=user_active_true][data-value=true]', 'true' do
225
+ assert_select 'input#user_active_true[type=radio]'
226
+ end
227
+ assert_select 'label[for=user_active_false][data-value=false]', 'false' do
228
+ assert_select 'input#user_active_false[type=radio]'
229
+ end
230
+ end
231
+
232
+ test 'collection radio with block helpers allows access to the current object item in the collection to access extra properties' do
233
+ with_collection_radio_buttons :user, :active, [true, false], :to_s, :to_s do |b|
234
+ b.label(:class => b.object) { b.radio_button + b.text }
235
+ end
236
+
237
+ assert_select 'label.true[for=user_active_true]', 'true' do
238
+ assert_select 'input#user_active_true[type=radio]'
239
+ end
240
+ assert_select 'label.false[for=user_active_false]', 'false' do
241
+ assert_select 'input#user_active_false[type=radio]'
242
+ end
243
+ end
244
+
245
+ test 'collection_radio helper is deprecated in favor of collection_radio_buttons' do
246
+ assert_deprecated "[SIMPLE_FORM] The `collection_radio` helper is deprecated, " \
247
+ "please use `collection_radio_buttons` instead" do
248
+ with_concat_form_for(@user) do |f|
249
+ f.collection_radio :active, [true, false], :to_s, :to_s
250
+ end
251
+ end
252
+
253
+ assert_select 'input[type=radio][value=true]'
254
+ assert_select 'input[type=radio][value=false]'
255
+ end
256
+
257
+ # COLLECTION CHECK BOX
258
+ test 'collection check box accepts a collection and generate a serie of checkboxes for value method' do
259
+ collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
260
+ with_collection_check_boxes @user, :tag_ids, collection, :id, :name
261
+
262
+ assert_select 'form input#user_tag_ids_1[type=checkbox][value=1]'
263
+ assert_select 'form input#user_tag_ids_2[type=checkbox][value=2]'
264
+ end
265
+
266
+ test 'collection check box generates only one hidden field for the entire collection, to ensure something will be sent back to the server when posting an empty collection' do
267
+ collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
268
+ with_collection_check_boxes @user, :tag_ids, collection, :id, :name
269
+
270
+ assert_select "form input[type=hidden][name='user[tag_ids][]'][value=]", :count => 1
271
+ end
272
+
273
+ test 'collection check box accepts a collection and generate a serie of checkboxes with labels for label method' do
274
+ collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
275
+ with_collection_check_boxes @user, :tag_ids, collection, :id, :name
276
+
277
+ assert_select 'form label.collection_check_boxes[for=user_tag_ids_1]', 'Tag 1'
278
+ assert_select 'form label.collection_check_boxes[for=user_tag_ids_2]', 'Tag 2'
279
+ end
280
+
281
+ test 'collection check box handles camelized collection values for labels correctly' do
282
+ with_collection_check_boxes @user, :active, ['Yes', 'No'], :to_s, :to_s
283
+
284
+ assert_select 'form label.collection_check_boxes[for=user_active_yes]', 'Yes'
285
+ assert_select 'form label.collection_check_boxes[for=user_active_no]', 'No'
286
+ end
287
+
288
+ test 'collection check box should sanitize collection values for labels correctly' do
289
+ with_collection_check_boxes @user, :name, ['$0.99', '$1.99'], :to_s, :to_s
290
+ assert_select 'label.collection_check_boxes[for=user_name_099]', '$0.99'
291
+ assert_select 'label.collection_check_boxes[for=user_name_199]', '$1.99'
292
+ end
293
+
294
+ test 'collection check box checks the correct value to local variables' do
295
+ user = User.new
296
+ user.tag_ids = [1, 3]
297
+ collection = (1..3).map{|i| [i, "Tag #{i}"] }
298
+ with_collection_check_boxes user, :tag_ids, collection, :first, :last
299
+
300
+ assert_select 'form input[type=checkbox][value=1][checked=checked]'
301
+ assert_select 'form input[type=checkbox][value=3][checked=checked]'
302
+ assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
303
+ end
304
+
305
+
306
+ test 'collection check box accepts selected values as :checked option' do
307
+ collection = (1..3).map{|i| [i, "Tag #{i}"] }
308
+ with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :checked => [1, 3]
309
+
310
+ assert_select 'form input[type=checkbox][value=1][checked=checked]'
311
+ assert_select 'form input[type=checkbox][value=3][checked=checked]'
312
+ assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
313
+ end
314
+
315
+ test 'collection check box accepts a single checked value' do
316
+ collection = (1..3).map{|i| [i, "Tag #{i}"] }
317
+ with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :checked => 3
318
+
319
+ assert_select 'form input[type=checkbox][value=3][checked=checked]'
320
+ assert_no_select 'form input[type=checkbox][value=1][checked=checked]'
321
+ assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
322
+ end
323
+
324
+ test 'collection check box accepts selected values as :checked option and override the model values' do
325
+ collection = (1..3).map{|i| [i, "Tag #{i}"] }
326
+ @user.tag_ids = [2]
327
+ with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :checked => [1, 3]
328
+
329
+ assert_select 'form input[type=checkbox][value=1][checked=checked]'
330
+ assert_select 'form input[type=checkbox][value=3][checked=checked]'
331
+ assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
332
+ end
333
+
334
+ test 'collection check box accepts multiple disabled items' do
335
+ collection = (1..3).map{|i| [i, "Tag #{i}"] }
336
+ with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :disabled => [1, 3]
337
+
338
+ assert_select 'form input[type=checkbox][value=1][disabled=disabled]'
339
+ assert_select 'form input[type=checkbox][value=3][disabled=disabled]'
340
+ assert_no_select 'form input[type=checkbox][value=2][disabled=disabled]'
341
+ end
342
+
343
+ test 'collection check box accepts single disable item' do
344
+ collection = (1..3).map{|i| [i, "Tag #{i}"] }
345
+ with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :disabled => 1
346
+
347
+ assert_select 'form input[type=checkbox][value=1][disabled=disabled]'
348
+ assert_no_select 'form input[type=checkbox][value=3][disabled=disabled]'
349
+ assert_no_select 'form input[type=checkbox][value=2][disabled=disabled]'
350
+ end
351
+
352
+ test 'collection check box accepts a proc to disabled items' do
353
+ collection = (1..3).map{|i| [i, "Tag #{i}"] }
354
+ with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :disabled => proc { |i| i.first == 1 }
355
+
356
+ assert_select 'form input[type=checkbox][value=1][disabled=disabled]'
357
+ assert_no_select 'form input[type=checkbox][value=3][disabled=disabled]'
358
+ assert_no_select 'form input[type=checkbox][value=2][disabled=disabled]'
359
+ end
360
+
361
+ test 'collection check box accepts html options' do
362
+ collection = [[1, 'Tag 1'], [2, 'Tag 2']]
363
+ with_collection_check_boxes @user, :tag_ids, collection, :first, :last, {}, :class => 'check'
364
+
365
+ assert_select 'form input.check[type=checkbox][value=1]'
366
+ assert_select 'form input.check[type=checkbox][value=2]'
367
+ end
368
+
369
+ test 'collection check box with fields for' do
370
+ collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
371
+ with_concat_form_for(@user) do |f|
372
+ f.fields_for(:post) do |p|
373
+ p.collection_check_boxes :tag_ids, collection, :id, :name
374
+ end
375
+ end
376
+
377
+ assert_select 'form input#user_post_tag_ids_1[type=checkbox][value=1]'
378
+ assert_select 'form input#user_post_tag_ids_2[type=checkbox][value=2]'
379
+
380
+ assert_select 'form label.collection_check_boxes[for=user_post_tag_ids_1]', 'Tag 1'
381
+ assert_select 'form label.collection_check_boxes[for=user_post_tag_ids_2]', 'Tag 2'
382
+ end
383
+
384
+ test 'collection check boxes wraps the collection in the given collection wrapper tag' do
385
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => :ul
386
+
387
+ assert_select 'form ul input[type=checkbox]', :count => 2
388
+ end
389
+
390
+ test 'collection check boxes does not render any wrapper tag by default' do
391
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
392
+
393
+ assert_select 'form input[type=checkbox]', :count => 2
394
+ assert_no_select 'form ul'
395
+ end
396
+
397
+ test 'collection check boxes does not wrap the collection when given falsy values' do
398
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => false
399
+
400
+ assert_select 'form input[type=checkbox]', :count => 2
401
+ assert_no_select 'form ul'
402
+ end
403
+
404
+ test 'collection check boxes uses the given class for collection wrapper tag' do
405
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
406
+ :collection_wrapper_tag => :ul, :collection_wrapper_class => "items-list"
407
+
408
+ assert_select 'form ul.items-list input[type=checkbox]', :count => 2
409
+ end
410
+
411
+ test 'collection check boxes uses no class for collection wrapper tag when no wrapper tag is given' do
412
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
413
+ :collection_wrapper_class => "items-list"
414
+
415
+ assert_select 'form input[type=checkbox]', :count => 2
416
+ assert_no_select 'form ul'
417
+ assert_no_select '.items-list'
418
+ end
419
+
420
+ test 'collection check boxes uses no class for collection wrapper tag by default' do
421
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => :ul
422
+
423
+ assert_select 'form ul'
424
+ assert_no_select 'form ul[class]'
425
+ end
426
+
427
+ test 'collection check boxes wrap items in a span tag by default' do
428
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
429
+
430
+ assert_select 'form span input[type=checkbox]', :count => 2
431
+ end
432
+
433
+ test 'collection check boxes wraps each item in the given item wrapper tag' do
434
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :item_wrapper_tag => :li
435
+
436
+ assert_select 'form li input[type=checkbox]', :count => 2
437
+ end
438
+
439
+ test 'collection check boxes does not wrap each item when given explicitly falsy value' do
440
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :item_wrapper_tag => false
441
+
442
+ assert_select 'form input[type=checkbox]'
443
+ assert_no_select 'form span input[type=checkbox]'
444
+ end
445
+
446
+ test 'collection check boxes uses the given class for item wrapper tag' do
447
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
448
+ :item_wrapper_tag => :li, :item_wrapper_class => "inline"
449
+
450
+ assert_select "form li.inline input[type=checkbox]", :count => 2
451
+ end
452
+
453
+ test 'collection check boxes uses no class for item wrapper tag when no wrapper tag is given' do
454
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
455
+ :item_wrapper_tag => nil, :item_wrapper_class => "inline"
456
+
457
+ assert_select 'form input[type=checkbox]', :count => 2
458
+ assert_no_select 'form li'
459
+ assert_no_select '.inline'
460
+ end
461
+
462
+ test 'collection check boxes uses no class for item wrapper tag by default' do
463
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
464
+ :item_wrapper_tag => :li
465
+
466
+ assert_select "form li", :count => 2
467
+ assert_no_select "form li[class]"
468
+ end
469
+
470
+ test 'collection check box does not wrap input inside the label' do
471
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
472
+
473
+ assert_select 'form input[type=checkbox] + label'
474
+ assert_no_select 'form label input'
475
+ end
476
+
477
+ test 'collection check boxes accepts a block to render the label as check box wrapper' do
478
+ with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b|
479
+ b.label { b.check_box }
480
+ end
481
+
482
+ assert_select 'label[for=user_active_true] > input#user_active_true[type=checkbox]'
483
+ assert_select 'label[for=user_active_false] > input#user_active_false[type=checkbox]'
484
+ end
485
+
486
+ test 'collection check boxes accepts a block to change the order of label and check box' do
487
+ with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b|
488
+ b.label + b.check_box
489
+ end
490
+
491
+ assert_select 'label[for=user_active_true] + input#user_active_true[type=checkbox]'
492
+ assert_select 'label[for=user_active_false] + input#user_active_false[type=checkbox]'
493
+ end
494
+
495
+ test 'collection check boxes with block helpers accept extra html options' do
496
+ with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b|
497
+ b.label(:class => "check_box") + b.check_box(:class => "check_box")
498
+ end
499
+
500
+ assert_select 'label.check_box[for=user_active_true] + input#user_active_true.check_box[type=checkbox]'
501
+ assert_select 'label.check_box[for=user_active_false] + input#user_active_false.check_box[type=checkbox]'
502
+ end
503
+
504
+ test 'collection check boxes with block helpers allows access to current text and value' do
505
+ with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b|
506
+ b.label(:"data-value" => b.value) { b.check_box + b.text }
507
+ end
508
+
509
+ assert_select 'label[for=user_active_true][data-value=true]', 'true' do
510
+ assert_select 'input#user_active_true[type=checkbox]'
511
+ end
512
+ assert_select 'label[for=user_active_false][data-value=false]', 'false' do
513
+ assert_select 'input#user_active_false[type=checkbox]'
514
+ end
515
+ end
516
+
517
+ test 'collection check boxes with block helpers allows access to the current object item in the collection to access extra properties' do
518
+ with_collection_check_boxes :user, :active, [true, false], :to_s, :to_s do |b|
519
+ b.label(:class => b.object) { b.check_box + b.text }
520
+ end
521
+
522
+ assert_select 'label.true[for=user_active_true]', 'true' do
523
+ assert_select 'input#user_active_true[type=checkbox]'
524
+ end
525
+ assert_select 'label.false[for=user_active_false]', 'false' do
526
+ assert_select 'input#user_active_false[type=checkbox]'
527
+ end
528
+ end
529
+
530
+ # SIMPLE FIELDS
531
+ test 'simple fields for is available and yields an instance of FormBuilder' do
532
+ with_concat_form_for(@user) do |f|
533
+ f.simple_fields_for(:posts) do |posts_form|
534
+ assert posts_form.instance_of?(SimpleForm::FormBuilder)
535
+ end
536
+ end
537
+ end
538
+
539
+ test 'fields for with a hash like model yeilds an instance of FormBuilder' do
540
+ @hash_backed_author = HashBackedAuthor.new
541
+
542
+ with_concat_form_for(:user) do |f|
543
+ f.simple_fields_for(:author, @hash_backed_author) do |author|
544
+ assert author.instance_of?(SimpleForm::FormBuilder)
545
+ author.input :name
546
+ end
547
+ end
548
+
549
+ assert_select "input[name='user[author][name]'][value='hash backed author']"
550
+ end
551
+
552
+ test 'fields for yields an instance of CustomBuilder if main builder is a CustomBuilder' do
553
+ with_custom_form_for(:user) do |f|
554
+ f.simple_fields_for(:company) do |company|
555
+ assert company.instance_of?(CustomFormBuilder)
556
+ end
557
+ end
558
+ end
559
+
560
+ test 'fields for yields an instance of FormBuilder if it was set in options' do
561
+ with_custom_form_for(:user) do |f|
562
+ f.simple_fields_for(:company, :builder => SimpleForm::FormBuilder) do |company|
563
+ assert company.instance_of?(SimpleForm::FormBuilder)
564
+ end
565
+ end
566
+ end
567
+
568
+ test 'fields inherites wrapper option from the parent form' do
569
+ swap_wrapper :another do
570
+ simple_form_for(:user, :wrapper => :another) do |f|
571
+ f.simple_fields_for(:company) do |company|
572
+ assert_equal :another, company.options[:wrapper]
573
+ end
574
+ end
575
+ end
576
+ end
577
+ end