simple_form 3.4.0 → 4.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 +4 -4
- data/CHANGELOG.md +44 -0
- data/README.md +208 -36
- 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 +15 -2
- data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +358 -73
- data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +20 -8
- data/lib/simple_form/action_view_extensions/builder.rb +1 -0
- data/lib/simple_form/action_view_extensions/form_helper.rb +1 -0
- data/lib/simple_form/components/errors.rb +10 -1
- data/lib/simple_form/components/hints.rb +1 -0
- data/lib/simple_form/components/html5.rb +1 -0
- data/lib/simple_form/components/label_input.rb +2 -1
- data/lib/simple_form/components/labels.rb +11 -4
- data/lib/simple_form/components/maxlength.rb +4 -13
- data/lib/simple_form/components/min_max.rb +1 -0
- data/lib/simple_form/components/minlength.rb +5 -14
- 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 +1 -0
- data/lib/simple_form/error_notification.rb +1 -0
- data/lib/simple_form/form_builder.rb +74 -19
- 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 +20 -1
- data/lib/simple_form/inputs/block_input.rb +1 -0
- data/lib/simple_form/inputs/boolean_input.rb +3 -2
- data/lib/simple_form/inputs/collection_check_boxes_input.rb +2 -1
- data/lib/simple_form/inputs/collection_input.rb +3 -2
- data/lib/simple_form/inputs/collection_radio_buttons_input.rb +2 -1
- data/lib/simple_form/inputs/collection_select_input.rb +1 -0
- data/lib/simple_form/inputs/date_time_input.rb +1 -0
- 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 +1 -0
- data/lib/simple_form/inputs/priority_input.rb +1 -0
- data/lib/simple_form/inputs/range_input.rb +1 -0
- data/lib/simple_form/inputs/string_input.rb +1 -0
- data/lib/simple_form/inputs/text_input.rb +1 -0
- data/lib/simple_form/inputs.rb +1 -0
- data/lib/simple_form/map_type.rb +1 -0
- data/lib/simple_form/railtie.rb +1 -0
- data/lib/simple_form/tags.rb +1 -0
- 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 +58 -7
- data/test/action_view_extensions/builder_test.rb +6 -5
- 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 +27 -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 +6 -0
- data/test/form_builder/general_test.rb +61 -3
- data/test/form_builder/hint_test.rb +6 -0
- data/test/form_builder/input_field_test.rb +27 -1
- data/test/form_builder/label_test.rb +9 -3
- data/test/form_builder/wrapper_test.rb +24 -4
- data/test/generators/simple_form_generator_test.rb +4 -3
- data/test/inputs/boolean_input_test.rb +9 -0
- data/test/inputs/collection_check_boxes_input_test.rb +30 -14
- data/test/inputs/collection_radio_buttons_input_test.rb +40 -24
- data/test/inputs/collection_select_input_test.rb +40 -39
- data/test/inputs/datetime_input_test.rb +5 -4
- data/test/inputs/disabled_test.rb +1 -0
- data/test/inputs/discovery_test.rb +1 -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 +2 -1
- data/test/inputs/priority_input_test.rb +1 -0
- data/test/inputs/readonly_test.rb +1 -0
- data/test/inputs/required_test.rb +1 -0
- data/test/inputs/string_input_test.rb +2 -1
- data/test/inputs/text_input_test.rb +1 -0
- data/test/simple_form_test.rb +1 -0
- data/test/support/discovery_inputs.rb +1 -0
- data/test/support/misc_helpers.rb +16 -1
- data/test/support/mock_controller.rb +7 -1
- data/test/support/models.rb +53 -14
- data/test/test_helper.rb +2 -0
- metadata +5 -15
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'
|
|
@@ -58,11 +60,11 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
|
58
60
|
|
|
59
61
|
# Series of attemps to detect a default label method for collection.
|
|
60
62
|
mattr_accessor :collection_label_methods
|
|
61
|
-
@@collection_label_methods = [
|
|
63
|
+
@@collection_label_methods = %i[to_label name title to_s]
|
|
62
64
|
|
|
63
65
|
# Series of attemps to detect a default value method for collection.
|
|
64
66
|
mattr_accessor :collection_value_methods
|
|
65
|
-
@@collection_value_methods = [
|
|
67
|
+
@@collection_value_methods = %i[id to_s]
|
|
66
68
|
|
|
67
69
|
# You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
|
|
68
70
|
mattr_accessor :collection_wrapper_tag
|
|
@@ -84,7 +86,7 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
|
84
86
|
|
|
85
87
|
# How the label text should be generated altogether with the required text.
|
|
86
88
|
mattr_accessor :label_text
|
|
87
|
-
@@label_text =
|
|
89
|
+
@@label_text = ->(label, required, explicit_label) { "#{required} #{label}" }
|
|
88
90
|
|
|
89
91
|
# You can define the class to be used on all labels. Defaults to none.
|
|
90
92
|
mattr_accessor :label_class
|
|
@@ -108,7 +110,7 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
|
108
110
|
|
|
109
111
|
# You can define which elements should obtain additional classes.
|
|
110
112
|
mattr_accessor :generate_additional_classes_for
|
|
111
|
-
@@generate_additional_classes_for = [
|
|
113
|
+
@@generate_additional_classes_for = %i[wrapper label input]
|
|
112
114
|
|
|
113
115
|
# Whether attributes are required by default or not.
|
|
114
116
|
mattr_accessor :required_by_default
|
|
@@ -120,7 +122,7 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
|
120
122
|
|
|
121
123
|
# Collection of methods to detect if a file type was given.
|
|
122
124
|
mattr_accessor :file_methods
|
|
123
|
-
@@file_methods = [
|
|
125
|
+
@@file_methods = %i[mounted_as file? public_filename attached?]
|
|
124
126
|
|
|
125
127
|
# Custom mappings for input types. This should be a hash containing a regexp
|
|
126
128
|
# to match as key, and the input type that will be used when the field name
|
|
@@ -163,7 +165,7 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
|
163
165
|
|
|
164
166
|
# Cache SimpleForm inputs discovery.
|
|
165
167
|
mattr_accessor :cache_discovery
|
|
166
|
-
@@cache_discovery = defined?(Rails) && !Rails.env.development?
|
|
168
|
+
@@cache_discovery = defined?(Rails.env) && !Rails.env.development?
|
|
167
169
|
|
|
168
170
|
# Adds a class to each generated button, mostly for compatiblity.
|
|
169
171
|
mattr_accessor :button_class
|
|
@@ -198,6 +200,12 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
|
198
200
|
mattr_accessor :i18n_scope
|
|
199
201
|
@@i18n_scope = 'simple_form'
|
|
200
202
|
|
|
203
|
+
mattr_accessor :input_field_error_class
|
|
204
|
+
@@input_field_error_class = nil
|
|
205
|
+
|
|
206
|
+
mattr_accessor :input_field_valid_class
|
|
207
|
+
@@input_field_valid_class = nil
|
|
208
|
+
|
|
201
209
|
# Retrieves a given wrapper
|
|
202
210
|
def self.wrapper(name)
|
|
203
211
|
@@wrappers[name.to_s] or raise WrapperNotFound, "Couldn't find wrapper with name #{name}"
|
|
@@ -227,7 +235,7 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
|
227
235
|
SimpleForm::Wrappers::Root.new(builder.to_a, options)
|
|
228
236
|
end
|
|
229
237
|
|
|
230
|
-
wrappers class: :input, hint_class: :field_with_hint, error_class: :field_with_errors do |b|
|
|
238
|
+
wrappers class: :input, hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b|
|
|
231
239
|
b.use :html5
|
|
232
240
|
|
|
233
241
|
b.use :min_max
|
|
@@ -263,6 +271,49 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
|
263
271
|
@@configured = true
|
|
264
272
|
yield self
|
|
265
273
|
end
|
|
274
|
+
|
|
275
|
+
# Includes a component to be used by Simple Form. Methods defined in a
|
|
276
|
+
# component will be exposed to be used in the wrapper as Simple::Components
|
|
277
|
+
#
|
|
278
|
+
# Examples
|
|
279
|
+
#
|
|
280
|
+
# # The application needs to tell where the components will be.
|
|
281
|
+
# Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
|
|
282
|
+
#
|
|
283
|
+
# # Create a custom component in the path specified above.
|
|
284
|
+
# # lib/components/input_group_component.rb
|
|
285
|
+
# module InputGroupComponent
|
|
286
|
+
# def prepend
|
|
287
|
+
# ...
|
|
288
|
+
# end
|
|
289
|
+
#
|
|
290
|
+
# def append
|
|
291
|
+
# ...
|
|
292
|
+
# end
|
|
293
|
+
# end
|
|
294
|
+
#
|
|
295
|
+
# SimpleForm.setup do |config|
|
|
296
|
+
# # Create a wrapper using the custom component.
|
|
297
|
+
# config.wrappers :input_group, tag: :div, error_class: :error do |b|
|
|
298
|
+
# b.use :label
|
|
299
|
+
# b.optional :prepend
|
|
300
|
+
# b.use :input
|
|
301
|
+
# b.use :append
|
|
302
|
+
# end
|
|
303
|
+
# end
|
|
304
|
+
#
|
|
305
|
+
# # Using the custom component in the form.
|
|
306
|
+
# <%= simple_form_for @blog, wrapper: input_group do |f| %>
|
|
307
|
+
# <%= f.input :title, prepend: true %>
|
|
308
|
+
# <% end %>
|
|
309
|
+
#
|
|
310
|
+
def self.include_component(component)
|
|
311
|
+
if Module === component
|
|
312
|
+
SimpleForm::Inputs::Base.include(component)
|
|
313
|
+
else
|
|
314
|
+
raise TypeError, "SimpleForm.include_component expects a module but got: #{component.class}"
|
|
315
|
+
end
|
|
316
|
+
end
|
|
266
317
|
end
|
|
267
318
|
|
|
268
319
|
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'
|
|
@@ -243,7 +244,7 @@ class BuilderTest < ActionView::TestCase
|
|
|
243
244
|
|
|
244
245
|
test "collection radio with block helpers does not leak the template" do
|
|
245
246
|
with_concat_form_for(@user) do |f|
|
|
246
|
-
collection_input =
|
|
247
|
+
collection_input = f.collection_radio_buttons :active, [true, false], :to_s, :to_s do |b|
|
|
247
248
|
b.label(class: b.object) { b.radio_button + b.text }
|
|
248
249
|
end
|
|
249
250
|
concat collection_input
|
|
@@ -283,7 +284,7 @@ class BuilderTest < ActionView::TestCase
|
|
|
283
284
|
end
|
|
284
285
|
|
|
285
286
|
test "collection check box handles camelized collection values for labels correctly" do
|
|
286
|
-
with_collection_check_boxes @user, :active, [
|
|
287
|
+
with_collection_check_boxes @user, :active, %w[Yes No], :to_s, :to_s
|
|
287
288
|
|
|
288
289
|
assert_select 'form label.collection_check_boxes[for=user_active_yes]', 'Yes'
|
|
289
290
|
assert_select 'form label.collection_check_boxes[for=user_active_no]', 'No'
|
|
@@ -317,7 +318,7 @@ class BuilderTest < ActionView::TestCase
|
|
|
317
318
|
|
|
318
319
|
test "collection check boxes accepts selected string values as :checked option" do
|
|
319
320
|
collection = (1..3).map { |i| [i, "Category #{i}"] }
|
|
320
|
-
with_collection_check_boxes :user, :category_ids, collection, :first, :last, checked: [
|
|
321
|
+
with_collection_check_boxes :user, :category_ids, collection, :first, :last, checked: %w[1 3]
|
|
321
322
|
|
|
322
323
|
assert_select 'input[type=checkbox][value="1"][checked=checked]'
|
|
323
324
|
assert_select 'input[type=checkbox][value="3"][checked=checked]'
|
|
@@ -541,7 +542,7 @@ class BuilderTest < ActionView::TestCase
|
|
|
541
542
|
|
|
542
543
|
test "collection check boxes with block helpers does not leak the template" do
|
|
543
544
|
with_concat_form_for(@user) do |f|
|
|
544
|
-
collection_input =
|
|
545
|
+
collection_input = f.collection_check_boxes :active, [true, false], :to_s, :to_s do |b|
|
|
545
546
|
b.label(class: b.object) { b.check_box + b.text }
|
|
546
547
|
end
|
|
547
548
|
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,12 @@ 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
|
|
221
246
|
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
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
# encoding: UTF-8
|
|
2
3
|
require 'test_helper'
|
|
3
4
|
|
|
@@ -30,6 +31,12 @@ class FormBuilderTest < ActionView::TestCase
|
|
|
30
31
|
end
|
|
31
32
|
end
|
|
32
33
|
|
|
34
|
+
test 'builder works with decorated object responsive to #to_model' do
|
|
35
|
+
assert_nothing_raised do
|
|
36
|
+
with_form_for @decorated_user, :name
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
33
40
|
test 'builder input allows a block to configure input' do
|
|
34
41
|
with_form_for @user, :name do
|
|
35
42
|
text_field_tag :foo, :bar, id: :cool
|
|
@@ -49,7 +56,7 @@ class FormBuilderTest < ActionView::TestCase
|
|
|
49
56
|
test 'builder does not override custom input mappings for custom collection' do
|
|
50
57
|
swap SimpleForm, input_mappings: { /gender$/ => :check_boxes } do
|
|
51
58
|
with_concat_form_for @user do |f|
|
|
52
|
-
f.input :gender, collection: [
|
|
59
|
+
f.input :gender, collection: %i[male female]
|
|
53
60
|
end
|
|
54
61
|
|
|
55
62
|
assert_no_select 'select option', 'Male'
|
|
@@ -58,7 +65,7 @@ class FormBuilderTest < ActionView::TestCase
|
|
|
58
65
|
end
|
|
59
66
|
|
|
60
67
|
test 'builder allows to skip input_type class' do
|
|
61
|
-
swap SimpleForm, generate_additional_classes_for: [
|
|
68
|
+
swap SimpleForm, generate_additional_classes_for: %i[label wrapper] do
|
|
62
69
|
with_form_for @user, :post_count
|
|
63
70
|
assert_no_select "form input#user_post_count.integer"
|
|
64
71
|
assert_select "form input#user_post_count"
|
|
@@ -119,9 +126,40 @@ class FormBuilderTest < ActionView::TestCase
|
|
|
119
126
|
|
|
120
127
|
test 'builder generates text areas for text columns' do
|
|
121
128
|
with_form_for @user, :description
|
|
129
|
+
assert_no_select 'form input#user_description.string'
|
|
130
|
+
assert_select 'form textarea#user_description.text'
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
test 'builder generates text areas for text columns when hinted' do
|
|
134
|
+
with_form_for @user, :description, as: :text
|
|
135
|
+
assert_no_select 'form input#user_description.string'
|
|
122
136
|
assert_select 'form textarea#user_description.text'
|
|
123
137
|
end
|
|
124
138
|
|
|
139
|
+
test 'builder generates text field for text columns when hinted' do
|
|
140
|
+
with_form_for @user, :description, as: :string
|
|
141
|
+
assert_no_select 'form textarea#user_description.text'
|
|
142
|
+
assert_select 'form input#user_description.string'
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
test 'builder generates text areas for hstore columns' do
|
|
146
|
+
with_form_for @user, :hstore
|
|
147
|
+
assert_no_select 'form input#user_hstore.string'
|
|
148
|
+
assert_select 'form textarea#user_hstore.text'
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
test 'builder generates text areas for json columns' do
|
|
152
|
+
with_form_for @user, :json
|
|
153
|
+
assert_no_select 'form input#user_json.string'
|
|
154
|
+
assert_select 'form textarea#user_json.text'
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
test 'builder generates text areas for jsonb columns' do
|
|
158
|
+
with_form_for @user, :jsonb
|
|
159
|
+
assert_no_select 'form input#user_jsonb.string'
|
|
160
|
+
assert_select 'form textarea#user_jsonb.text'
|
|
161
|
+
end
|
|
162
|
+
|
|
125
163
|
test 'builder generates a checkbox for boolean columns' do
|
|
126
164
|
with_form_for @user, :active
|
|
127
165
|
assert_select 'form input[type=checkbox]#user_active.boolean'
|
|
@@ -146,6 +184,11 @@ class FormBuilderTest < ActionView::TestCase
|
|
|
146
184
|
end
|
|
147
185
|
end
|
|
148
186
|
|
|
187
|
+
test 'builder generates string fields for citext columns' do
|
|
188
|
+
with_form_for @user, :citext
|
|
189
|
+
assert_select 'form input#user_citext.string'
|
|
190
|
+
end
|
|
191
|
+
|
|
149
192
|
test 'builder generates password fields for columns that matches password' do
|
|
150
193
|
with_form_for @user, :password
|
|
151
194
|
assert_select 'form input#user_password.password'
|
|
@@ -199,6 +242,16 @@ class FormBuilderTest < ActionView::TestCase
|
|
|
199
242
|
test 'builder generates file for file columns' do
|
|
200
243
|
@user.avatar = MiniTest::Mock.new
|
|
201
244
|
@user.avatar.expect(:public_filename, true)
|
|
245
|
+
@user.avatar.expect(:!, false)
|
|
246
|
+
|
|
247
|
+
with_form_for @user, :avatar
|
|
248
|
+
assert_select 'form input#user_avatar.file'
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
test 'builder generates file for activestorage entries' do
|
|
252
|
+
@user.avatar = MiniTest::Mock.new
|
|
253
|
+
@user.avatar.expect(:attached?, false)
|
|
254
|
+
@user.avatar.expect(:!, false)
|
|
202
255
|
|
|
203
256
|
with_form_for @user, :avatar
|
|
204
257
|
assert_select 'form input#user_avatar.file'
|
|
@@ -207,6 +260,7 @@ class FormBuilderTest < ActionView::TestCase
|
|
|
207
260
|
test 'builder generates file for attributes that are real db columns but have file methods' do
|
|
208
261
|
@user.home_picture = MiniTest::Mock.new
|
|
209
262
|
@user.home_picture.expect(:mounted_as, true)
|
|
263
|
+
@user.home_picture.expect(:!, false)
|
|
210
264
|
|
|
211
265
|
with_form_for @user, :home_picture
|
|
212
266
|
assert_select 'form input#user_home_picture.file'
|
|
@@ -221,11 +275,15 @@ class FormBuilderTest < ActionView::TestCase
|
|
|
221
275
|
with_form_for @user, :name, as: :text
|
|
222
276
|
assert_no_select 'form input#user_name'
|
|
223
277
|
assert_select 'form textarea#user_name.text'
|
|
278
|
+
end
|
|
224
279
|
|
|
280
|
+
test 'builder allows overriding default input type for radio_buttons' do
|
|
225
281
|
with_form_for @user, :active, as: :radio_buttons
|
|
226
282
|
assert_no_select 'form input[type=checkbox]'
|
|
227
283
|
assert_select 'form input.radio_buttons[type=radio]', count: 2
|
|
284
|
+
end
|
|
228
285
|
|
|
286
|
+
test 'builder allows overriding default input type for string' do
|
|
229
287
|
with_form_for @user, :born_at, as: :string
|
|
230
288
|
assert_no_select 'form select'
|
|
231
289
|
assert_select 'form input#user_born_at.string'
|
|
@@ -365,7 +423,7 @@ class FormBuilderTest < ActionView::TestCase
|
|
|
365
423
|
end
|
|
366
424
|
|
|
367
425
|
# DEFAULT OPTIONS
|
|
368
|
-
[
|
|
426
|
+
%i[input input_field].each do |method|
|
|
369
427
|
test "builder receives a default argument and pass it to the inputs when calling '#{method}'" do
|
|
370
428
|
with_concat_form_for @user, defaults: { input_html: { class: 'default_class' } } do |f|
|
|
371
429
|
f.public_send(method, :name)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'test_helper'
|
|
2
3
|
|
|
3
4
|
# Tests for f.hint
|
|
@@ -18,6 +19,11 @@ class HintTest < ActionView::TestCase
|
|
|
18
19
|
assert_select 'span.hint', 'Use with care...'
|
|
19
20
|
end
|
|
20
21
|
|
|
22
|
+
test 'hint is generated with decorated object responsive to #to_model' do
|
|
23
|
+
with_hint_for @decorated_user, :name, hint: 'Use with care...'
|
|
24
|
+
assert_select 'span.hint', 'Use with care...'
|
|
25
|
+
end
|
|
26
|
+
|
|
21
27
|
test 'hint does not modify the options hash' do
|
|
22
28
|
options = { hint: 'Use with care...' }
|
|
23
29
|
with_hint_for @user, :name, options
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'test_helper'
|
|
2
3
|
|
|
3
4
|
# Tests for f.input_field
|
|
@@ -112,7 +113,7 @@ class InputFieldTest < ActionView::TestCase
|
|
|
112
113
|
end
|
|
113
114
|
|
|
114
115
|
test 'builder collection input_field generates input tag with a clean HTML' do
|
|
115
|
-
with_input_field_for @user, :status, collection: [
|
|
116
|
+
with_input_field_for @user, :status, collection: %w[Open Closed],
|
|
116
117
|
class: 'status', label_method: :to_s, value_method: :to_s
|
|
117
118
|
|
|
118
119
|
assert_no_select 'select.status[input_html]'
|
|
@@ -172,4 +173,29 @@ class InputFieldTest < ActionView::TestCase
|
|
|
172
173
|
assert_select 'input[readonly="readonly"]'
|
|
173
174
|
end
|
|
174
175
|
end
|
|
176
|
+
|
|
177
|
+
test 'adds valid class to input_field when it is configured' do
|
|
178
|
+
swap SimpleForm, input_field_valid_class: 'is-valid' do
|
|
179
|
+
@user.instance_eval { undef errors }
|
|
180
|
+
with_input_field_for @user, :name
|
|
181
|
+
|
|
182
|
+
assert_select 'input.string.required.is-valid'
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
test 'adds error class to input_field when it is configured' do
|
|
187
|
+
swap SimpleForm, input_field_error_class: 'is-invalid' do
|
|
188
|
+
with_input_field_for @user, :name
|
|
189
|
+
|
|
190
|
+
assert_select 'input.string.required.is-invalid'
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
test 'does not add validation classes to input_field when it is not configured' do
|
|
195
|
+
swap SimpleForm, input_field_error_class: nil, input_field_valid_class: nil do
|
|
196
|
+
with_input_field_for @user, :name
|
|
197
|
+
|
|
198
|
+
assert_select 'input.string.required'
|
|
199
|
+
end
|
|
200
|
+
end
|
|
175
201
|
end
|