simple_form 3.1.0 → 5.0.0
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +148 -0
- data/MIT-LICENSE +1 -1
- data/README.md +278 -68
- data/lib/generators/simple_form/install_generator.rb +1 -0
- data/lib/generators/simple_form/templates/README +3 -3
- data/lib/generators/simple_form/templates/_form.html.erb +2 -0
- data/lib/generators/simple_form/templates/_form.html.haml +2 -0
- data/lib/generators/simple_form/templates/_form.html.slim +1 -0
- data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +19 -9
- data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +367 -63
- data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +23 -8
- data/lib/simple_form/action_view_extensions/builder.rb +1 -0
- data/lib/simple_form/action_view_extensions/form_helper.rb +4 -1
- data/lib/simple_form/components/errors.rb +15 -2
- data/lib/simple_form/components/hints.rb +1 -0
- data/lib/simple_form/components/html5.rb +15 -4
- data/lib/simple_form/components/label_input.rb +2 -1
- data/lib/simple_form/components/labels.rb +12 -5
- data/lib/simple_form/components/maxlength.rb +8 -4
- data/lib/simple_form/components/min_max.rb +1 -0
- data/lib/simple_form/components/minlength.rb +38 -0
- data/lib/simple_form/components/pattern.rb +1 -0
- data/lib/simple_form/components/placeholders.rb +2 -1
- data/lib/simple_form/components/readonly.rb +1 -0
- data/lib/simple_form/components.rb +2 -0
- data/lib/simple_form/error_notification.rb +1 -0
- data/lib/simple_form/form_builder.rb +117 -35
- data/lib/simple_form/helpers/autofocus.rb +1 -0
- data/lib/simple_form/helpers/disabled.rb +1 -0
- data/lib/simple_form/helpers/readonly.rb +1 -0
- data/lib/simple_form/helpers/required.rb +1 -0
- data/lib/simple_form/helpers/validators.rb +2 -1
- data/lib/simple_form/helpers.rb +1 -0
- data/lib/simple_form/i18n_cache.rb +1 -0
- data/lib/simple_form/inputs/base.rb +36 -12
- data/lib/simple_form/inputs/block_input.rb +1 -0
- data/lib/simple_form/inputs/boolean_input.rb +14 -3
- data/lib/simple_form/inputs/collection_check_boxes_input.rb +2 -1
- data/lib/simple_form/inputs/collection_input.rb +7 -5
- data/lib/simple_form/inputs/collection_radio_buttons_input.rb +3 -2
- data/lib/simple_form/inputs/collection_select_input.rb +1 -0
- data/lib/simple_form/inputs/color_input.rb +14 -0
- data/lib/simple_form/inputs/date_time_input.rb +13 -8
- data/lib/simple_form/inputs/file_input.rb +1 -0
- data/lib/simple_form/inputs/grouped_collection_select_input.rb +1 -0
- data/lib/simple_form/inputs/hidden_input.rb +1 -0
- data/lib/simple_form/inputs/numeric_input.rb +1 -0
- data/lib/simple_form/inputs/password_input.rb +2 -1
- data/lib/simple_form/inputs/priority_input.rb +1 -4
- data/lib/simple_form/inputs/range_input.rb +1 -0
- data/lib/simple_form/inputs/string_input.rb +3 -2
- data/lib/simple_form/inputs/text_input.rb +2 -1
- data/lib/simple_form/inputs.rb +2 -0
- data/lib/simple_form/map_type.rb +1 -0
- data/lib/simple_form/railtie.rb +1 -0
- data/lib/simple_form/tags.rb +7 -2
- data/lib/simple_form/version.rb +2 -1
- data/lib/simple_form/wrappers/builder.rb +1 -0
- data/lib/simple_form/wrappers/leaf.rb +2 -1
- data/lib/simple_form/wrappers/many.rb +1 -0
- data/lib/simple_form/wrappers/root.rb +2 -0
- data/lib/simple_form/wrappers/single.rb +2 -1
- data/lib/simple_form/wrappers.rb +1 -0
- data/lib/simple_form.rb +79 -14
- data/test/action_view_extensions/builder_test.rb +28 -9
- data/test/action_view_extensions/form_helper_test.rb +3 -2
- data/test/components/custom_components_test.rb +62 -0
- data/test/components/label_test.rb +33 -4
- data/test/form_builder/association_test.rb +33 -2
- data/test/form_builder/button_test.rb +1 -0
- data/test/form_builder/error_notification_test.rb +1 -0
- data/test/form_builder/error_test.rb +44 -9
- data/test/form_builder/general_test.rb +92 -20
- data/test/form_builder/hint_test.rb +6 -0
- data/test/form_builder/input_field_test.rb +76 -70
- data/test/form_builder/label_test.rb +27 -4
- data/test/form_builder/wrapper_test.rb +66 -14
- data/test/generators/simple_form_generator_test.rb +4 -3
- data/test/inputs/boolean_input_test.rb +35 -0
- data/test/inputs/collection_check_boxes_input_test.rb +38 -14
- data/test/inputs/collection_radio_buttons_input_test.rb +48 -24
- data/test/inputs/collection_select_input_test.rb +40 -39
- data/test/inputs/color_input_test.rb +10 -0
- data/test/inputs/datetime_input_test.rb +12 -8
- data/test/inputs/disabled_test.rb +14 -0
- data/test/inputs/discovery_test.rb +23 -0
- data/test/inputs/file_input_test.rb +1 -0
- data/test/inputs/general_test.rb +3 -2
- data/test/inputs/grouped_collection_select_input_test.rb +11 -10
- data/test/inputs/hidden_input_test.rb +1 -0
- data/test/inputs/numeric_input_test.rb +5 -1
- data/test/inputs/priority_input_test.rb +7 -6
- data/test/inputs/readonly_test.rb +1 -0
- data/test/inputs/required_test.rb +45 -0
- data/test/inputs/string_input_test.rb +18 -16
- data/test/inputs/text_input_test.rb +13 -0
- data/test/simple_form_test.rb +1 -0
- data/test/support/discovery_inputs.rb +8 -0
- data/test/support/misc_helpers.rb +44 -2
- data/test/support/mock_controller.rb +7 -1
- data/test/support/models.rb +105 -22
- data/test/test_helper.rb +14 -3
- metadata +42 -36
data/lib/simple_form.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'action_view'
|
3
|
+
require 'action_pack'
|
2
4
|
require 'simple_form/action_view_extensions/form_helper'
|
3
5
|
require 'simple_form/action_view_extensions/builder'
|
4
6
|
require 'active_support/core_ext/hash/slice'
|
@@ -36,6 +38,17 @@ to
|
|
36
38
|
See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
37
39
|
WARN
|
38
40
|
|
41
|
+
FILE_METHODS_DEPRECATION_WARN = <<-WARN
|
42
|
+
[SIMPLE_FORM] SimpleForm.file_methods is deprecated and has no effect.
|
43
|
+
|
44
|
+
Since version 5, Simple Form now supports automatically discover of file inputs for the following Gems: activestorage, carrierwave, paperclip, refile and shrine.
|
45
|
+
If you are using a custom method that is not from one of the supported Gems, please change your forms to pass the input type explicitly:
|
46
|
+
|
47
|
+
<%= form.input :avatar, as: :file %>
|
48
|
+
|
49
|
+
See http://blog.plataformatec.com.br/2019/09/incorrect-access-control-in-simple-form-cve-2019-16676 for more information.
|
50
|
+
WARN
|
51
|
+
|
39
52
|
@@configured = false
|
40
53
|
|
41
54
|
def self.configured? #:nodoc:
|
@@ -58,11 +71,11 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
58
71
|
|
59
72
|
# Series of attemps to detect a default label method for collection.
|
60
73
|
mattr_accessor :collection_label_methods
|
61
|
-
@@collection_label_methods = [
|
74
|
+
@@collection_label_methods = %i[to_label name title to_s]
|
62
75
|
|
63
76
|
# Series of attemps to detect a default value method for collection.
|
64
77
|
mattr_accessor :collection_value_methods
|
65
|
-
@@collection_value_methods = [
|
78
|
+
@@collection_value_methods = %i[id to_s]
|
66
79
|
|
67
80
|
# You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
|
68
81
|
mattr_accessor :collection_wrapper_tag
|
@@ -84,7 +97,7 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
84
97
|
|
85
98
|
# How the label text should be generated altogether with the required text.
|
86
99
|
mattr_accessor :label_text
|
87
|
-
@@label_text =
|
100
|
+
@@label_text = ->(label, required, explicit_label) { "#{required} #{label}" }
|
88
101
|
|
89
102
|
# You can define the class to be used on all labels. Defaults to none.
|
90
103
|
mattr_accessor :label_class
|
@@ -108,7 +121,7 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
108
121
|
|
109
122
|
# You can define which elements should obtain additional classes.
|
110
123
|
mattr_accessor :generate_additional_classes_for
|
111
|
-
@@generate_additional_classes_for = [
|
124
|
+
@@generate_additional_classes_for = %i[wrapper label input]
|
112
125
|
|
113
126
|
# Whether attributes are required by default or not.
|
114
127
|
mattr_accessor :required_by_default
|
@@ -118,10 +131,6 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
118
131
|
mattr_accessor :browser_validations
|
119
132
|
@@browser_validations = true
|
120
133
|
|
121
|
-
# Collection of methods to detect if a file type was given.
|
122
|
-
mattr_accessor :file_methods
|
123
|
-
@@file_methods = [:mounted_as, :file?, :public_filename]
|
124
|
-
|
125
134
|
# Custom mappings for input types. This should be a hash containing a regexp
|
126
135
|
# to match as key, and the input type that will be used when the field name
|
127
136
|
# matches the regexp as value, such as { /count/ => :integer }.
|
@@ -152,10 +161,6 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
152
161
|
mattr_accessor :country_priority
|
153
162
|
@@country_priority = nil
|
154
163
|
|
155
|
-
# DEPRECATED: Maximum size allowed for inputs.
|
156
|
-
mattr_accessor :default_input_size
|
157
|
-
@@default_input_size = nil
|
158
|
-
|
159
164
|
# When off, do not use translations in labels. Disabling translation in
|
160
165
|
# hints and placeholders can be done manually in the wrapper API.
|
161
166
|
mattr_accessor :translate_labels
|
@@ -167,7 +172,7 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
167
172
|
|
168
173
|
# Cache SimpleForm inputs discovery.
|
169
174
|
mattr_accessor :cache_discovery
|
170
|
-
@@cache_discovery = defined?(Rails) && !Rails.env.development?
|
175
|
+
@@cache_discovery = defined?(Rails.env) && !Rails.env.development?
|
171
176
|
|
172
177
|
# Adds a class to each generated button, mostly for compatiblity.
|
173
178
|
mattr_accessor :button_class
|
@@ -202,6 +207,12 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
202
207
|
mattr_accessor :i18n_scope
|
203
208
|
@@i18n_scope = 'simple_form'
|
204
209
|
|
210
|
+
mattr_accessor :input_field_error_class
|
211
|
+
@@input_field_error_class = nil
|
212
|
+
|
213
|
+
mattr_accessor :input_field_valid_class
|
214
|
+
@@input_field_valid_class = nil
|
215
|
+
|
205
216
|
# Retrieves a given wrapper
|
206
217
|
def self.wrapper(name)
|
207
218
|
@@wrappers[name.to_s] or raise WrapperNotFound, "Couldn't find wrapper with name #{name}"
|
@@ -231,11 +242,12 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
231
242
|
SimpleForm::Wrappers::Root.new(builder.to_a, options)
|
232
243
|
end
|
233
244
|
|
234
|
-
wrappers class: :input, hint_class: :field_with_hint, error_class: :field_with_errors do |b|
|
245
|
+
wrappers class: :input, hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b|
|
235
246
|
b.use :html5
|
236
247
|
|
237
248
|
b.use :min_max
|
238
249
|
b.use :maxlength
|
250
|
+
b.use :minlength
|
239
251
|
b.use :placeholder
|
240
252
|
b.optional :pattern
|
241
253
|
b.optional :readonly
|
@@ -260,12 +272,65 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
260
272
|
@@form_class = value
|
261
273
|
end
|
262
274
|
|
275
|
+
def self.file_methods=(file_methods)
|
276
|
+
ActiveSupport::Deprecation.warn(FILE_METHODS_DEPRECATION_WARN, caller)
|
277
|
+
@@file_methods = file_methods
|
278
|
+
end
|
279
|
+
|
280
|
+
def self.file_methods
|
281
|
+
ActiveSupport::Deprecation.warn(FILE_METHODS_DEPRECATION_WARN, caller)
|
282
|
+
@@file_methods
|
283
|
+
end
|
284
|
+
|
263
285
|
# Default way to setup Simple Form. Run rails generate simple_form:install
|
264
286
|
# to create a fresh initializer with all configuration values.
|
265
287
|
def self.setup
|
266
288
|
@@configured = true
|
267
289
|
yield self
|
268
290
|
end
|
291
|
+
|
292
|
+
# Includes a component to be used by Simple Form. Methods defined in a
|
293
|
+
# component will be exposed to be used in the wrapper as Simple::Components
|
294
|
+
#
|
295
|
+
# Examples
|
296
|
+
#
|
297
|
+
# # The application needs to tell where the components will be.
|
298
|
+
# Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
|
299
|
+
#
|
300
|
+
# # Create a custom component in the path specified above.
|
301
|
+
# # lib/components/input_group_component.rb
|
302
|
+
# module InputGroupComponent
|
303
|
+
# def prepend
|
304
|
+
# ...
|
305
|
+
# end
|
306
|
+
#
|
307
|
+
# def append
|
308
|
+
# ...
|
309
|
+
# end
|
310
|
+
# end
|
311
|
+
#
|
312
|
+
# SimpleForm.setup do |config|
|
313
|
+
# # Create a wrapper using the custom component.
|
314
|
+
# config.wrappers :input_group, tag: :div, error_class: :error do |b|
|
315
|
+
# b.use :label
|
316
|
+
# b.optional :prepend
|
317
|
+
# b.use :input
|
318
|
+
# b.use :append
|
319
|
+
# end
|
320
|
+
# end
|
321
|
+
#
|
322
|
+
# # Using the custom component in the form.
|
323
|
+
# <%= simple_form_for @blog, wrapper: input_group do |f| %>
|
324
|
+
# <%= f.input :title, prepend: true %>
|
325
|
+
# <% end %>
|
326
|
+
#
|
327
|
+
def self.include_component(component)
|
328
|
+
if Module === component
|
329
|
+
SimpleForm::Inputs::Base.include(component)
|
330
|
+
else
|
331
|
+
raise TypeError, "SimpleForm.include_component expects a module but got: #{component.class}"
|
332
|
+
end
|
333
|
+
end
|
269
334
|
end
|
270
335
|
|
271
336
|
require 'simple_form/railtie' if defined?(Rails)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'test_helper'
|
2
3
|
|
3
4
|
class BuilderTest < ActionView::TestCase
|
@@ -36,7 +37,7 @@ class BuilderTest < ActionView::TestCase
|
|
36
37
|
end
|
37
38
|
|
38
39
|
test "collection radio handles camelized collection values for labels correctly" do
|
39
|
-
with_collection_radio_buttons @user, :active, [
|
40
|
+
with_collection_radio_buttons @user, :active, %w[Yes No], :to_s, :to_s
|
40
41
|
|
41
42
|
assert_select 'form label.collection_radio_buttons[for=user_active_yes]', 'Yes'
|
42
43
|
assert_select 'form label.collection_radio_buttons[for=user_active_no]', 'No'
|
@@ -44,8 +45,17 @@ class BuilderTest < ActionView::TestCase
|
|
44
45
|
|
45
46
|
test "collection radio sanitizes collection values for labels correctly" do
|
46
47
|
with_collection_radio_buttons @user, :name, ['$0.99', '$1.99'], :to_s, :to_s
|
47
|
-
|
48
|
-
|
48
|
+
|
49
|
+
# Rails 6 changed the way it sanitizes the values
|
50
|
+
# https://github.com/rails/rails/blob/6-0-stable/actionview/lib/action_view/helpers/tags/base.rb#L141
|
51
|
+
# https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/helpers/tags/base.rb#L141
|
52
|
+
if ActionView::VERSION::MAJOR == 5
|
53
|
+
assert_select 'label.collection_radio_buttons[for=user_name_099]', '$0.99'
|
54
|
+
assert_select 'label.collection_radio_buttons[for=user_name_199]', '$1.99'
|
55
|
+
else
|
56
|
+
assert_select 'label.collection_radio_buttons[for=user_name_0_99]', '$0.99'
|
57
|
+
assert_select 'label.collection_radio_buttons[for=user_name_1_99]', '$1.99'
|
58
|
+
end
|
49
59
|
end
|
50
60
|
|
51
61
|
test "collection radio checks the correct value to local variables" do
|
@@ -243,7 +253,7 @@ class BuilderTest < ActionView::TestCase
|
|
243
253
|
|
244
254
|
test "collection radio with block helpers does not leak the template" do
|
245
255
|
with_concat_form_for(@user) do |f|
|
246
|
-
collection_input =
|
256
|
+
collection_input = f.collection_radio_buttons :active, [true, false], :to_s, :to_s do |b|
|
247
257
|
b.label(class: b.object) { b.radio_button + b.text }
|
248
258
|
end
|
249
259
|
concat collection_input
|
@@ -283,7 +293,7 @@ class BuilderTest < ActionView::TestCase
|
|
283
293
|
end
|
284
294
|
|
285
295
|
test "collection check box handles camelized collection values for labels correctly" do
|
286
|
-
with_collection_check_boxes @user, :active, [
|
296
|
+
with_collection_check_boxes @user, :active, %w[Yes No], :to_s, :to_s
|
287
297
|
|
288
298
|
assert_select 'form label.collection_check_boxes[for=user_active_yes]', 'Yes'
|
289
299
|
assert_select 'form label.collection_check_boxes[for=user_active_no]', 'No'
|
@@ -291,8 +301,17 @@ class BuilderTest < ActionView::TestCase
|
|
291
301
|
|
292
302
|
test "collection check box sanitizes collection values for labels correctly" do
|
293
303
|
with_collection_check_boxes @user, :name, ['$0.99', '$1.99'], :to_s, :to_s
|
294
|
-
|
295
|
-
|
304
|
+
|
305
|
+
# Rails 6 changed the way it sanitizes the values
|
306
|
+
# https://github.com/rails/rails/blob/6-0-stable/actionview/lib/action_view/helpers/tags/base.rb#L141
|
307
|
+
# https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/helpers/tags/base.rb#L141
|
308
|
+
if ActionView::VERSION::MAJOR == 5
|
309
|
+
assert_select 'label.collection_check_boxes[for=user_name_099]', '$0.99'
|
310
|
+
assert_select 'label.collection_check_boxes[for=user_name_199]', '$1.99'
|
311
|
+
else
|
312
|
+
assert_select 'label.collection_check_boxes[for=user_name_0_99]', '$0.99'
|
313
|
+
assert_select 'label.collection_check_boxes[for=user_name_1_99]', '$1.99'
|
314
|
+
end
|
296
315
|
end
|
297
316
|
|
298
317
|
test "collection check box checks the correct value to local variables" do
|
@@ -317,7 +336,7 @@ class BuilderTest < ActionView::TestCase
|
|
317
336
|
|
318
337
|
test "collection check boxes accepts selected string values as :checked option" do
|
319
338
|
collection = (1..3).map { |i| [i, "Category #{i}"] }
|
320
|
-
with_collection_check_boxes :user, :category_ids, collection, :first, :last, checked: [
|
339
|
+
with_collection_check_boxes :user, :category_ids, collection, :first, :last, checked: %w[1 3]
|
321
340
|
|
322
341
|
assert_select 'input[type=checkbox][value="1"][checked=checked]'
|
323
342
|
assert_select 'input[type=checkbox][value="3"][checked=checked]'
|
@@ -541,7 +560,7 @@ class BuilderTest < ActionView::TestCase
|
|
541
560
|
|
542
561
|
test "collection check boxes with block helpers does not leak the template" do
|
543
562
|
with_concat_form_for(@user) do |f|
|
544
|
-
collection_input =
|
563
|
+
collection_input = f.collection_check_boxes :active, [true, false], :to_s, :to_s do |b|
|
545
564
|
b.label(class: b.object) { b.check_box + b.text }
|
546
565
|
end
|
547
566
|
concat collection_input
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'test_helper'
|
2
3
|
|
3
4
|
class FormHelperTest < ActionView::TestCase
|
@@ -151,7 +152,7 @@ class FormHelperTest < ActionView::TestCase
|
|
151
152
|
end
|
152
153
|
|
153
154
|
test 'SimpleForm for swaps default action view field_error_proc' do
|
154
|
-
expected_error_proc =
|
155
|
+
expected_error_proc = -> {}
|
155
156
|
swap SimpleForm, field_error_proc: expected_error_proc do
|
156
157
|
simple_form_for :user do |f|
|
157
158
|
assert_equal expected_error_proc, ::ActionView::Base.field_error_proc
|
@@ -161,7 +162,7 @@ class FormHelperTest < ActionView::TestCase
|
|
161
162
|
|
162
163
|
private
|
163
164
|
|
164
|
-
def swap_field_error_proc(expected_error_proc =
|
165
|
+
def swap_field_error_proc(expected_error_proc = -> {})
|
165
166
|
swap ActionView::Base, field_error_proc: expected_error_proc do
|
166
167
|
yield
|
167
168
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
# Module that represents a custom component.
|
6
|
+
module Numbers
|
7
|
+
def number(wrapper_options = nil)
|
8
|
+
@number ||= options[:number].to_s.html_safe
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Module that represents a custom component.
|
13
|
+
module InputGroup
|
14
|
+
def prepend(wrapper_options = nil)
|
15
|
+
span_tag = content_tag(:span, options[:prepend], class: 'input-group-text')
|
16
|
+
template.content_tag(:div, span_tag, class: 'input-group-prepend')
|
17
|
+
end
|
18
|
+
|
19
|
+
def append(wrapper_options = nil)
|
20
|
+
span_tag = content_tag(:span, options[:append], class: 'input-group-text')
|
21
|
+
template.content_tag(:div, span_tag, class: 'input-group-append')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class CustomComponentsTest < ActionView::TestCase
|
26
|
+
test 'includes the custom components' do
|
27
|
+
SimpleForm.include_component Numbers
|
28
|
+
|
29
|
+
custom_wrapper = SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
30
|
+
b.use :number, wrap_with: { tag: 'div', class: 'number' }
|
31
|
+
end
|
32
|
+
|
33
|
+
with_form_for @user, :name, number: 1, wrapper: custom_wrapper
|
34
|
+
|
35
|
+
assert_select 'div.number', text: '1'
|
36
|
+
end
|
37
|
+
|
38
|
+
test 'includes custom components and use it as optional in the wrapper' do
|
39
|
+
SimpleForm.include_component InputGroup
|
40
|
+
|
41
|
+
custom_wrapper = SimpleForm.build tag: :div, class: 'custom_wrapper' do |b|
|
42
|
+
b.use :label
|
43
|
+
b.optional :prepend
|
44
|
+
b.use :input
|
45
|
+
b.use :append
|
46
|
+
end
|
47
|
+
|
48
|
+
with_form_for @user, :name, prepend: true, wrapper: custom_wrapper
|
49
|
+
|
50
|
+
assert_select 'div.input-group-prepend > span.input-group-text'
|
51
|
+
assert_select 'div.input-group-append > span.input-group-text'
|
52
|
+
end
|
53
|
+
|
54
|
+
test 'raises a TypeError when the component is not a Module' do
|
55
|
+
component = 'MyComponent'
|
56
|
+
|
57
|
+
exception = assert_raises TypeError do
|
58
|
+
SimpleForm.include_component(component)
|
59
|
+
end
|
60
|
+
assert_equal exception.message, "SimpleForm.include_component expects a module but got: String"
|
61
|
+
end
|
62
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# encoding: UTF-8
|
2
3
|
require 'test_helper'
|
3
4
|
|
@@ -177,7 +178,7 @@ class IsolatedLabelTest < ActionView::TestCase
|
|
177
178
|
end
|
178
179
|
|
179
180
|
test 'label does not have css class from type when generate_additional_classes_for does not include :label' do
|
180
|
-
swap SimpleForm, generate_additional_classes_for: [
|
181
|
+
swap SimpleForm, generate_additional_classes_for: %i[wrapper input] do
|
181
182
|
with_label_for @user, :name, :string
|
182
183
|
assert_no_select 'label.string'
|
183
184
|
with_label_for @user, :description, :text
|
@@ -192,7 +193,7 @@ class IsolatedLabelTest < ActionView::TestCase
|
|
192
193
|
end
|
193
194
|
|
194
195
|
test 'label does not generate empty css class' do
|
195
|
-
swap SimpleForm, generate_additional_classes_for: [
|
196
|
+
swap SimpleForm, generate_additional_classes_for: %i[wrapper input] do
|
196
197
|
with_label_for @user, :name, :string
|
197
198
|
assert_no_select 'label[class]'
|
198
199
|
end
|
@@ -206,7 +207,7 @@ class IsolatedLabelTest < ActionView::TestCase
|
|
206
207
|
end
|
207
208
|
|
208
209
|
test 'label does not obtain required from ActiveModel::Validations when generate_additional_classes_for does not include :label' do
|
209
|
-
swap SimpleForm, generate_additional_classes_for: [
|
210
|
+
swap SimpleForm, generate_additional_classes_for: %i[wrapper input] do
|
210
211
|
with_label_for @validating_user, :name, :string
|
211
212
|
assert_no_select 'label.required'
|
212
213
|
with_label_for @validating_user, :status, :string
|
@@ -248,6 +249,15 @@ class IsolatedLabelTest < ActionView::TestCase
|
|
248
249
|
end
|
249
250
|
end
|
250
251
|
|
252
|
+
test 'label uses custom i18n scope to find required text' do
|
253
|
+
store_translations(:en, my_scope: { required: { text: 'Pflichtfeld' } }) do
|
254
|
+
swap SimpleForm, i18n_scope: :my_scope do
|
255
|
+
with_label_for @user, :name, :string
|
256
|
+
assert_select 'form label abbr[title="Pflichtfeld"]', '*'
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
251
261
|
test 'label uses i18n to find required mark' do
|
252
262
|
store_translations(:en, simple_form: { required: { mark: '*-*' } }) do
|
253
263
|
with_label_for @user, :name, :string
|
@@ -255,6 +265,15 @@ class IsolatedLabelTest < ActionView::TestCase
|
|
255
265
|
end
|
256
266
|
end
|
257
267
|
|
268
|
+
test 'label uses custom i18n scope to find required mark' do
|
269
|
+
store_translations(:en, my_scope: { required: { mark: '!!' } }) do
|
270
|
+
swap SimpleForm, i18n_scope: :my_scope do
|
271
|
+
with_label_for @user, :name, :string
|
272
|
+
assert_select 'form label abbr', '!!'
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
258
277
|
test 'label uses i18n to find required string tag' do
|
259
278
|
store_translations(:en, simple_form: { required: { html: '<span class="required" title="requerido">*</span>' } }) do
|
260
279
|
with_label_for @user, :name, :string
|
@@ -263,6 +282,16 @@ class IsolatedLabelTest < ActionView::TestCase
|
|
263
282
|
end
|
264
283
|
end
|
265
284
|
|
285
|
+
test 'label uses custom i18n scope to find required string tag' do
|
286
|
+
store_translations(:en, my_scope: { required: { html: '<span class="mandatory" title="Pflichtfeld">!!</span>' } }) do
|
287
|
+
swap SimpleForm, i18n_scope: :my_scope do
|
288
|
+
with_label_for @user, :name, :string
|
289
|
+
assert_no_select 'form label abbr'
|
290
|
+
assert_select 'form label span.mandatory[title=Pflichtfeld]', '!!'
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
266
295
|
test 'label allows overwriting input id' do
|
267
296
|
with_label_for @user, :name, :string, input_html: { id: 'my_new_id' }
|
268
297
|
assert_select 'label[for=my_new_id]'
|
@@ -289,7 +318,7 @@ class IsolatedLabelTest < ActionView::TestCase
|
|
289
318
|
end
|
290
319
|
|
291
320
|
test 'label includes for attribute for select collection' do
|
292
|
-
with_label_for @user, :sex, :select, collection: [
|
321
|
+
with_label_for @user, :sex, :select, collection: %i[male female]
|
293
322
|
assert_select 'label[for=user_sex]'
|
294
323
|
end
|
295
324
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# encoding: UTF-8
|
2
3
|
require 'test_helper'
|
3
4
|
|
@@ -14,6 +15,12 @@ class AssociationTest < ActionView::TestCase
|
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
18
|
+
test 'builder association works with decorated object responsive to #to_model' do
|
19
|
+
assert_nothing_raised do
|
20
|
+
with_association_for @decorated_user, :company
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
17
24
|
test 'builder association with a block calls simple_fields_for' do
|
18
25
|
simple_form_for @user do |f|
|
19
26
|
f.association :posts do |posts_form|
|
@@ -121,6 +128,15 @@ class AssociationTest < ActionView::TestCase
|
|
121
128
|
assert_no_select 'form select option[value="2"]'
|
122
129
|
end
|
123
130
|
|
131
|
+
test 'builder allows collection to have a scope with parameter' do
|
132
|
+
with_association_for @user, :special_tags
|
133
|
+
assert_select 'form select.select#user_special_tag_ids'
|
134
|
+
assert_select 'form select[multiple=multiple]'
|
135
|
+
assert_select 'form select option[value="1"]', 'Tag 1'
|
136
|
+
assert_no_select 'form select option[value="2"]'
|
137
|
+
assert_no_select 'form select option[value="3"]'
|
138
|
+
end
|
139
|
+
|
124
140
|
test 'builder marks the record which already belongs to the user' do
|
125
141
|
@user.company_id = 2
|
126
142
|
with_association_for @user, :company, as: :radio_buttons
|
@@ -154,6 +170,15 @@ class AssociationTest < ActionView::TestCase
|
|
154
170
|
end
|
155
171
|
end
|
156
172
|
|
173
|
+
test 'builder does not call where if the given association does not respond to it' do
|
174
|
+
with_association_for @user, :friends
|
175
|
+
assert_select 'form select.select#user_friend_ids'
|
176
|
+
assert_select 'form select[multiple=multiple]'
|
177
|
+
assert_select 'form select option[value="1"]', 'Friend 1'
|
178
|
+
assert_select 'form select option[value="2"]', 'Friend 2'
|
179
|
+
assert_select 'form select option[value="3"]', 'Friend 3'
|
180
|
+
end
|
181
|
+
|
157
182
|
test 'builder does not call order if the given association does not respond to it' do
|
158
183
|
with_association_for @user, :pictures
|
159
184
|
assert_select 'form select.select#user_picture_ids'
|
@@ -210,12 +235,18 @@ class AssociationTest < ActionView::TestCase
|
|
210
235
|
end
|
211
236
|
|
212
237
|
test 'builder with collection support does not change the options hash' do
|
213
|
-
options = { as: :check_boxes, collection_wrapper_tag: :ul, item_wrapper_tag: :li}
|
238
|
+
options = { as: :check_boxes, collection_wrapper_tag: :ul, item_wrapper_tag: :li }
|
214
239
|
with_association_for @user, :tags, options
|
215
240
|
|
216
241
|
assert_select 'form ul', count: 1
|
217
242
|
assert_select 'form ul li', count: 3
|
218
|
-
assert_equal({ as: :check_boxes, collection_wrapper_tag: :ul, item_wrapper_tag: :li},
|
243
|
+
assert_equal({ as: :check_boxes, collection_wrapper_tag: :ul, item_wrapper_tag: :li },
|
219
244
|
options)
|
220
245
|
end
|
246
|
+
|
247
|
+
test 'builder with group select considers multiple select by default' do
|
248
|
+
with_association_for @user, :tags, as: :grouped_select, group_method: :group_method
|
249
|
+
|
250
|
+
assert_select 'select[multiple="multiple"].grouped_select'
|
251
|
+
end
|
221
252
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'test_helper'
|
2
3
|
|
3
4
|
# Tests for f.error and f.full_error
|
@@ -35,6 +36,11 @@ class ErrorTest < ActionView::TestCase
|
|
35
36
|
assert_select 'span.error', "cannot be blank"
|
36
37
|
end
|
37
38
|
|
39
|
+
test 'error generates messages with decorated object responsive to #to_model' do
|
40
|
+
with_error_for @decorated_user, :name
|
41
|
+
assert_select 'span.error', "cannot be blank"
|
42
|
+
end
|
43
|
+
|
38
44
|
test 'error generates messages for attribute with one error when using first' do
|
39
45
|
swap SimpleForm, error_method: :first do
|
40
46
|
with_error_for @user, :age
|
@@ -94,13 +100,36 @@ class ErrorTest < ActionView::TestCase
|
|
94
100
|
assert_no_select 'span.error b', 'markup'
|
95
101
|
end
|
96
102
|
|
97
|
-
|
98
103
|
test 'error generates an error message with raw HTML tags' do
|
99
104
|
with_error_for @user, :name, error_prefix: '<b>Name</b>'.html_safe
|
100
105
|
assert_select 'span.error', "Name cannot be blank"
|
101
106
|
assert_select 'span.error b', "Name"
|
102
107
|
end
|
103
108
|
|
109
|
+
test 'error adds aria-invalid attribute to inputs' do
|
110
|
+
with_form_for @user, :name, error: true
|
111
|
+
assert_select "input#user_name[name='user[name]'][aria-invalid='true']"
|
112
|
+
|
113
|
+
with_form_for @user, :name, as: :text, error: true
|
114
|
+
assert_select "textarea#user_name[name='user[name]'][aria-invalid='true']"
|
115
|
+
|
116
|
+
@user.errors.add(:active, 'must select one')
|
117
|
+
with_form_for @user, :active, as: :radio_buttons
|
118
|
+
assert_select "input#user_active_true[type=radio][name='user[active]'][aria-invalid='true']"
|
119
|
+
assert_select "input#user_active_false[type=radio][name='user[active]'][aria-invalid='true']"
|
120
|
+
|
121
|
+
with_form_for @user, :active, as: :check_boxes
|
122
|
+
assert_select "input#user_active_true[type=checkbox][aria-invalid='true']"
|
123
|
+
assert_select "input#user_active_false[type=checkbox][aria-invalid='true']"
|
124
|
+
|
125
|
+
with_form_for @user, :company_id, as: :select, error: true
|
126
|
+
assert_select "select#user_company_id[aria-invalid='true']"
|
127
|
+
|
128
|
+
@user.errors.add(:password, 'must not be blank')
|
129
|
+
with_form_for @user, :password
|
130
|
+
assert_select "input#user_password[type=password][aria-invalid='true']"
|
131
|
+
end
|
132
|
+
|
104
133
|
# FULL ERRORS
|
105
134
|
|
106
135
|
test 'full error generates a full error tag for the attribute' do
|
@@ -146,14 +175,14 @@ class ErrorTest < ActionView::TestCase
|
|
146
175
|
# FULL_ERROR_WRAPPER
|
147
176
|
|
148
177
|
test 'full error finds errors on association' do
|
149
|
-
swap_wrapper :default,
|
178
|
+
swap_wrapper :default, custom_wrapper_with_full_error do
|
150
179
|
with_form_for @user, :company_id, as: :select
|
151
180
|
assert_select 'span.error', 'Company must be valid'
|
152
181
|
end
|
153
182
|
end
|
154
183
|
|
155
184
|
test 'full error finds errors on association with reflection' do
|
156
|
-
swap_wrapper :default,
|
185
|
+
swap_wrapper :default, custom_wrapper_with_full_error do
|
157
186
|
with_form_for @user, :company_id, as: :select,
|
158
187
|
reflection: Association.new(Company, :company, {})
|
159
188
|
assert_select 'span.error', 'Company must be valid'
|
@@ -161,14 +190,14 @@ class ErrorTest < ActionView::TestCase
|
|
161
190
|
end
|
162
191
|
|
163
192
|
test 'full error can be disabled' do
|
164
|
-
swap_wrapper :default,
|
193
|
+
swap_wrapper :default, custom_wrapper_with_full_error do
|
165
194
|
with_form_for @user, :company_id, as: :select, full_error: false
|
166
195
|
assert_no_select 'span.error'
|
167
196
|
end
|
168
197
|
end
|
169
198
|
|
170
199
|
test 'full error can be disabled setting error to false' do
|
171
|
-
swap_wrapper :default,
|
200
|
+
swap_wrapper :default, custom_wrapper_with_full_error do
|
172
201
|
with_form_for @user, :company_id, as: :select, error: false
|
173
202
|
assert_no_select 'span.error'
|
174
203
|
end
|
@@ -195,8 +224,14 @@ class ErrorTest < ActionView::TestCase
|
|
195
224
|
assert_no_select 'span.error'
|
196
225
|
end
|
197
226
|
|
227
|
+
test 'input with custom error works when form does not use a model' do
|
228
|
+
with_form_for :user, :active, error: "Super User Active! cannot be blank"
|
229
|
+
|
230
|
+
assert_select 'span.error'
|
231
|
+
end
|
232
|
+
|
198
233
|
test 'input with custom error works when using full_error component' do
|
199
|
-
swap_wrapper :default,
|
234
|
+
swap_wrapper :default, custom_wrapper_with_full_error do
|
200
235
|
error_text = "Super User Name! cannot be blank"
|
201
236
|
with_form_for @user, :name, error: error_text
|
202
237
|
|
@@ -219,7 +254,7 @@ class ErrorTest < ActionView::TestCase
|
|
219
254
|
end
|
220
255
|
|
221
256
|
test 'input with custom error escapes the error text using full_error component' do
|
222
|
-
swap_wrapper :default,
|
257
|
+
swap_wrapper :default, custom_wrapper_with_full_error do
|
223
258
|
with_form_for @user, :name, error: 'error must not contain <b>markup</b>'
|
224
259
|
|
225
260
|
assert_select 'span.error'
|
@@ -228,7 +263,7 @@ class ErrorTest < ActionView::TestCase
|
|
228
263
|
end
|
229
264
|
|
230
265
|
test 'input with custom error does not escape the error text if it is safe using full_error component' do
|
231
|
-
swap_wrapper :default,
|
266
|
+
swap_wrapper :default, custom_wrapper_with_full_error do
|
232
267
|
with_form_for @user, :name, error: 'error must contain <b>markup</b>'.html_safe
|
233
268
|
|
234
269
|
assert_select 'span.error'
|
@@ -237,7 +272,7 @@ class ErrorTest < ActionView::TestCase
|
|
237
272
|
end
|
238
273
|
|
239
274
|
test 'input with custom error when using full_error component does not generate the error if there is no error on the attribute' do
|
240
|
-
swap_wrapper :default,
|
275
|
+
swap_wrapper :default, custom_wrapper_with_full_error do
|
241
276
|
with_form_for @user, :active, error: "Super User Active! can't be blank"
|
242
277
|
|
243
278
|
assert_no_select 'span.error'
|