simple_form 3.0.4 → 5.0.3
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 +199 -33
- data/MIT-LICENSE +2 -1
- data/README.md +453 -128
- data/lib/generators/simple_form/install_generator.rb +4 -3
- data/lib/generators/simple_form/templates/README +3 -5
- 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 +47 -16
- data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +418 -23
- data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +101 -5
- data/lib/generators/simple_form/templates/config/locales/simple_form.en.yml +7 -2
- data/lib/simple_form/action_view_extensions/builder.rb +2 -0
- data/lib/simple_form/action_view_extensions/form_helper.rb +10 -3
- data/lib/simple_form/components/errors.rb +39 -6
- data/lib/simple_form/components/hints.rb +3 -2
- data/lib/simple_form/components/html5.rb +16 -5
- data/lib/simple_form/components/label_input.rb +21 -2
- data/lib/simple_form/components/labels.rb +22 -11
- data/lib/simple_form/components/maxlength.rb +9 -5
- data/lib/simple_form/components/min_max.rb +2 -1
- data/lib/simple_form/components/minlength.rb +38 -0
- data/lib/simple_form/components/pattern.rb +2 -1
- data/lib/simple_form/components/placeholders.rb +4 -3
- data/lib/simple_form/components/readonly.rb +2 -1
- data/lib/simple_form/components.rb +2 -0
- data/lib/simple_form/error_notification.rb +1 -0
- data/lib/simple_form/form_builder.rb +220 -89
- 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 +6 -5
- data/lib/simple_form/i18n_cache.rb +1 -0
- data/lib/simple_form/inputs/base.rb +62 -16
- data/lib/simple_form/inputs/block_input.rb +2 -1
- data/lib/simple_form/inputs/boolean_input.rb +40 -16
- data/lib/simple_form/inputs/collection_check_boxes_input.rb +3 -2
- data/lib/simple_form/inputs/collection_input.rb +37 -14
- data/lib/simple_form/inputs/collection_radio_buttons_input.rb +9 -13
- data/lib/simple_form/inputs/collection_select_input.rb +5 -2
- data/lib/simple_form/inputs/color_input.rb +14 -0
- data/lib/simple_form/inputs/date_time_input.rb +24 -9
- data/lib/simple_form/inputs/file_input.rb +5 -2
- data/lib/simple_form/inputs/grouped_collection_select_input.rb +16 -3
- data/lib/simple_form/inputs/hidden_input.rb +5 -2
- data/lib/simple_form/inputs/numeric_input.rb +6 -4
- data/lib/simple_form/inputs/password_input.rb +6 -3
- data/lib/simple_form/inputs/priority_input.rb +5 -6
- data/lib/simple_form/inputs/range_input.rb +2 -1
- data/lib/simple_form/inputs/rich_text_area_input.rb +12 -0
- data/lib/simple_form/inputs/string_input.rb +7 -4
- data/lib/simple_form/inputs/text_input.rb +6 -3
- data/lib/simple_form/inputs.rb +3 -0
- data/lib/simple_form/map_type.rb +1 -0
- data/lib/simple_form/railtie.rb +8 -0
- data/lib/simple_form/tags.rb +13 -2
- data/lib/simple_form/version.rb +2 -1
- data/lib/simple_form/wrappers/builder.rb +7 -6
- data/lib/simple_form/wrappers/leaf.rb +29 -0
- data/lib/simple_form/wrappers/many.rb +7 -6
- data/lib/simple_form/wrappers/root.rb +10 -3
- data/lib/simple_form/wrappers/single.rb +7 -4
- data/lib/simple_form/wrappers.rb +2 -0
- data/lib/simple_form.rb +137 -21
- data/test/action_view_extensions/builder_test.rb +64 -45
- data/test/action_view_extensions/form_helper_test.rb +36 -16
- data/test/components/custom_components_test.rb +62 -0
- data/test/components/label_test.rb +70 -41
- data/test/form_builder/association_test.rb +85 -37
- data/test/form_builder/button_test.rb +11 -10
- data/test/form_builder/error_notification_test.rb +2 -1
- data/test/form_builder/error_test.rb +146 -33
- data/test/form_builder/general_test.rb +183 -81
- data/test/form_builder/hint_test.rb +24 -18
- data/test/form_builder/input_field_test.rb +105 -75
- data/test/form_builder/label_test.rb +68 -13
- data/test/form_builder/wrapper_test.rb +197 -22
- data/test/generators/simple_form_generator_test.rb +8 -7
- data/test/inputs/boolean_input_test.rb +97 -6
- data/test/inputs/collection_check_boxes_input_test.rb +117 -25
- data/test/inputs/collection_radio_buttons_input_test.rb +176 -54
- data/test/inputs/collection_select_input_test.rb +189 -77
- data/test/inputs/color_input_test.rb +10 -0
- data/test/inputs/datetime_input_test.rb +121 -50
- data/test/inputs/disabled_test.rb +29 -15
- data/test/inputs/discovery_test.rb +79 -6
- data/test/inputs/file_input_test.rb +3 -2
- data/test/inputs/general_test.rb +23 -22
- data/test/inputs/grouped_collection_select_input_test.rb +54 -17
- data/test/inputs/hidden_input_test.rb +5 -4
- data/test/inputs/numeric_input_test.rb +48 -44
- data/test/inputs/priority_input_test.rb +17 -16
- data/test/inputs/readonly_test.rb +20 -19
- data/test/inputs/required_test.rb +58 -13
- data/test/inputs/rich_text_area_input_test.rb +15 -0
- data/test/inputs/string_input_test.rb +58 -36
- data/test/inputs/text_input_test.rb +20 -7
- data/test/simple_form_test.rb +9 -0
- data/test/support/discovery_inputs.rb +40 -2
- data/test/support/misc_helpers.rb +113 -5
- data/test/support/mock_controller.rb +7 -1
- data/test/support/models.rb +162 -39
- data/test/test_helper.rb +19 -4
- metadata +51 -43
@@ -1,27 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'test_helper'
|
2
3
|
|
3
4
|
class RequiredTest < ActionView::TestCase
|
4
5
|
# REQUIRED AND PRESENCE VALIDATION
|
5
|
-
test 'builder input
|
6
|
+
test 'builder input obtains required from ActiveModel::Validations when it is included' do
|
6
7
|
with_form_for @validating_user, :name
|
7
8
|
assert_select 'input.required[required]#validating_user_name'
|
8
9
|
with_form_for @validating_user, :status
|
9
10
|
assert_select 'input.optional#validating_user_status'
|
10
11
|
end
|
11
12
|
|
12
|
-
test 'builder input
|
13
|
+
test 'builder input allows overriding required when ActiveModel::Validations is included' do
|
13
14
|
with_form_for @validating_user, :name, required: false
|
14
15
|
assert_select 'input.optional#validating_user_name'
|
15
16
|
with_form_for @validating_user, :status, required: true
|
16
17
|
assert_select 'input.required[required]#validating_user_status'
|
17
18
|
end
|
18
19
|
|
19
|
-
test 'builder input
|
20
|
+
test 'builder input is required by default when ActiveModel::Validations is not included' do
|
20
21
|
with_form_for @user, :name
|
21
22
|
assert_select 'input.required[required]#user_name'
|
22
23
|
end
|
23
24
|
|
24
|
-
test 'builder input
|
25
|
+
test 'builder input does not be required by default when ActiveModel::Validations is not included if option is set to false' do
|
25
26
|
swap SimpleForm, required_by_default: false do
|
26
27
|
with_form_for @user, :name
|
27
28
|
assert_select 'input.optional#user_name'
|
@@ -29,15 +30,47 @@ class RequiredTest < ActionView::TestCase
|
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
32
|
-
test 'when not using browser validations, input
|
33
|
+
test 'when not using browser validations, input does not generate required html attribute' do
|
33
34
|
swap SimpleForm, browser_validations: false do
|
34
35
|
with_input_for @user, :name, :string
|
35
36
|
assert_select 'input[type=text].required'
|
36
37
|
assert_no_select 'input[type=text][required]'
|
38
|
+
assert_no_select 'input[type=text][aria-required]'
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
|
-
test '
|
42
|
+
test 'when not using browser validations, when required option is set to false, input does not generate required html attribute' do
|
43
|
+
swap SimpleForm, browser_validations: false do
|
44
|
+
with_input_for @user, :name, :string, required: false
|
45
|
+
assert_no_select 'input[type=text].required'
|
46
|
+
assert_no_select 'input[type=text][required]'
|
47
|
+
assert_no_select 'input[type=text][aria-required]'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
test 'when not using browser validations, when required option is set to true, input generates required html attribute' do
|
52
|
+
swap SimpleForm, browser_validations: false do
|
53
|
+
with_input_for @user, :name, :string, required: true
|
54
|
+
assert_select 'input[type=text].required'
|
55
|
+
assert_select 'input[type=text][required]'
|
56
|
+
assert_select 'input[type=text][aria-required]'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
test 'when not using browser validations, when required option is true in the wrapper, input does not generate required html attribute' do
|
61
|
+
swap SimpleForm, browser_validations: false do
|
62
|
+
swap_wrapper :default, self.custom_wrapper_with_required_input do
|
63
|
+
with_concat_form_for(@user) do |f|
|
64
|
+
concat f.input :name
|
65
|
+
end
|
66
|
+
assert_select 'input[type=text].required'
|
67
|
+
assert_no_select 'input[type=text][required]'
|
68
|
+
assert_no_select 'input[type=text][aria-required]'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
test 'builder input allows disabling required when ActiveModel::Validations is not included' do
|
41
74
|
with_form_for @user, :name, required: false
|
42
75
|
assert_no_select 'input.required'
|
43
76
|
assert_no_select 'input[required]'
|
@@ -53,14 +86,14 @@ class RequiredTest < ActionView::TestCase
|
|
53
86
|
end
|
54
87
|
|
55
88
|
# VALIDATORS :if :unless
|
56
|
-
test 'builder input
|
89
|
+
test 'builder input does not be required when ActiveModel::Validations is included and if option is present' do
|
57
90
|
with_form_for @validating_user, :age
|
58
91
|
assert_no_select 'input.required'
|
59
92
|
assert_no_select 'input[required]'
|
60
93
|
assert_select 'input.optional#validating_user_age'
|
61
94
|
end
|
62
95
|
|
63
|
-
test 'builder input
|
96
|
+
test 'builder input does not be required when ActiveModel::Validations is included and unless option is present' do
|
64
97
|
with_form_for @validating_user, :amount
|
65
98
|
assert_no_select 'input.required'
|
66
99
|
assert_no_select 'input[required]'
|
@@ -68,7 +101,7 @@ class RequiredTest < ActionView::TestCase
|
|
68
101
|
end
|
69
102
|
|
70
103
|
# VALIDATORS :on
|
71
|
-
test 'builder input
|
104
|
+
test 'builder input is required when validation is on create and is not persisted' do
|
72
105
|
@validating_user.new_record!
|
73
106
|
with_form_for @validating_user, :action
|
74
107
|
assert_select 'input.required'
|
@@ -76,14 +109,14 @@ class RequiredTest < ActionView::TestCase
|
|
76
109
|
assert_select 'input.required[required]#validating_user_action'
|
77
110
|
end
|
78
111
|
|
79
|
-
test 'builder input
|
112
|
+
test 'builder input does not be required when validation is on create and is persisted' do
|
80
113
|
with_form_for @validating_user, :action
|
81
114
|
assert_no_select 'input.required'
|
82
115
|
assert_no_select 'input[required]'
|
83
116
|
assert_select 'input.optional#validating_user_action'
|
84
117
|
end
|
85
118
|
|
86
|
-
test 'builder input
|
119
|
+
test 'builder input is required when validation is on save' do
|
87
120
|
with_form_for @validating_user, :credit_limit
|
88
121
|
assert_select 'input.required'
|
89
122
|
assert_select 'input[required]'
|
@@ -96,18 +129,30 @@ class RequiredTest < ActionView::TestCase
|
|
96
129
|
assert_select 'input.required[required]#validating_user_credit_limit'
|
97
130
|
end
|
98
131
|
|
99
|
-
test 'builder input
|
132
|
+
test 'builder input is required when validation is on update and is persisted' do
|
100
133
|
with_form_for @validating_user, :phone_number
|
101
134
|
assert_select 'input.required'
|
102
135
|
assert_select 'input[required]'
|
103
136
|
assert_select 'input.required[required]#validating_user_phone_number'
|
104
137
|
end
|
105
138
|
|
106
|
-
test 'builder input
|
139
|
+
test 'builder input does not be required when validation is on update and is not persisted' do
|
107
140
|
@validating_user.new_record!
|
108
141
|
with_form_for @validating_user, :phone_number
|
109
142
|
assert_no_select 'input.required'
|
110
143
|
assert_no_select 'input[required]'
|
111
144
|
assert_select 'input.optional#validating_user_phone_number'
|
112
145
|
end
|
146
|
+
|
147
|
+
test 'builder input does not generate required html attribute when option is set to false when it is set to true in wrapper' do
|
148
|
+
swap SimpleForm, browser_validations: true do
|
149
|
+
swap_wrapper :default, self.custom_wrapper_with_required_input do
|
150
|
+
with_concat_form_for(@user) do |f|
|
151
|
+
concat f.input :name, required: false
|
152
|
+
end
|
153
|
+
assert_no_select 'input[type=text][required]'
|
154
|
+
assert_no_select 'input[type=text][aria-required]'
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
113
158
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# encoding: UTF-8
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class RichTextAreaInputTest < ActionView::TestCase
|
6
|
+
test 'input generates a text area for text attributes' do
|
7
|
+
with_input_for @user, :description, :text
|
8
|
+
assert_select 'textarea.text#user_description'
|
9
|
+
end
|
10
|
+
|
11
|
+
test 'input generates a text area for text attributes that accept placeholder' do
|
12
|
+
with_input_for @user, :description, :text, placeholder: 'Put in some text'
|
13
|
+
assert_select 'textarea.text[placeholder="Put in some text"]'
|
14
|
+
end
|
15
|
+
end
|
@@ -1,117 +1,139 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# encoding: UTF-8
|
2
3
|
require 'test_helper'
|
3
4
|
|
4
5
|
class StringInputTest < ActionView::TestCase
|
5
|
-
test 'input
|
6
|
+
test 'input maps text field to string attribute' do
|
6
7
|
with_input_for @user, :name, :string
|
7
|
-
assert_select "input#user_name[type=text][name='user[name]'][value=New in SimpleForm!]"
|
8
|
+
assert_select "input#user_name[type=text][name='user[name]'][value='New in SimpleForm!']"
|
8
9
|
end
|
9
10
|
|
10
|
-
test 'input
|
11
|
+
test 'input maps text field to citext attribute' do
|
12
|
+
with_input_for @user, :name, :citext
|
13
|
+
assert_select "input#user_name[type=text][name='user[name]'][value='New in SimpleForm!']"
|
14
|
+
end
|
15
|
+
|
16
|
+
test 'input generates a password field for password attributes' do
|
11
17
|
with_input_for @user, :password, :password
|
12
18
|
assert_select "input#user_password.password[type=password][name='user[password]']"
|
13
19
|
end
|
14
20
|
|
15
|
-
test 'input
|
21
|
+
test 'input gets maxlength from column definition for string attributes' do
|
16
22
|
with_input_for @user, :name, :string
|
17
|
-
assert_select 'input.string[maxlength=100]'
|
23
|
+
assert_select 'input.string[maxlength="100"]'
|
18
24
|
end
|
19
25
|
|
20
|
-
test 'input
|
26
|
+
test 'input does not get maxlength from column without size definition for string attributes' do
|
21
27
|
with_input_for @user, :action, :string
|
22
28
|
assert_no_select 'input.string[maxlength]'
|
23
29
|
end
|
24
30
|
|
25
|
-
test 'input
|
31
|
+
test 'input gets maxlength from column definition for password attributes' do
|
26
32
|
with_input_for @user, :password, :password
|
27
|
-
assert_select 'input.password[type=password][maxlength=100]'
|
33
|
+
assert_select 'input.password[type=password][maxlength="100"]'
|
28
34
|
end
|
29
35
|
|
30
|
-
test 'input
|
36
|
+
test 'input infers maxlength column definition from validation when present' do
|
31
37
|
with_input_for @validating_user, :name, :string
|
32
|
-
assert_select 'input.string[maxlength=25]'
|
38
|
+
assert_select 'input.string[maxlength="25"]'
|
33
39
|
end
|
34
40
|
|
35
|
-
test 'input
|
36
|
-
with_input_for @validating_user, :
|
37
|
-
|
41
|
+
test 'input infers minlength column definition from validation when present' do
|
42
|
+
with_input_for @validating_user, :name, :string
|
43
|
+
assert_select 'input.string[minlength="5"]'
|
44
|
+
end
|
45
|
+
|
46
|
+
test 'input gets maxlength from validation when :is option present' do
|
47
|
+
with_input_for @validating_user, :home_picture, :string
|
48
|
+
assert_select 'input.string[maxlength="12"]'
|
38
49
|
end
|
39
50
|
|
40
|
-
test 'input
|
51
|
+
test 'input gets minlength from validation when :is option present' do
|
41
52
|
with_input_for @validating_user, :home_picture, :string
|
42
|
-
assert_select 'input.string[
|
53
|
+
assert_select 'input.string[minlength="12"]'
|
43
54
|
end
|
44
55
|
|
45
|
-
test 'input maxlength
|
56
|
+
test 'input maxlength is the column limit plus one to make room for decimal point' do
|
46
57
|
with_input_for @user, :credit_limit, :string
|
47
58
|
|
48
|
-
assert_select
|
59
|
+
assert_select 'input.string[maxlength="16"]'
|
49
60
|
end
|
50
61
|
|
51
|
-
test 'input
|
62
|
+
test 'input does not generate placeholder by default' do
|
52
63
|
with_input_for @user, :name, :string
|
53
64
|
assert_no_select 'input[placeholder]'
|
54
65
|
end
|
55
66
|
|
56
|
-
test 'input
|
67
|
+
test 'input accepts the placeholder option' do
|
57
68
|
with_input_for @user, :name, :string, placeholder: 'Put in some text'
|
58
|
-
assert_select 'input.string[placeholder=Put in some text]'
|
69
|
+
assert_select 'input.string[placeholder="Put in some text"]'
|
59
70
|
end
|
60
71
|
|
61
|
-
test 'input
|
72
|
+
test 'input generates a password field for password attributes that accept placeholder' do
|
62
73
|
with_input_for @user, :password, :password, placeholder: 'Password Confirmation'
|
63
|
-
assert_select 'input[type=password].password[placeholder=Password Confirmation]#user_password'
|
74
|
+
assert_select 'input[type=password].password[placeholder="Password Confirmation"]#user_password'
|
64
75
|
end
|
65
76
|
|
66
|
-
test 'input
|
77
|
+
test 'input does not infer pattern from attributes by default' do
|
67
78
|
with_input_for @other_validating_user, :country, :string
|
68
79
|
assert_no_select 'input[pattern="\w+"]'
|
69
80
|
end
|
70
81
|
|
71
|
-
test 'input
|
82
|
+
test 'input infers pattern from attributes' do
|
72
83
|
with_input_for @other_validating_user, :country, :string, pattern: true
|
73
|
-
assert_select '
|
84
|
+
assert_select "input:match('pattern', ?)", /\w+/
|
74
85
|
end
|
75
86
|
|
76
|
-
test 'input
|
87
|
+
test 'input infers pattern from attributes using proc' do
|
77
88
|
with_input_for @other_validating_user, :name, :string, pattern: true
|
78
|
-
assert_select '
|
89
|
+
assert_select "input:match('pattern', ?)", /\w+/
|
79
90
|
end
|
80
91
|
|
81
|
-
test 'input
|
92
|
+
test 'input does not infer pattern from attributes if root default is false' do
|
82
93
|
swap_wrapper do
|
83
94
|
with_input_for @other_validating_user, :country, :string
|
84
95
|
assert_no_select 'input[pattern="\w+"]'
|
85
96
|
end
|
86
97
|
end
|
87
98
|
|
88
|
-
test 'input
|
99
|
+
test 'input uses given pattern from attributes' do
|
89
100
|
with_input_for @other_validating_user, :country, :string, input_html: { pattern: "\\d+" }
|
90
|
-
assert_select '
|
101
|
+
assert_select "input:match('pattern', ?)", /\\d+/
|
91
102
|
end
|
92
103
|
|
93
|
-
test 'input
|
104
|
+
test 'input does not use pattern if model has :without validation option' do
|
94
105
|
with_input_for @other_validating_user, :description, :string, pattern: true
|
95
106
|
assert_no_select 'input[pattern="\d+"]'
|
96
107
|
end
|
97
108
|
|
98
|
-
test 'input
|
109
|
+
test 'input uses i18n to translate placeholder text' do
|
99
110
|
store_translations(:en, simple_form: { placeholders: { user: {
|
100
111
|
name: 'Name goes here'
|
101
112
|
} } }) do
|
102
113
|
with_input_for @user, :name, :string
|
103
|
-
assert_select 'input.string[placeholder=Name goes here]'
|
114
|
+
assert_select 'input.string[placeholder="Name goes here"]'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
test 'input uses custom i18n scope to translate placeholder text' do
|
119
|
+
store_translations(:en, my_scope: { placeholders: { user: {
|
120
|
+
name: 'Name goes here'
|
121
|
+
} } }) do
|
122
|
+
swap SimpleForm, i18n_scope: :my_scope do
|
123
|
+
with_input_for @user, :name, :string
|
124
|
+
assert_select 'input.string[placeholder="Name goes here"]'
|
125
|
+
end
|
104
126
|
end
|
105
127
|
end
|
106
128
|
|
107
|
-
[
|
108
|
-
test "input
|
129
|
+
%i[email url search tel].each do |type|
|
130
|
+
test "input allows type #{type}" do
|
109
131
|
with_input_for @user, :name, type
|
110
132
|
assert_select "input.string.#{type}"
|
111
133
|
assert_select "input[type=#{type}]"
|
112
134
|
end
|
113
135
|
|
114
|
-
test "input
|
136
|
+
test "input does not allow type #{type} if HTML5 compatibility is disabled" do
|
115
137
|
swap_wrapper do
|
116
138
|
with_input_for @user, :name, type
|
117
139
|
assert_select "input[type=text]"
|
@@ -1,24 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# encoding: UTF-8
|
2
3
|
require 'test_helper'
|
3
4
|
|
4
5
|
class TextInputTest < ActionView::TestCase
|
5
|
-
test 'input
|
6
|
+
test 'input generates a text area for text attributes' do
|
6
7
|
with_input_for @user, :description, :text
|
7
8
|
assert_select 'textarea.text#user_description'
|
8
9
|
end
|
9
10
|
|
10
|
-
test 'input
|
11
|
+
test 'input generates a text area for text attributes that accept placeholder' do
|
11
12
|
with_input_for @user, :description, :text, placeholder: 'Put in some text'
|
12
|
-
assert_select 'textarea.text[placeholder=Put in some text]'
|
13
|
+
assert_select 'textarea.text[placeholder="Put in some text"]'
|
13
14
|
end
|
14
15
|
|
15
|
-
test 'input
|
16
|
+
test 'input generates a placeholder from the translations' do
|
17
|
+
store_translations(:en, simple_form: { placeholders: { user: { name: "placeholder from i18n en.simple_form.placeholders.user.name" } } }) do
|
18
|
+
with_input_for @user, :name, :text
|
19
|
+
assert_select 'textarea.text[placeholder="placeholder from i18n en.simple_form.placeholders.user.name"]'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
test 'input gets maxlength from column definition for text attributes' do
|
16
24
|
with_input_for @user, :description, :text
|
17
|
-
assert_select 'textarea.text[maxlength=200]'
|
25
|
+
assert_select 'textarea.text[maxlength="200"]'
|
26
|
+
end
|
27
|
+
|
28
|
+
test 'input infers maxlength column definition from validation when present for text attributes' do
|
29
|
+
with_input_for @validating_user, :description, :text
|
30
|
+
assert_select 'textarea.text[maxlength="50"]'
|
18
31
|
end
|
19
32
|
|
20
|
-
test 'input
|
33
|
+
test 'input infers minlength column definition from validation when present for text attributes' do
|
21
34
|
with_input_for @validating_user, :description, :text
|
22
|
-
assert_select 'textarea.text[
|
35
|
+
assert_select 'textarea.text[minlength="15"]'
|
23
36
|
end
|
24
37
|
end
|
data/test/simple_form_test.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'test_helper'
|
2
3
|
|
3
4
|
class SimpleFormTest < ActiveSupport::TestCase
|
@@ -6,4 +7,12 @@ class SimpleFormTest < ActiveSupport::TestCase
|
|
6
7
|
assert_equal SimpleForm, config
|
7
8
|
end
|
8
9
|
end
|
10
|
+
|
11
|
+
test 'setup block configure Simple Form' do
|
12
|
+
SimpleForm.setup do |config|
|
13
|
+
assert_equal SimpleForm, config
|
14
|
+
end
|
15
|
+
|
16
|
+
assert_equal true, SimpleForm.configured?
|
17
|
+
end
|
9
18
|
end
|
@@ -1,16 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
class StringInput < SimpleForm::Inputs::StringInput
|
2
|
-
def input
|
3
|
+
def input(wrapper_options = nil)
|
3
4
|
"<section>#{super}</section>".html_safe
|
4
5
|
end
|
5
6
|
end
|
6
7
|
|
7
8
|
class NumericInput < SimpleForm::Inputs::NumericInput
|
8
|
-
def input
|
9
|
+
def input(wrapper_options = nil)
|
9
10
|
"<section>#{super}</section>".html_safe
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
13
14
|
class CustomizedInput < SimpleForm::Inputs::StringInput
|
15
|
+
def input(wrapper_options = nil)
|
16
|
+
"<section>#{super}</section>".html_safe
|
17
|
+
end
|
18
|
+
|
19
|
+
def input_method
|
20
|
+
:text_field
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class DeprecatedInput < SimpleForm::Inputs::StringInput
|
14
25
|
def input
|
15
26
|
"<section>#{super}</section>".html_safe
|
16
27
|
end
|
@@ -25,3 +36,30 @@ class CollectionSelectInput < SimpleForm::Inputs::CollectionSelectInput
|
|
25
36
|
super.push('chosen')
|
26
37
|
end
|
27
38
|
end
|
39
|
+
|
40
|
+
class FileInput < SimpleForm::Inputs::FileInput
|
41
|
+
def input_html_classes
|
42
|
+
super.delete_if { |html_class| html_class == :file }
|
43
|
+
super.push('file-upload')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
module CustomInputs
|
48
|
+
class CustomizedInput < SimpleForm::Inputs::StringInput
|
49
|
+
def input_html_classes
|
50
|
+
super.push('customized-namespace-custom-input')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class PasswordInput < SimpleForm::Inputs::PasswordInput
|
55
|
+
def input_html_classes
|
56
|
+
super.push('password-custom-input')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class NumericInput < SimpleForm::Inputs::PasswordInput
|
61
|
+
def input_html_classes
|
62
|
+
super.push('numeric-custom-input')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module MiscHelpers
|
2
3
|
def store_translations(locale, translations, &block)
|
3
4
|
I18n.backend.store_translations locale, translations
|
@@ -46,12 +47,12 @@ module MiscHelpers
|
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
49
|
-
def swap_wrapper(name
|
50
|
-
old = SimpleForm.wrappers[name]
|
51
|
-
SimpleForm.wrappers[name] = wrapper
|
50
|
+
def swap_wrapper(name = :default, wrapper = custom_wrapper)
|
51
|
+
old = SimpleForm.wrappers[name.to_s]
|
52
|
+
SimpleForm.wrappers[name.to_s] = wrapper
|
52
53
|
yield
|
53
54
|
ensure
|
54
|
-
SimpleForm.wrappers[name] = old
|
55
|
+
SimpleForm.wrappers[name.to_s] = old
|
55
56
|
end
|
56
57
|
|
57
58
|
def custom_wrapper
|
@@ -68,6 +69,62 @@ module MiscHelpers
|
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
72
|
+
def custom_wrapper_with_wrapped_optional_component
|
73
|
+
SimpleForm.build tag: :section, class: "custom_wrapper" do |b|
|
74
|
+
b.wrapper tag: :div, class: 'no_output_wrapper' do |ba|
|
75
|
+
ba.optional :hint, wrap_with: { tag: :p, class: 'omg_hint' }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def custom_wrapper_with_unless_blank
|
81
|
+
SimpleForm.build tag: :section, class: "custom_wrapper" do |b|
|
82
|
+
b.wrapper tag: :div, class: 'no_output_wrapper', unless_blank: true do |ba|
|
83
|
+
ba.optional :hint, wrap_with: { tag: :p, class: 'omg_hint' }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def custom_wrapper_with_input_class
|
89
|
+
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
90
|
+
b.use :label
|
91
|
+
b.use :input, class: 'inline-class'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def custom_wrapper_with_input_data_modal
|
96
|
+
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
97
|
+
b.use :label
|
98
|
+
b.use :input, data: { modal: 'data-modal', wrapper: 'data-wrapper' }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def custom_wrapper_with_input_aria_modal
|
103
|
+
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
104
|
+
b.use :label
|
105
|
+
b.use :input, aria: { modal: 'aria-modal', wrapper: 'aria-wrapper' }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def custom_wrapper_with_label_class
|
110
|
+
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
111
|
+
b.use :label, class: 'inline-class'
|
112
|
+
b.use :input
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def custom_wrapper_with_input_attributes
|
117
|
+
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
118
|
+
b.use :input, data: { modal: true }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def custom_wrapper_with_label_input_class
|
123
|
+
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
124
|
+
b.use :label_input, class: 'inline-class'
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
71
128
|
def custom_wrapper_with_wrapped_input
|
72
129
|
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
73
130
|
b.wrapper tag: :div, class: 'elem' do |component|
|
@@ -112,12 +169,57 @@ module MiscHelpers
|
|
112
169
|
end
|
113
170
|
end
|
114
171
|
|
172
|
+
def custom_wrapper_with_additional_attributes
|
173
|
+
SimpleForm.build tag: :div, class: 'custom_wrapper', html: { data: { wrapper: :test }, title: 'some title' } do |b|
|
174
|
+
b.use :label_input
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def custom_wrapper_with_full_error
|
179
|
+
SimpleForm.build tag: :div, class: 'custom_wrapper' do |b|
|
180
|
+
b.use :full_error, wrap_with: { tag: :span, class: :error }
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def custom_wrapper_with_label_text
|
185
|
+
SimpleForm.build label_text: proc { |label, required| "**#{label}**" } do |b|
|
186
|
+
b.use :label_input
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def custom_wrapper_with_custom_label_component
|
191
|
+
SimpleForm.build tag: :span, class: 'custom_wrapper' do |b|
|
192
|
+
b.use :label_text
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
115
196
|
def custom_wrapper_with_html5_components
|
116
197
|
SimpleForm.build tag: :span, class: 'custom_wrapper' do |b|
|
117
198
|
b.use :label_text
|
118
199
|
end
|
119
200
|
end
|
120
201
|
|
202
|
+
def custom_wrapper_with_required_input
|
203
|
+
SimpleForm.build tag: :span, class: 'custom_wrapper' do |b|
|
204
|
+
b.use :html5
|
205
|
+
b.use :input, required: true
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def custom_wrapper_with_input_error_class
|
210
|
+
SimpleForm.build tag: :div, class: "custom_wrapper", error_class: :field_with_errors do |b|
|
211
|
+
b.use :label
|
212
|
+
b.use :input, class: 'inline-class', error_class: 'is-invalid'
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def custom_wrapper_with_input_valid_class(valid_class: :field_without_errors)
|
217
|
+
SimpleForm.build tag: :div, class: "custom_wrapper", valid_class: valid_class do |b|
|
218
|
+
b.use :label
|
219
|
+
b.use :input, class: 'inline-class', valid_class: 'is-valid'
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
121
223
|
def custom_form_for(object, *args, &block)
|
122
224
|
simple_form_for(object, *args, { builder: CustomFormBuilder }, &block)
|
123
225
|
end
|
@@ -148,11 +250,17 @@ module MiscHelpers
|
|
148
250
|
end
|
149
251
|
end
|
150
252
|
|
151
|
-
def with_input_for(object, attribute_name, type, options={})
|
253
|
+
def with_input_for(object, attribute_name, type, options = {})
|
152
254
|
with_concat_form_for(object) do |f|
|
153
255
|
f.input(attribute_name, options.merge(as: type))
|
154
256
|
end
|
155
257
|
end
|
258
|
+
|
259
|
+
def with_input_field_for(object, *args)
|
260
|
+
with_concat_form_for(object) do |f|
|
261
|
+
f.input_field(*args)
|
262
|
+
end
|
263
|
+
end
|
156
264
|
end
|
157
265
|
|
158
266
|
class CustomFormBuilder < SimpleForm::FormBuilder
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
class MockController
|
2
3
|
attr_writer :action_name
|
3
4
|
|
@@ -9,7 +10,7 @@ class MockController
|
|
9
10
|
defined?(@action_name) ? @action_name : "edit"
|
10
11
|
end
|
11
12
|
|
12
|
-
def url_for(*
|
13
|
+
def url_for(*)
|
13
14
|
"http://example.com"
|
14
15
|
end
|
15
16
|
|
@@ -17,8 +18,13 @@ class MockController
|
|
17
18
|
{}
|
18
19
|
end
|
19
20
|
|
21
|
+
def polymorphic_mappings(*); {}; end
|
22
|
+
|
20
23
|
def hash_for_user_path(*); end
|
24
|
+
|
21
25
|
def hash_for_validating_user_path(*); end
|
26
|
+
|
22
27
|
def hash_for_other_validating_user_path(*); end
|
28
|
+
|
23
29
|
def hash_for_users_path(*); end
|
24
30
|
end
|