simple_form 3.0.4 → 3.1.0.rc2
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 +35 -43
- data/MIT-LICENSE +1 -1
- data/README.md +179 -73
- data/lib/generators/simple_form/install_generator.rb +2 -2
- data/lib/generators/simple_form/templates/README +3 -4
- data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +25 -5
- data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +108 -24
- data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +1 -1
- data/lib/generators/simple_form/templates/config/locales/simple_form.en.yml +7 -2
- data/lib/simple_form/action_view_extensions/form_helper.rb +1 -1
- data/lib/simple_form/components/errors.rb +27 -5
- data/lib/simple_form/components/hints.rb +2 -2
- data/lib/simple_form/components/html5.rb +1 -1
- data/lib/simple_form/components/label_input.rb +20 -2
- data/lib/simple_form/components/labels.rb +10 -6
- data/lib/simple_form/components/maxlength.rb +1 -1
- data/lib/simple_form/components/min_max.rb +1 -1
- data/lib/simple_form/components/pattern.rb +1 -1
- data/lib/simple_form/components/placeholders.rb +2 -2
- data/lib/simple_form/components/readonly.rb +1 -1
- data/lib/simple_form/form_builder.rb +121 -74
- data/lib/simple_form/helpers.rb +5 -5
- data/lib/simple_form/inputs/base.rb +34 -12
- data/lib/simple_form/inputs/block_input.rb +1 -1
- data/lib/simple_form/inputs/boolean_input.rb +27 -14
- data/lib/simple_form/inputs/collection_input.rb +32 -9
- data/lib/simple_form/inputs/collection_radio_buttons_input.rb +6 -11
- data/lib/simple_form/inputs/collection_select_input.rb +4 -2
- data/lib/simple_form/inputs/date_time_input.rb +12 -2
- data/lib/simple_form/inputs/file_input.rb +4 -2
- data/lib/simple_form/inputs/grouped_collection_select_input.rb +15 -3
- data/lib/simple_form/inputs/hidden_input.rb +4 -2
- data/lib/simple_form/inputs/numeric_input.rb +5 -4
- data/lib/simple_form/inputs/password_input.rb +4 -2
- data/lib/simple_form/inputs/priority_input.rb +4 -2
- data/lib/simple_form/inputs/range_input.rb +1 -1
- data/lib/simple_form/inputs/string_input.rb +4 -2
- data/lib/simple_form/inputs/text_input.rb +4 -2
- data/lib/simple_form/railtie.rb +7 -0
- data/lib/simple_form/tags.rb +8 -0
- data/lib/simple_form/version.rb +1 -1
- data/lib/simple_form/wrappers/builder.rb +6 -6
- data/lib/simple_form/wrappers/leaf.rb +28 -0
- data/lib/simple_form/wrappers/many.rb +6 -6
- data/lib/simple_form/wrappers/root.rb +1 -1
- data/lib/simple_form/wrappers/single.rb +5 -3
- data/lib/simple_form/wrappers.rb +1 -0
- data/lib/simple_form.rb +46 -6
- data/test/action_view_extensions/builder_test.rb +5 -5
- data/test/action_view_extensions/form_helper_test.rb +13 -13
- data/test/components/label_test.rb +36 -36
- data/test/form_builder/association_test.rb +21 -4
- data/test/form_builder/button_test.rb +5 -5
- data/test/form_builder/error_notification_test.rb +1 -1
- data/test/form_builder/error_test.rb +68 -49
- data/test/form_builder/general_test.rb +67 -62
- data/test/form_builder/hint_test.rb +15 -15
- data/test/form_builder/input_field_test.rb +33 -49
- data/test/form_builder/label_test.rb +44 -12
- data/test/form_builder/wrapper_test.rb +120 -19
- data/test/generators/simple_form_generator_test.rb +2 -2
- data/test/inputs/boolean_input_test.rb +54 -6
- data/test/inputs/collection_check_boxes_input_test.rb +63 -17
- data/test/inputs/collection_radio_buttons_input_test.rb +112 -36
- data/test/inputs/collection_select_input_test.rb +141 -36
- data/test/inputs/datetime_input_test.rb +116 -49
- data/test/inputs/disabled_test.rb +15 -15
- data/test/inputs/discovery_test.rb +56 -6
- data/test/inputs/file_input_test.rb +2 -2
- data/test/inputs/general_test.rb +20 -20
- data/test/inputs/grouped_collection_select_input_test.rb +38 -2
- data/test/inputs/hidden_input_test.rb +4 -4
- data/test/inputs/numeric_input_test.rb +24 -24
- data/test/inputs/priority_input_test.rb +7 -7
- data/test/inputs/readonly_test.rb +19 -19
- data/test/inputs/required_test.rb +13 -13
- data/test/inputs/string_input_test.rb +41 -21
- data/test/inputs/text_input_test.rb +4 -4
- data/test/simple_form_test.rb +8 -0
- data/test/support/discovery_inputs.rb +32 -2
- data/test/support/misc_helpers.rb +66 -6
- data/test/support/models.rb +50 -24
- metadata +7 -7
|
@@ -8,24 +8,24 @@ class HintTest < ActionView::TestCase
|
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
test 'hint
|
|
11
|
+
test 'hint does not be generated by default' do
|
|
12
12
|
with_hint_for @user, :name
|
|
13
13
|
assert_no_select 'span.hint'
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
test 'hint
|
|
16
|
+
test 'hint is generated with optional text' do
|
|
17
17
|
with_hint_for @user, :name, hint: 'Use with care...'
|
|
18
18
|
assert_select 'span.hint', 'Use with care...'
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
test 'hint
|
|
21
|
+
test 'hint does not modify the options hash' do
|
|
22
22
|
options = { hint: 'Use with care...' }
|
|
23
23
|
with_hint_for @user, :name, options
|
|
24
24
|
assert_select 'span.hint', 'Use with care...'
|
|
25
25
|
assert_equal({ hint: 'Use with care...' }, options)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
test 'hint
|
|
28
|
+
test 'hint is generated cleanly with optional text' do
|
|
29
29
|
with_hint_for @user, :name, hint: 'Use with care...', hint_tag: :span
|
|
30
30
|
assert_no_select 'span.hint[hint]'
|
|
31
31
|
assert_no_select 'span.hint[hint_tag]'
|
|
@@ -37,18 +37,18 @@ class HintTest < ActionView::TestCase
|
|
|
37
37
|
assert_select 'p.hint', 'Use with care...'
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
test 'hint
|
|
40
|
+
test 'hint is able to pass html options' do
|
|
41
41
|
with_hint_for @user, :name, hint: 'Yay!', id: 'hint', class: 'yay'
|
|
42
42
|
assert_select 'span#hint.hint.yay'
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
test 'hint
|
|
45
|
+
test 'hint is output as html_safe' do
|
|
46
46
|
with_hint_for @user, :name, hint: '<b>Bold</b> and not...'.html_safe
|
|
47
47
|
assert_select 'span.hint', 'Bold and not...'
|
|
48
48
|
assert_select 'span.hint b', 'Bold'
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
test 'builder
|
|
51
|
+
test 'builder escapes hint text' do
|
|
52
52
|
with_hint_for @user, :name, hint: '<script>alert(1337)</script>'
|
|
53
53
|
assert_select 'span.hint', "<script>alert(1337)</script>"
|
|
54
54
|
end
|
|
@@ -60,7 +60,7 @@ class HintTest < ActionView::TestCase
|
|
|
60
60
|
assert_select 'span.hint', 'Hello World!'
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
test 'hint without attribute name
|
|
63
|
+
test 'hint without attribute name generates component tag with a clean HTML' do
|
|
64
64
|
with_hint_for @validating_user, 'Hello World!'
|
|
65
65
|
assert_no_select 'span.hint[hint]'
|
|
66
66
|
assert_no_select 'span.hint[hint_html]'
|
|
@@ -73,14 +73,14 @@ class HintTest < ActionView::TestCase
|
|
|
73
73
|
assert_no_select 'p.hint[hint_tag]'
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
test 'hint without attribute name
|
|
76
|
+
test 'hint without attribute name is able to pass html options' do
|
|
77
77
|
with_hint_for @user, 'Yay', id: 'hint', class: 'yay'
|
|
78
78
|
assert_select 'span#hint.hint.yay', 'Yay'
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
# I18n
|
|
82
82
|
|
|
83
|
-
test 'hint
|
|
83
|
+
test 'hint uses i18n based on model, action, and attribute to lookup translation' do
|
|
84
84
|
store_translations(:en, simple_form: { hints: { user: {
|
|
85
85
|
edit: { name: 'Content of this input will be truncated...' }
|
|
86
86
|
} } }) do
|
|
@@ -89,7 +89,7 @@ class HintTest < ActionView::TestCase
|
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
-
test 'hint
|
|
92
|
+
test 'hint uses i18n with model and attribute to lookup translation' do
|
|
93
93
|
store_translations(:en, simple_form: { hints: { user: {
|
|
94
94
|
name: 'Content of this input will be capitalized...'
|
|
95
95
|
} } }) do
|
|
@@ -98,7 +98,7 @@ class HintTest < ActionView::TestCase
|
|
|
98
98
|
end
|
|
99
99
|
end
|
|
100
100
|
|
|
101
|
-
test 'hint
|
|
101
|
+
test 'hint uses i18n under defaults namespace to lookup translation' do
|
|
102
102
|
store_translations(:en, simple_form: {
|
|
103
103
|
hints: { defaults: { name: 'Content of this input will be downcased...' } }
|
|
104
104
|
}) do
|
|
@@ -107,7 +107,7 @@ class HintTest < ActionView::TestCase
|
|
|
107
107
|
end
|
|
108
108
|
end
|
|
109
109
|
|
|
110
|
-
test 'hint
|
|
110
|
+
test 'hint uses i18n with lookup for association name' do
|
|
111
111
|
store_translations(:en, simple_form: { hints: {
|
|
112
112
|
user: { company: 'My company!' }
|
|
113
113
|
} } ) do
|
|
@@ -116,7 +116,7 @@ class HintTest < ActionView::TestCase
|
|
|
116
116
|
end
|
|
117
117
|
end
|
|
118
118
|
|
|
119
|
-
test 'hint
|
|
119
|
+
test 'hint outputs translations as html_safe' do
|
|
120
120
|
store_translations(:en, simple_form: { hints: { user: {
|
|
121
121
|
edit: { name: '<b>This is bold</b> and this is not...' }
|
|
122
122
|
} } }) do
|
|
@@ -128,7 +128,7 @@ class HintTest < ActionView::TestCase
|
|
|
128
128
|
|
|
129
129
|
# No object
|
|
130
130
|
|
|
131
|
-
test 'hint
|
|
131
|
+
test 'hint generates properly when object is not present' do
|
|
132
132
|
with_hint_for :project, :name, hint: 'Test without object'
|
|
133
133
|
assert_select 'span.hint', 'Test without object'
|
|
134
134
|
end
|
|
@@ -2,7 +2,7 @@ require 'test_helper'
|
|
|
2
2
|
|
|
3
3
|
# Tests for f.input_field
|
|
4
4
|
class InputFieldTest < ActionView::TestCase
|
|
5
|
-
test "builder input_field
|
|
5
|
+
test "builder input_field only renders the input tag, nothing else" do
|
|
6
6
|
with_concat_form_for(@user) do |f|
|
|
7
7
|
f.input_field :name
|
|
8
8
|
end
|
|
@@ -12,7 +12,7 @@ class InputFieldTest < ActionView::TestCase
|
|
|
12
12
|
assert_no_select '.hint'
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
test 'builder input_field
|
|
15
|
+
test 'builder input_field allows overriding default input type' do
|
|
16
16
|
with_concat_form_for(@user) do |f|
|
|
17
17
|
f.input_field :name, as: :text
|
|
18
18
|
end
|
|
@@ -21,7 +21,7 @@ class InputFieldTest < ActionView::TestCase
|
|
|
21
21
|
assert_select 'textarea#user_name.text'
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
test 'builder input_field
|
|
24
|
+
test 'builder input_field generates input type based on column type' do
|
|
25
25
|
with_concat_form_for(@user) do |f|
|
|
26
26
|
f.input_field :age
|
|
27
27
|
end
|
|
@@ -29,7 +29,7 @@ class InputFieldTest < ActionView::TestCase
|
|
|
29
29
|
assert_select 'input[type=number].integer#user_age'
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
test 'builder input_field
|
|
32
|
+
test 'builder input_field is able to disable any component' do
|
|
33
33
|
with_concat_form_for(@user) do |f|
|
|
34
34
|
f.input_field :age, html5: false
|
|
35
35
|
end
|
|
@@ -38,7 +38,7 @@ class InputFieldTest < ActionView::TestCase
|
|
|
38
38
|
assert_select 'input[type=text].integer#user_age'
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
test 'builder input_field
|
|
41
|
+
test 'builder input_field allows passing options to input tag' do
|
|
42
42
|
with_concat_form_for(@user) do |f|
|
|
43
43
|
f.input_field :name, id: 'name_input', class: 'name'
|
|
44
44
|
end
|
|
@@ -46,7 +46,7 @@ class InputFieldTest < ActionView::TestCase
|
|
|
46
46
|
assert_select 'input.string.name#name_input'
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
test 'builder input_field
|
|
49
|
+
test 'builder input_field does not modify the options hash' do
|
|
50
50
|
options = { id: 'name_input', class: 'name' }
|
|
51
51
|
|
|
52
52
|
with_concat_form_for(@user) do |f|
|
|
@@ -58,7 +58,7 @@ class InputFieldTest < ActionView::TestCase
|
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
test 'builder input_field
|
|
61
|
+
test 'builder input_field generates an input tag with a clean HTML' do
|
|
62
62
|
with_concat_form_for(@user) do |f|
|
|
63
63
|
f.input_field :name, as: :integer, class: 'name'
|
|
64
64
|
end
|
|
@@ -67,7 +67,7 @@ class InputFieldTest < ActionView::TestCase
|
|
|
67
67
|
assert_no_select 'input.integer[as]'
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
-
test 'builder input_field
|
|
70
|
+
test 'builder input_field uses i18n to translate placeholder text' do
|
|
71
71
|
store_translations(:en, simple_form: { placeholders: { user: {
|
|
72
72
|
name: 'Name goes here'
|
|
73
73
|
} } }) do
|
|
@@ -80,7 +80,7 @@ class InputFieldTest < ActionView::TestCase
|
|
|
80
80
|
end
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
test 'builder input_field
|
|
83
|
+
test 'builder input_field uses min_max component' do
|
|
84
84
|
with_concat_form_for(@other_validating_user) do |f|
|
|
85
85
|
f.input_field :age, as: :integer
|
|
86
86
|
end
|
|
@@ -88,15 +88,31 @@ class InputFieldTest < ActionView::TestCase
|
|
|
88
88
|
assert_select 'input[min=18]'
|
|
89
89
|
end
|
|
90
90
|
|
|
91
|
-
test 'builder input_field
|
|
91
|
+
test 'builder input_field does not use pattern component by default' do
|
|
92
92
|
with_concat_form_for(@other_validating_user) do |f|
|
|
93
93
|
f.input_field :country, as: :string
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
+
assert_no_select 'input[pattern="\w+"]'
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
test 'builder input_field infers pattern from attributes' do
|
|
100
|
+
with_concat_form_for(@other_validating_user) do |f|
|
|
101
|
+
f.input_field :country, as: :string, pattern: true
|
|
102
|
+
end
|
|
103
|
+
|
|
96
104
|
assert_select 'input[pattern="\w+"]'
|
|
97
105
|
end
|
|
98
106
|
|
|
99
|
-
test 'builder input_field
|
|
107
|
+
test 'builder input_field accepts custom patter' do
|
|
108
|
+
with_concat_form_for(@other_validating_user) do |f|
|
|
109
|
+
f.input_field :country, as: :string, pattern: '\d+'
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
assert_select 'input[pattern="\d+"]'
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
test 'builder input_field uses readonly component' do
|
|
100
116
|
with_concat_form_for(@other_validating_user) do |f|
|
|
101
117
|
f.input_field :age, as: :integer, readonly: true
|
|
102
118
|
end
|
|
@@ -104,7 +120,7 @@ class InputFieldTest < ActionView::TestCase
|
|
|
104
120
|
assert_select 'input.integer.readonly[readonly]'
|
|
105
121
|
end
|
|
106
122
|
|
|
107
|
-
test 'builder input_field
|
|
123
|
+
test 'builder input_field uses maxlength component' do
|
|
108
124
|
with_concat_form_for(@validating_user) do |f|
|
|
109
125
|
f.input_field :name, as: :string
|
|
110
126
|
end
|
|
@@ -112,7 +128,7 @@ class InputFieldTest < ActionView::TestCase
|
|
|
112
128
|
assert_select 'input.string[maxlength=25]'
|
|
113
129
|
end
|
|
114
130
|
|
|
115
|
-
test 'builder collection input_field
|
|
131
|
+
test 'builder collection input_field generates input tag with a clean HTML' do
|
|
116
132
|
with_concat_form_for(@user) do |f|
|
|
117
133
|
f.input_field :status, collection: ['Open', 'Closed'], class: 'status', label_method: :to_s, value_method: :to_s
|
|
118
134
|
end
|
|
@@ -123,43 +139,11 @@ class InputFieldTest < ActionView::TestCase
|
|
|
123
139
|
assert_no_select 'select.status[value_method]'
|
|
124
140
|
end
|
|
125
141
|
|
|
126
|
-
test 'build input_field
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
f.input_field :name, pattern: '\w+'
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
assert_select 'input[pattern="\w+"]'
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
test 'build input_field without placeholder component use the placeholder string' do
|
|
137
|
-
swap_wrapper :default, self.custom_wrapper_with_html5_components do
|
|
138
|
-
with_concat_form_for(@user) do |f|
|
|
139
|
-
f.input_field :name, placeholder: 'Placeholder'
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
assert_select 'input[placeholder="Placeholder"]'
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
test 'build input_field without maxlength component use the maxlength string' do
|
|
147
|
-
swap_wrapper :default, self.custom_wrapper_with_html5_components do
|
|
148
|
-
with_concat_form_for(@user) do |f|
|
|
149
|
-
f.input_field :name, maxlength: 5
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
assert_select 'input[maxlength="5"]'
|
|
142
|
+
test 'build input_field does not treat "boolean_style" as a HTML attribute' do
|
|
143
|
+
with_concat_form_for(@user) do |f|
|
|
144
|
+
f.input_field :active, boolean_style: :nested
|
|
153
145
|
end
|
|
154
|
-
end
|
|
155
146
|
|
|
156
|
-
|
|
157
|
-
swap_wrapper :default, self.custom_wrapper_with_html5_components do
|
|
158
|
-
with_concat_form_for(@user) do |f|
|
|
159
|
-
f.input_field :name, readonly: true
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
assert_select 'input[readonly="readonly"]'
|
|
163
|
-
end
|
|
147
|
+
assert_no_select 'input.boolean[boolean_style]'
|
|
164
148
|
end
|
|
165
149
|
end
|
|
@@ -8,63 +8,63 @@ class LabelTest < ActionView::TestCase
|
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
test 'builder
|
|
11
|
+
test 'builder generates a label for the attribute' do
|
|
12
12
|
with_label_for @user, :name
|
|
13
13
|
assert_select 'label.string[for=user_name]', /Name/
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
test 'builder
|
|
16
|
+
test 'builder generates a label for the boolean attrbiute' do
|
|
17
17
|
with_label_for @user, :name, as: :boolean
|
|
18
18
|
assert_select 'label.boolean[for=user_name]', /Name/
|
|
19
19
|
assert_no_select 'label[as=boolean]'
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
test 'builder
|
|
22
|
+
test 'builder generates a label component tag with a clean HTML' do
|
|
23
23
|
with_label_for @user, :name
|
|
24
24
|
assert_no_select 'label.string[label_html]'
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
test 'builder
|
|
27
|
+
test 'builder adds a required class to label if the attribute is required' do
|
|
28
28
|
with_label_for @validating_user, :name
|
|
29
29
|
assert_select 'label.string.required[for=validating_user_name]', /Name/
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
test 'builder
|
|
32
|
+
test 'builder escapes label text' do
|
|
33
33
|
with_label_for @user, :name, label: '<script>alert(1337)</script>', required: false
|
|
34
34
|
assert_select 'label.string', "<script>alert(1337)</script>"
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
test 'builder
|
|
37
|
+
test 'builder does not escape label text if it is safe' do
|
|
38
38
|
with_label_for @user, :name, label: '<script>alert(1337)</script>'.html_safe, required: false
|
|
39
39
|
assert_select 'label.string script', "alert(1337)"
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
test 'builder
|
|
42
|
+
test 'builder allows passing options to label tag' do
|
|
43
43
|
with_label_for @user, :name, label: 'My label', id: 'name_label'
|
|
44
44
|
assert_select 'label.string#name_label', /My label/
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
test 'builder label
|
|
47
|
+
test 'builder label generates label tag with clean HTML' do
|
|
48
48
|
with_label_for @user, :name, label: 'My label', required: true, id: 'name_label'
|
|
49
49
|
assert_select 'label.string#name_label', /My label/
|
|
50
50
|
assert_no_select 'label[label]'
|
|
51
51
|
assert_no_select 'label[required]'
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
test 'builder
|
|
54
|
+
test 'builder does not modify the options hash' do
|
|
55
55
|
options = { label: 'My label', id: 'name_label' }
|
|
56
56
|
with_label_for @user, :name, options
|
|
57
57
|
assert_select 'label.string#name_label', /My label/
|
|
58
58
|
assert_equal({ label: 'My label', id: 'name_label' }, options)
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
test 'builder
|
|
61
|
+
test 'builder fallbacks to default label when string is given' do
|
|
62
62
|
with_label_for @user, :name, 'Nome do usuário'
|
|
63
63
|
assert_select 'label', 'Nome do usuário'
|
|
64
64
|
assert_no_select 'label.string'
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
test 'builder
|
|
67
|
+
test 'builder fallbacks to default label when block is given' do
|
|
68
68
|
with_label_for @user, :name do
|
|
69
69
|
'Nome do usuário'
|
|
70
70
|
end
|
|
@@ -73,9 +73,41 @@ class LabelTest < ActionView::TestCase
|
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
test 'builder allows label order to be changed' do
|
|
76
|
-
swap SimpleForm, label_text:
|
|
76
|
+
swap SimpleForm, label_text: proc { |l, r| "#{l}:" } do
|
|
77
77
|
with_label_for @user, :age
|
|
78
78
|
assert_select 'label.integer[for=user_age]', "Age:"
|
|
79
79
|
end
|
|
80
80
|
end
|
|
81
|
+
|
|
82
|
+
test 'configuration allow set label text for wrappers' do
|
|
83
|
+
swap_wrapper :default, self.custom_wrapper_with_label_text do
|
|
84
|
+
with_concat_form_for(@user) do |f|
|
|
85
|
+
concat f.input :age
|
|
86
|
+
end
|
|
87
|
+
assert_select "label.integer[for=user_age]", "**Age**"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
test 'configuration allow set rewrited label tag for wrappers' do
|
|
92
|
+
swap_wrapper :default, self.custom_wrapper_with_custom_label_component do
|
|
93
|
+
with_concat_form_for(@user) do |f|
|
|
94
|
+
concat f.input :age
|
|
95
|
+
end
|
|
96
|
+
assert_select "span.integer.user_age", /Age/
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
test 'builder allows custom formatting when label is explicitly specified' do
|
|
101
|
+
swap SimpleForm, label_text: lambda { |l, r, explicit_label| explicit_label ? l : "#{l.titleize}:" } do
|
|
102
|
+
with_label_for @user, :time_zone, 'What is your home time zone?'
|
|
103
|
+
assert_select 'label[for=user_time_zone]', 'What is your home time zone?'
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
test 'builder allows custom formatting when label is generated' do
|
|
108
|
+
swap SimpleForm, label_text: lambda { |l, r, explicit_label| explicit_label ? l : "#{l.titleize}:" } do
|
|
109
|
+
with_label_for @user, :time_zone
|
|
110
|
+
assert_select 'label[for=user_time_zone]', 'Time Zone:'
|
|
111
|
+
end
|
|
112
|
+
end
|
|
81
113
|
end
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
require 'test_helper'
|
|
2
2
|
|
|
3
3
|
class WrapperTest < ActionView::TestCase
|
|
4
|
-
test 'wrapper
|
|
4
|
+
test 'wrapper does not have error class for attribute without errors' do
|
|
5
5
|
with_form_for @user, :active
|
|
6
6
|
assert_no_select 'div.field_with_errors'
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
test 'wrapper
|
|
9
|
+
test 'wrapper does not have error class when object is not present' do
|
|
10
10
|
with_form_for :project, :name
|
|
11
11
|
assert_no_select 'div.field_with_errors'
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
test 'wrapper
|
|
14
|
+
test 'wrapper adds the attribute name class' do
|
|
15
15
|
with_form_for @user, :name
|
|
16
16
|
assert_select 'div.user_name'
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
test 'wrapper
|
|
19
|
+
test 'wrapper adds the attribute name class for nested forms' do
|
|
20
20
|
@user.company = Company.new(1, 'Empresa')
|
|
21
21
|
with_concat_form_for @user do |f|
|
|
22
22
|
concat(f.simple_fields_for(:company) do |company_form|
|
|
@@ -27,44 +27,44 @@ class WrapperTest < ActionView::TestCase
|
|
|
27
27
|
assert_select 'div.user_company_name'
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
test 'wrapper
|
|
30
|
+
test 'wrapper adds the association name class' do
|
|
31
31
|
with_form_for @user, :company
|
|
32
32
|
assert_select 'div.user_company'
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
test 'wrapper
|
|
35
|
+
test 'wrapper adds error class for attribute with errors' do
|
|
36
36
|
with_form_for @user, :name
|
|
37
37
|
assert_select 'div.field_with_errors'
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
test 'wrapper
|
|
40
|
+
test 'wrapper adds hint class for attribute with a hint' do
|
|
41
41
|
with_form_for @user, :name, hint: 'hint'
|
|
42
42
|
assert_select 'div.field_with_hint'
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
test 'wrapper
|
|
45
|
+
test 'wrapper does not have disabled class by default' do
|
|
46
46
|
with_form_for @user, :active
|
|
47
47
|
assert_no_select 'div.disabled'
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
test 'wrapper
|
|
50
|
+
test 'wrapper has disabled class when input is disabled' do
|
|
51
51
|
with_form_for @user, :active, disabled: true
|
|
52
52
|
assert_select 'div.disabled'
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
test 'wrapper
|
|
55
|
+
test 'wrapper supports no wrapping when wrapper is false' do
|
|
56
56
|
with_form_for @user, :name, wrapper: false
|
|
57
57
|
assert_select 'form > label[for=user_name]'
|
|
58
58
|
assert_select 'form > input#user_name.string'
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
test 'wrapper
|
|
61
|
+
test 'wrapper supports no wrapping when wrapper tag is false' do
|
|
62
62
|
with_form_for @user, :name, wrapper: custom_wrapper_without_top_level
|
|
63
63
|
assert_select 'form > label[for=user_name]'
|
|
64
64
|
assert_select 'form > input#user_name.string'
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
test 'wrapper
|
|
67
|
+
test 'wrapper wraps tag adds required/optional css classes' do
|
|
68
68
|
with_form_for @user, :name
|
|
69
69
|
assert_select 'form div.input.required.string'
|
|
70
70
|
|
|
@@ -72,22 +72,22 @@ class WrapperTest < ActionView::TestCase
|
|
|
72
72
|
assert_select 'form div.input.optional.integer'
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
-
test 'wrapper
|
|
75
|
+
test 'wrapper allows custom options to be given' do
|
|
76
76
|
with_form_for @user, :name, wrapper_html: { id: "super_cool", class: 'yay' }
|
|
77
77
|
assert_select 'form #super_cool.required.string.yay'
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
test 'wrapper
|
|
80
|
+
test 'wrapper allows tag to be given on demand' do
|
|
81
81
|
with_form_for @user, :name, wrapper_tag: :b
|
|
82
82
|
assert_select 'form b.required.string'
|
|
83
83
|
end
|
|
84
84
|
|
|
85
|
-
test 'wrapper
|
|
85
|
+
test 'wrapper allows wrapper class to be given on demand' do
|
|
86
86
|
with_form_for @user, :name, wrapper_class: :wrapper
|
|
87
87
|
assert_select 'form div.wrapper.required.string'
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
-
test 'wrapper
|
|
90
|
+
test 'wrapper skips additional classes when configured' do
|
|
91
91
|
swap SimpleForm, generate_additional_classes_for: [:input, :label] do
|
|
92
92
|
with_form_for @user, :name, wrapper_class: :wrapper
|
|
93
93
|
assert_select 'form div.wrapper'
|
|
@@ -97,7 +97,7 @@ class WrapperTest < ActionView::TestCase
|
|
|
97
97
|
end
|
|
98
98
|
end
|
|
99
99
|
|
|
100
|
-
test 'wrapper
|
|
100
|
+
test 'wrapper does not generate empty css class' do
|
|
101
101
|
swap SimpleForm, generate_additional_classes_for: [:input, :label] do
|
|
102
102
|
swap_wrapper :default, custom_wrapper_without_class do
|
|
103
103
|
with_form_for @user, :name
|
|
@@ -128,6 +128,21 @@ class WrapperTest < ActionView::TestCase
|
|
|
128
128
|
end
|
|
129
129
|
end
|
|
130
130
|
|
|
131
|
+
test 'custom wrappers can have additional attributes' do
|
|
132
|
+
swap_wrapper :default, self.custom_wrapper_with_additional_attributes do
|
|
133
|
+
with_form_for @user, :name
|
|
134
|
+
|
|
135
|
+
assert_select "div.custom_wrapper[title='some title'][data-wrapper='test']"
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
test 'custom wrappers can have full error message on attributes' do
|
|
140
|
+
swap_wrapper :default, self.custom_wrapper_with_full_error do
|
|
141
|
+
with_form_for @user, :name
|
|
142
|
+
assert_select 'span.error', "Name can't be blank"
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
131
146
|
test 'custom wrappers on a form basis' do
|
|
132
147
|
swap_wrapper :another do
|
|
133
148
|
with_concat_form_for(@user) do |f|
|
|
@@ -172,7 +187,7 @@ class WrapperTest < ActionView::TestCase
|
|
|
172
187
|
end
|
|
173
188
|
end
|
|
174
189
|
|
|
175
|
-
test '
|
|
190
|
+
test 'does not duplicate label classes for different inputs' do
|
|
176
191
|
swap_wrapper :default, self.custom_wrapper_with_label_html_option do
|
|
177
192
|
with_concat_form_for(@user) do |f|
|
|
178
193
|
concat f.input :name, required: false
|
|
@@ -191,7 +206,7 @@ class WrapperTest < ActionView::TestCase
|
|
|
191
206
|
end
|
|
192
207
|
end
|
|
193
208
|
|
|
194
|
-
test '
|
|
209
|
+
test 'uses wrapper for specified in config mapping' do
|
|
195
210
|
swap_wrapper :another do
|
|
196
211
|
swap SimpleForm, wrapper_mappings: { string: :another } do
|
|
197
212
|
with_form_for @user, :name
|
|
@@ -200,4 +215,90 @@ class WrapperTest < ActionView::TestCase
|
|
|
200
215
|
end
|
|
201
216
|
end
|
|
202
217
|
end
|
|
218
|
+
|
|
219
|
+
test 'uses custom wrapper mapping per form basis' do
|
|
220
|
+
swap_wrapper :another do
|
|
221
|
+
with_concat_form_for @user, wrapper_mappings: { string: :another } do |f|
|
|
222
|
+
concat f.input :name
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
assert_select "section.custom_wrapper div.another_wrapper label"
|
|
227
|
+
assert_select "section.custom_wrapper div.another_wrapper input.string"
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
test 'input accepts attributes in the DSL' do
|
|
231
|
+
swap_wrapper :default, self.custom_wrapper_with_input_class do
|
|
232
|
+
with_concat_form_for @user do |f|
|
|
233
|
+
concat f.input :name
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
assert_select "div.custom_wrapper input.string.inline-class"
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
test 'label accepts attributes in the DSL' do
|
|
241
|
+
swap_wrapper :default, self.custom_wrapper_with_label_class do
|
|
242
|
+
with_concat_form_for @user do |f|
|
|
243
|
+
concat f.input :name
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
assert_select "div.custom_wrapper label.string.inline-class"
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
test 'label_input accepts attributes in the DSL' do
|
|
251
|
+
swap_wrapper :default, self.custom_wrapper_with_label_input_class do
|
|
252
|
+
with_concat_form_for @user do |f|
|
|
253
|
+
concat f.input :name
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
assert_select "div.custom_wrapper label.string.inline-class"
|
|
258
|
+
assert_select "div.custom_wrapper input.string.inline-class"
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
test 'input accepts data attributes in the DSL' do
|
|
262
|
+
swap_wrapper :default, self.custom_wrapper_with_input_attributes do
|
|
263
|
+
with_concat_form_for @user do |f|
|
|
264
|
+
concat f.input :name
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
assert_select "div.custom_wrapper input.string[data-modal=true]"
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
test 'inline wrapper displays when there is content' do
|
|
272
|
+
swap_wrapper :default, self.custom_wrapper_with_wrapped_optional_component do
|
|
273
|
+
with_form_for @user, :name, hint: "can't be blank"
|
|
274
|
+
assert_select 'section.custom_wrapper div.no_output_wrapper p.omg_hint', "can't be blank"
|
|
275
|
+
assert_select 'p.omg_hint'
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
test 'inline wrapper does not display when there is no content' do
|
|
280
|
+
swap_wrapper :default, self.custom_wrapper_with_wrapped_optional_component do
|
|
281
|
+
with_form_for @user, :name
|
|
282
|
+
assert_select 'section.custom_wrapper div.no_output_wrapper'
|
|
283
|
+
assert_no_select 'p.omg_hint'
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
test 'optional wrapper does not display when there is content' do
|
|
288
|
+
swap_wrapper :default, self.custom_wrapper_with_unless_blank do
|
|
289
|
+
with_form_for @user, :name, hint: "can't be blank"
|
|
290
|
+
assert_select 'section.custom_wrapper div.no_output_wrapper'
|
|
291
|
+
assert_select 'div.no_output_wrapper'
|
|
292
|
+
assert_select 'p.omg_hint'
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
test 'optional wrapper does not display when there is no content' do
|
|
297
|
+
swap_wrapper :default, self.custom_wrapper_with_unless_blank do
|
|
298
|
+
with_form_for @user, :name
|
|
299
|
+
assert_no_select 'section.custom_wrapper div.no_output_wrapper'
|
|
300
|
+
assert_no_select 'div.no_output_wrapper'
|
|
301
|
+
assert_no_select 'p.omg_hint'
|
|
302
|
+
end
|
|
303
|
+
end
|
|
203
304
|
end
|
|
@@ -21,8 +21,8 @@ class SimpleFormGeneratorTest < Rails::Generators::TestCase
|
|
|
21
21
|
run_generator %w(--bootstrap)
|
|
22
22
|
assert_file 'config/initializers/simple_form.rb',
|
|
23
23
|
/config\.default_wrapper = :default/, /config\.boolean_style = :nested/
|
|
24
|
-
assert_file 'config/initializers/simple_form_bootstrap.rb', /config\.wrappers :
|
|
25
|
-
/config\.default_wrapper = :
|
|
24
|
+
assert_file 'config/initializers/simple_form_bootstrap.rb', /config\.wrappers :vertical_form/,
|
|
25
|
+
/config\.wrappers :horizontal_form/, /config\.default_wrapper = :vertical_form/
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
test 'generates the simple_form initializer with the foundation wrappers' do
|