ehoch_simple_form 2.0.2.dev

Sign up to get free protection for your applications and to get access to all the features.
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