simple_form 3.0.1 → 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.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +149 -25
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +441 -107
  5. data/lib/generators/simple_form/install_generator.rb +4 -3
  6. data/lib/generators/simple_form/templates/README +4 -5
  7. data/lib/generators/simple_form/templates/_form.html.erb +2 -0
  8. data/lib/generators/simple_form/templates/_form.html.haml +2 -0
  9. data/lib/generators/simple_form/templates/_form.html.slim +1 -0
  10. data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +48 -11
  11. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +417 -23
  12. data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +101 -5
  13. data/lib/generators/simple_form/templates/config/locales/simple_form.en.yml +7 -2
  14. data/lib/simple_form/action_view_extensions/builder.rb +2 -0
  15. data/lib/simple_form/action_view_extensions/form_helper.rb +10 -3
  16. data/lib/simple_form/components/errors.rb +38 -3
  17. data/lib/simple_form/components/hints.rb +3 -2
  18. data/lib/simple_form/components/html5.rb +16 -5
  19. data/lib/simple_form/components/label_input.rb +21 -2
  20. data/lib/simple_form/components/labels.rb +22 -11
  21. data/lib/simple_form/components/maxlength.rb +9 -5
  22. data/lib/simple_form/components/min_max.rb +2 -1
  23. data/lib/simple_form/components/minlength.rb +38 -0
  24. data/lib/simple_form/components/pattern.rb +2 -1
  25. data/lib/simple_form/components/placeholders.rb +4 -3
  26. data/lib/simple_form/components/readonly.rb +2 -1
  27. data/lib/simple_form/components.rb +2 -0
  28. data/lib/simple_form/error_notification.rb +1 -0
  29. data/lib/simple_form/form_builder.rb +193 -80
  30. data/lib/simple_form/helpers/autofocus.rb +1 -0
  31. data/lib/simple_form/helpers/disabled.rb +1 -0
  32. data/lib/simple_form/helpers/readonly.rb +1 -0
  33. data/lib/simple_form/helpers/required.rb +1 -0
  34. data/lib/simple_form/helpers/validators.rb +2 -1
  35. data/lib/simple_form/helpers.rb +6 -5
  36. data/lib/simple_form/i18n_cache.rb +1 -0
  37. data/lib/simple_form/inputs/base.rb +57 -14
  38. data/lib/simple_form/inputs/block_input.rb +2 -1
  39. data/lib/simple_form/inputs/boolean_input.rb +39 -16
  40. data/lib/simple_form/inputs/collection_check_boxes_input.rb +2 -1
  41. data/lib/simple_form/inputs/collection_input.rb +37 -14
  42. data/lib/simple_form/inputs/collection_radio_buttons_input.rb +9 -13
  43. data/lib/simple_form/inputs/collection_select_input.rb +5 -2
  44. data/lib/simple_form/inputs/date_time_input.rb +24 -9
  45. data/lib/simple_form/inputs/file_input.rb +5 -2
  46. data/lib/simple_form/inputs/grouped_collection_select_input.rb +16 -3
  47. data/lib/simple_form/inputs/hidden_input.rb +5 -2
  48. data/lib/simple_form/inputs/numeric_input.rb +6 -4
  49. data/lib/simple_form/inputs/password_input.rb +6 -3
  50. data/lib/simple_form/inputs/priority_input.rb +5 -2
  51. data/lib/simple_form/inputs/range_input.rb +2 -1
  52. data/lib/simple_form/inputs/string_input.rb +6 -3
  53. data/lib/simple_form/inputs/text_input.rb +6 -3
  54. data/lib/simple_form/inputs.rb +1 -0
  55. data/lib/simple_form/map_type.rb +1 -0
  56. data/lib/simple_form/railtie.rb +8 -0
  57. data/lib/simple_form/tags.rb +7 -0
  58. data/lib/simple_form/version.rb +2 -1
  59. data/lib/simple_form/wrappers/builder.rb +7 -6
  60. data/lib/simple_form/wrappers/leaf.rb +29 -0
  61. data/lib/simple_form/wrappers/many.rb +7 -6
  62. data/lib/simple_form/wrappers/root.rb +3 -1
  63. data/lib/simple_form/wrappers/single.rb +7 -4
  64. data/lib/simple_form/wrappers.rb +2 -0
  65. data/lib/simple_form.rb +117 -18
  66. data/test/action_view_extensions/builder_test.rb +42 -41
  67. data/test/action_view_extensions/form_helper_test.rb +36 -16
  68. data/test/components/custom_components_test.rb +62 -0
  69. data/test/components/label_test.rb +70 -41
  70. data/test/form_builder/association_test.rb +79 -37
  71. data/test/form_builder/button_test.rb +11 -10
  72. data/test/form_builder/error_notification_test.rb +2 -1
  73. data/test/form_builder/error_test.rb +173 -24
  74. data/test/form_builder/general_test.rb +171 -73
  75. data/test/form_builder/hint_test.rb +24 -18
  76. data/test/form_builder/input_field_test.rb +132 -56
  77. data/test/form_builder/label_test.rb +68 -13
  78. data/test/form_builder/wrapper_test.rb +190 -22
  79. data/test/generators/simple_form_generator_test.rb +8 -7
  80. data/test/inputs/boolean_input_test.rb +89 -6
  81. data/test/inputs/collection_check_boxes_input_test.rb +109 -25
  82. data/test/inputs/collection_radio_buttons_input_test.rb +168 -54
  83. data/test/inputs/collection_select_input_test.rb +183 -77
  84. data/test/inputs/datetime_input_test.rb +131 -50
  85. data/test/inputs/disabled_test.rb +16 -15
  86. data/test/inputs/discovery_test.rb +58 -6
  87. data/test/inputs/file_input_test.rb +3 -2
  88. data/test/inputs/general_test.rb +23 -22
  89. data/test/inputs/grouped_collection_select_input_test.rb +54 -17
  90. data/test/inputs/hidden_input_test.rb +5 -4
  91. data/test/inputs/numeric_input_test.rb +48 -44
  92. data/test/inputs/priority_input_test.rb +23 -14
  93. data/test/inputs/readonly_test.rb +20 -19
  94. data/test/inputs/required_test.rb +58 -13
  95. data/test/inputs/string_input_test.rb +62 -33
  96. data/test/inputs/text_input_test.rb +20 -7
  97. data/test/simple_form_test.rb +9 -0
  98. data/test/support/discovery_inputs.rb +33 -2
  99. data/test/support/misc_helpers.rb +113 -5
  100. data/test/support/mock_controller.rb +7 -1
  101. data/test/support/models.rb +137 -37
  102. data/test/test_helper.rb +15 -1
  103. metadata +25 -33
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  # Tests for f.hint
@@ -8,24 +9,29 @@ class HintTest < ActionView::TestCase
8
9
  end
9
10
  end
10
11
 
11
- test 'hint should not be generated by default' do
12
+ test 'hint does not be generated by default' do
12
13
  with_hint_for @user, :name
13
14
  assert_no_select 'span.hint'
14
15
  end
15
16
 
16
- test 'hint should be generated with optional text' do
17
+ test 'hint is generated with optional text' do
17
18
  with_hint_for @user, :name, hint: 'Use with care...'
18
19
  assert_select 'span.hint', 'Use with care...'
19
20
  end
20
21
 
21
- test 'hint should not modify the options hash' do
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
+
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
24
30
  assert_select 'span.hint', 'Use with care...'
25
31
  assert_equal({ hint: 'Use with care...' }, options)
26
32
  end
27
33
 
28
- test 'hint should be generated cleanly with optional text' do
34
+ test 'hint is generated cleanly with optional text' do
29
35
  with_hint_for @user, :name, hint: 'Use with care...', hint_tag: :span
30
36
  assert_no_select 'span.hint[hint]'
31
37
  assert_no_select 'span.hint[hint_tag]'
@@ -37,20 +43,20 @@ class HintTest < ActionView::TestCase
37
43
  assert_select 'p.hint', 'Use with care...'
38
44
  end
39
45
 
40
- test 'hint should be able to pass html options' do
46
+ test 'hint is able to pass html options' do
41
47
  with_hint_for @user, :name, hint: 'Yay!', id: 'hint', class: 'yay'
42
48
  assert_select 'span#hint.hint.yay'
43
49
  end
44
50
 
45
- test 'hint should be output as html_safe' do
51
+ test 'hint is output as html_safe' do
46
52
  with_hint_for @user, :name, hint: '<b>Bold</b> and not...'.html_safe
47
53
  assert_select 'span.hint', 'Bold and not...'
48
54
  assert_select 'span.hint b', 'Bold'
49
55
  end
50
56
 
51
- test 'builder should escape hint text' do
57
+ test 'builder escapes hint text' do
52
58
  with_hint_for @user, :name, hint: '<script>alert(1337)</script>'
53
- assert_select 'span.hint', "&lt;script&gt;alert(1337)&lt;/script&gt;"
59
+ assert_no_select 'span.hint script'
54
60
  end
55
61
 
56
62
  # Without attribute name
@@ -60,7 +66,7 @@ class HintTest < ActionView::TestCase
60
66
  assert_select 'span.hint', 'Hello World!'
61
67
  end
62
68
 
63
- test 'hint without attribute name should generate component tag with a clean HTML' do
69
+ test 'hint without attribute name generates component tag with a clean HTML' do
64
70
  with_hint_for @validating_user, 'Hello World!'
65
71
  assert_no_select 'span.hint[hint]'
66
72
  assert_no_select 'span.hint[hint_html]'
@@ -73,14 +79,14 @@ class HintTest < ActionView::TestCase
73
79
  assert_no_select 'p.hint[hint_tag]'
74
80
  end
75
81
 
76
- test 'hint without attribute name should be able to pass html options' do
82
+ test 'hint without attribute name is able to pass html options' do
77
83
  with_hint_for @user, 'Yay', id: 'hint', class: 'yay'
78
84
  assert_select 'span#hint.hint.yay', 'Yay'
79
85
  end
80
86
 
81
87
  # I18n
82
88
 
83
- test 'hint should use i18n based on model, action, and attribute to lookup translation' do
89
+ test 'hint uses i18n based on model, action, and attribute to lookup translation' do
84
90
  store_translations(:en, simple_form: { hints: { user: {
85
91
  edit: { name: 'Content of this input will be truncated...' }
86
92
  } } }) do
@@ -89,7 +95,7 @@ class HintTest < ActionView::TestCase
89
95
  end
90
96
  end
91
97
 
92
- test 'hint should use i18n with model and attribute to lookup translation' do
98
+ test 'hint uses i18n with model and attribute to lookup translation' do
93
99
  store_translations(:en, simple_form: { hints: { user: {
94
100
  name: 'Content of this input will be capitalized...'
95
101
  } } }) do
@@ -98,7 +104,7 @@ class HintTest < ActionView::TestCase
98
104
  end
99
105
  end
100
106
 
101
- test 'hint should use i18n under defaults namespace to lookup translation' do
107
+ test 'hint uses i18n under defaults namespace to lookup translation' do
102
108
  store_translations(:en, simple_form: {
103
109
  hints: { defaults: { name: 'Content of this input will be downcased...' } }
104
110
  }) do
@@ -107,7 +113,7 @@ class HintTest < ActionView::TestCase
107
113
  end
108
114
  end
109
115
 
110
- test 'hint should use i18n with lookup for association name' do
116
+ test 'hint uses i18n with lookup for association name' do
111
117
  store_translations(:en, simple_form: { hints: {
112
118
  user: { company: 'My company!' }
113
119
  } } ) do
@@ -116,7 +122,7 @@ class HintTest < ActionView::TestCase
116
122
  end
117
123
  end
118
124
 
119
- test 'hint should output translations as html_safe' do
125
+ test 'hint outputs translations as html_safe' do
120
126
  store_translations(:en, simple_form: { hints: { user: {
121
127
  edit: { name: '<b>This is bold</b> and this is not...' }
122
128
  } } }) do
@@ -128,7 +134,7 @@ class HintTest < ActionView::TestCase
128
134
 
129
135
  # No object
130
136
 
131
- test 'hint should generate properly when object is not present' do
137
+ test 'hint generates properly when object is not present' do
132
138
  with_hint_for :project, :name, hint: 'Test without object'
133
139
  assert_select 'span.hint', 'Test without object'
134
140
  end
@@ -137,8 +143,8 @@ class HintTest < ActionView::TestCase
137
143
 
138
144
  test 'hint with custom wrappers works' do
139
145
  swap_wrapper do
140
- with_hint_for @user, :name, hint: "can't be blank"
141
- assert_select 'div.omg_hint', "can&#39;t be blank"
146
+ with_hint_for @user, :name, hint: "cannot be blank"
147
+ assert_select 'div.omg_hint', "cannot be blank"
142
148
  end
143
149
  end
144
150
  end
@@ -1,125 +1,201 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  # Tests for f.input_field
4
5
  class InputFieldTest < ActionView::TestCase
5
- test "builder input_field should only render the input tag, nothing else" do
6
- with_concat_form_for(@user) do |f|
7
- f.input_field :name
6
+ def with_input_field_for(object, *args)
7
+ with_concat_form_for(object) do |f|
8
+ f.input_field(*args)
8
9
  end
10
+ end
11
+
12
+ test "builder input_field only renders the input tag, nothing else" do
13
+ with_input_field_for @user, :name
14
+
9
15
  assert_select 'form > input.required.string'
10
16
  assert_no_select 'div.string'
11
17
  assert_no_select 'label'
12
18
  assert_no_select '.hint'
13
19
  end
14
20
 
15
- test 'builder input_field should allow overriding default input type' do
16
- with_concat_form_for(@user) do |f|
17
- f.input_field :name, as: :text
18
- end
21
+ test 'builder input_field allows overriding default input type' do
22
+ with_input_field_for @user, :name, as: :text
19
23
 
20
24
  assert_no_select 'input#user_name'
21
25
  assert_select 'textarea#user_name.text'
22
26
  end
23
27
 
24
- test 'builder input_field should generate input type based on column type' do
25
- with_concat_form_for(@user) do |f|
26
- f.input_field :age
27
- end
28
+ test 'builder input_field generates input type based on column type' do
29
+ with_input_field_for @user, :age
28
30
 
29
31
  assert_select 'input[type=number].integer#user_age'
30
32
  end
31
33
 
32
- test 'builder input_field should be able to disable any component' do
33
- with_concat_form_for(@user) do |f|
34
- f.input_field :age, html5: false
35
- end
34
+ test 'builder input_field is able to disable any component' do
35
+ with_input_field_for @user, :age, html5: false
36
36
 
37
37
  assert_no_select 'input[html5=false]#user_age'
38
38
  assert_select 'input[type=text].integer#user_age'
39
39
  end
40
40
 
41
- test 'builder input_field should allow passing options to input tag' do
42
- with_concat_form_for(@user) do |f|
43
- f.input_field :name, id: 'name_input', class: 'name'
44
- end
41
+ test 'builder input_field allows passing options to input tag' do
42
+ with_input_field_for @user, :name, id: 'name_input', class: 'name'
45
43
 
46
44
  assert_select 'input.string.name#name_input'
47
45
  end
48
46
 
49
- test 'builder input_field should not modify the options hash' do
47
+ test 'builder input_field does not modify the options hash' do
50
48
  options = { id: 'name_input', class: 'name' }
51
-
52
- with_concat_form_for(@user) do |f|
53
- f.input_field :name, options
54
- end
49
+ with_input_field_for @user, :name, options
55
50
 
56
51
  assert_select 'input.string.name#name_input'
57
52
  assert_equal({ id: 'name_input', class: 'name' }, options)
58
53
  end
59
54
 
60
55
 
61
- test 'builder input_field should generate an input tag with a clean HTML' do
62
- with_concat_form_for(@user) do |f|
63
- f.input_field :name, as: :integer, class: 'name'
64
- end
56
+ test 'builder input_field generates an input tag with a clean HTML' do
57
+ with_input_field_for @user, :name, as: :integer, class: 'name'
65
58
 
66
59
  assert_no_select 'input.integer[input_html]'
67
60
  assert_no_select 'input.integer[as]'
68
61
  end
69
62
 
70
- test 'builder input_field should use i18n to translate placeholder text' do
63
+ test 'builder input_field uses i18n to translate placeholder text' do
71
64
  store_translations(:en, simple_form: { placeholders: { user: {
72
65
  name: 'Name goes here'
73
66
  } } }) do
67
+ with_input_field_for @user, :name
74
68
 
75
- with_concat_form_for(@user) do |f|
76
- f.input_field :name
77
- end
78
-
79
- assert_select 'input.string[placeholder=Name goes here]'
69
+ assert_select 'input.string[placeholder="Name goes here"]'
80
70
  end
81
71
  end
82
72
 
83
- test 'builder input_field should use min_max component' do
84
- with_concat_form_for(@other_validating_user) do |f|
85
- f.input_field :age, as: :integer
86
- end
73
+ test 'builder input_field uses min_max component' do
74
+ with_input_field_for @other_validating_user, :age, as: :integer
87
75
 
88
- assert_select 'input[min=18]'
76
+ assert_select 'input[min="18"]'
89
77
  end
90
78
 
91
- test 'builder input_field should use pattern component' do
92
- with_concat_form_for(@other_validating_user) do |f|
93
- f.input_field :country, as: :string
94
- end
79
+ test 'builder input_field does not use pattern component by default' do
80
+ with_input_field_for @other_validating_user, :country, as: :string
81
+
82
+ assert_no_select 'input[pattern="\w+"]'
83
+ end
84
+
85
+ test 'builder input_field infers pattern from attributes' do
86
+ with_input_field_for @other_validating_user, :country, as: :string, pattern: true
95
87
 
96
88
  assert_select 'input[pattern="\w+"]'
97
89
  end
98
90
 
99
- test 'builder input_field should use readonly component' do
100
- with_concat_form_for(@other_validating_user) do |f|
101
- f.input_field :age, as: :integer, readonly: true
102
- end
91
+ test 'builder input_field accepts custom pattern' do
92
+ with_input_field_for @other_validating_user, :country, as: :string, pattern: '\d+'
93
+
94
+ assert_select 'input[pattern="\d+"]'
95
+ end
96
+
97
+ test 'builder input_field uses readonly component' do
98
+ with_input_field_for @other_validating_user, :age, as: :integer, readonly: true
103
99
 
104
100
  assert_select 'input.integer.readonly[readonly]'
105
101
  end
106
102
 
107
- test 'builder input_field should use maxlength component' do
108
- with_concat_form_for(@validating_user) do |f|
109
- f.input_field :name, as: :string
110
- end
103
+ test 'builder input_field uses maxlength component' do
104
+ with_input_field_for @validating_user, :name, as: :string
111
105
 
112
- assert_select 'input.string[maxlength=25]'
106
+ assert_select 'input.string[maxlength="25"]'
113
107
  end
114
108
 
115
- test 'builder collection input_field should generate input tag with a clean HTML' do
116
- with_concat_form_for(@user) do |f|
117
- f.input_field :status, collection: ['Open', 'Closed'], class: 'status', label_method: :to_s, value_method: :to_s
118
- end
109
+ test 'builder input_field uses minlength component' do
110
+ with_input_field_for @validating_user, :name, as: :string
111
+
112
+ assert_select 'input.string[minlength="5"]'
113
+ end
114
+
115
+ test 'builder collection input_field generates input tag with a clean HTML' do
116
+ with_input_field_for @user, :status, collection: %w[Open Closed],
117
+ class: 'status', label_method: :to_s, value_method: :to_s
119
118
 
120
119
  assert_no_select 'select.status[input_html]'
121
120
  assert_no_select 'select.status[collection]'
122
121
  assert_no_select 'select.status[label_method]'
123
122
  assert_no_select 'select.status[value_method]'
124
123
  end
124
+
125
+ test 'build input_field does not treat "boolean_style" as a HTML attribute' do
126
+ with_input_field_for @user, :active, boolean_style: :nested
127
+
128
+ assert_no_select 'input.boolean[boolean_style]'
129
+ end
130
+
131
+ test 'build input_field does not treat "prompt" as a HTML attribute' do
132
+ with_input_field_for @user, :attempts, collection: [1,2,3,4,5], prompt: :translate
133
+
134
+ assert_no_select 'select[prompt]'
135
+ end
136
+
137
+ test 'build input_field without pattern component use the pattern string' do
138
+ swap_wrapper :default, custom_wrapper_with_html5_components do
139
+ with_input_field_for @user, :name, pattern: '\w+'
140
+
141
+ assert_select 'input[pattern="\w+"]'
142
+ end
143
+ end
144
+
145
+ test 'build input_field without placeholder component use the placeholder string' do
146
+ swap_wrapper :default, custom_wrapper_with_html5_components do
147
+ with_input_field_for @user, :name, placeholder: 'Placeholder'
148
+
149
+ assert_select 'input[placeholder="Placeholder"]'
150
+ end
151
+ end
152
+
153
+ test 'build input_field without maxlength component use the maxlength string' do
154
+ swap_wrapper :default, custom_wrapper_with_html5_components do
155
+ with_input_field_for @user, :name, maxlength: 5
156
+
157
+ assert_select 'input[maxlength="5"]'
158
+ end
159
+ end
160
+
161
+ test 'build input_field without minlength component use the minlength string' do
162
+ swap_wrapper :default, custom_wrapper_with_html5_components do
163
+ with_input_field_for @user, :name, minlength: 5
164
+
165
+ assert_select 'input[minlength="5"]'
166
+ end
167
+ end
168
+
169
+ test 'build input_field without readonly component use the readonly string' do
170
+ swap_wrapper :default, custom_wrapper_with_html5_components do
171
+ with_input_field_for @user, :name, readonly: true
172
+
173
+ assert_select 'input[readonly="readonly"]'
174
+ end
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
125
201
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: UTF-8
2
3
  require 'test_helper'
3
4
 
@@ -8,63 +9,78 @@ class LabelTest < ActionView::TestCase
8
9
  end
9
10
  end
10
11
 
11
- test 'builder should generate a label for the attribute' do
12
+ test 'builder generates a label for the attribute' do
12
13
  with_label_for @user, :name
13
14
  assert_select 'label.string[for=user_name]', /Name/
14
15
  end
15
16
 
16
- test 'builder should generate a label for the boolean attrbiute' do
17
+ test 'builder generates a label for the attribute with decorated object responsive to #to_model' do
18
+ with_label_for @decorated_user, :name
19
+ assert_select 'label.string[for=user_name]', /Name/
20
+ end
21
+
22
+ test 'builder generates a label for the boolean attrbiute' do
17
23
  with_label_for @user, :name, as: :boolean
18
24
  assert_select 'label.boolean[for=user_name]', /Name/
19
25
  assert_no_select 'label[as=boolean]'
20
26
  end
21
27
 
22
- test 'builder should generate a label component tag with a clean HTML' do
28
+ test 'builder generates a label component tag with a clean HTML' do
23
29
  with_label_for @user, :name
24
30
  assert_no_select 'label.string[label_html]'
25
31
  end
26
32
 
27
- test 'builder should add a required class to label if the attribute is required' do
33
+ test 'builder adds a required class to label if the attribute is required' do
28
34
  with_label_for @validating_user, :name
29
35
  assert_select 'label.string.required[for=validating_user_name]', /Name/
30
36
  end
31
37
 
32
- test 'builder should escape label text' do
38
+ test 'builder adds a disabled class to label if the attribute is disabled' do
39
+ with_label_for @validating_user, :name, disabled: true
40
+ assert_select 'label.string.disabled[for=validating_user_name]', /Name/
41
+ end
42
+
43
+ test 'builder does not add a disabled class to label if the attribute is not disabled' do
44
+ with_label_for @validating_user, :name, disabled: false
45
+ assert_no_select 'label.string.disabled[for=validating_user_name]', /Name/
46
+ end
47
+
48
+ test 'builder escapes label text' do
33
49
  with_label_for @user, :name, label: '<script>alert(1337)</script>', required: false
34
- assert_select 'label.string', "&lt;script&gt;alert(1337)&lt;/script&gt;"
50
+ assert_no_select 'label.string script'
35
51
  end
36
52
 
37
- test 'builder should not escape label text if it is safe' do
53
+ test 'builder does not escape label text if it is safe' do
38
54
  with_label_for @user, :name, label: '<script>alert(1337)</script>'.html_safe, required: false
39
55
  assert_select 'label.string script', "alert(1337)"
40
56
  end
41
57
 
42
- test 'builder should allow passing options to label tag' do
58
+ test 'builder allows passing options to label tag' do
43
59
  with_label_for @user, :name, label: 'My label', id: 'name_label'
44
60
  assert_select 'label.string#name_label', /My label/
45
61
  end
46
62
 
47
- test 'builder label should generate label tag with clean HTML' do
63
+ test 'builder label generates label tag with clean HTML' do
48
64
  with_label_for @user, :name, label: 'My label', required: true, id: 'name_label'
49
65
  assert_select 'label.string#name_label', /My label/
50
66
  assert_no_select 'label[label]'
51
67
  assert_no_select 'label[required]'
52
68
  end
53
69
 
54
- test 'builder should not modify the options hash' do
70
+ test 'builder does not modify the options hash' do
55
71
  options = { label: 'My label', id: 'name_label' }
56
72
  with_label_for @user, :name, options
57
73
  assert_select 'label.string#name_label', /My label/
58
74
  assert_equal({ label: 'My label', id: 'name_label' }, options)
59
75
  end
60
76
 
61
- test 'builder should fallback to default label when string is given' do
77
+ test 'builder fallbacks to default label when string is given' do
62
78
  with_label_for @user, :name, 'Nome do usuário'
63
79
  assert_select 'label', 'Nome do usuário'
64
80
  assert_no_select 'label.string'
65
81
  end
66
82
 
67
- test 'builder should fallback to default label when block is given' do
83
+ test 'builder fallbacks to default label when block is given' do
68
84
  with_label_for @user, :name do
69
85
  'Nome do usuário'
70
86
  end
@@ -73,9 +89,48 @@ class LabelTest < ActionView::TestCase
73
89
  end
74
90
 
75
91
  test 'builder allows label order to be changed' do
76
- swap SimpleForm, label_text: lambda { |l, r| "#{l}:" } do
92
+ swap SimpleForm, label_text: proc { |l, r| "#{l}:" } do
77
93
  with_label_for @user, :age
78
94
  assert_select 'label.integer[for=user_age]', "Age:"
79
95
  end
80
96
  end
97
+
98
+ test 'configuration allow set label text for wrappers' do
99
+ swap_wrapper :default, custom_wrapper_with_label_text do
100
+ with_concat_form_for(@user) do |f|
101
+ concat f.input :age
102
+ end
103
+ assert_select "label.integer[for=user_age]", "**Age**"
104
+ end
105
+ end
106
+
107
+ test 'configuration allow set rewrited label tag for wrappers' do
108
+ swap_wrapper :default, custom_wrapper_with_custom_label_component do
109
+ with_concat_form_for(@user) do |f|
110
+ concat f.input :age
111
+ end
112
+ assert_select "span.integer.user_age", /Age/
113
+ end
114
+ end
115
+
116
+ test 'builder allows custom formatting when label is explicitly specified' do
117
+ swap SimpleForm, label_text: ->(l, r, explicit_label) { explicit_label ? l : "#{l.titleize}:" } do
118
+ with_label_for @user, :time_zone, 'What is your home time zone?'
119
+ assert_select 'label[for=user_time_zone]', 'What is your home time zone?'
120
+ end
121
+ end
122
+
123
+ test 'builder allows custom formatting when label is generated' do
124
+ swap SimpleForm, label_text: ->(l, r, explicit_label) { explicit_label ? l : "#{l.titleize}:" } do
125
+ with_label_for @user, :time_zone
126
+ assert_select 'label[for=user_time_zone]', 'Time Zone:'
127
+ end
128
+ end
129
+
130
+ test 'builder allows label specific `label_text` option' do
131
+ with_label_for @user, :time_zone, label_text: ->(l, _, _) { "#{l.titleize}:" }
132
+
133
+ assert_no_select 'label[label_text]'
134
+ assert_select 'label[for=user_time_zone]', 'Time Zone:'
135
+ end
81
136
  end