simple_form 3.1.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +148 -0
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +278 -68
  5. data/lib/generators/simple_form/install_generator.rb +1 -0
  6. data/lib/generators/simple_form/templates/README +3 -3
  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 +19 -9
  11. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +367 -63
  12. data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +23 -8
  13. data/lib/simple_form/action_view_extensions/builder.rb +1 -0
  14. data/lib/simple_form/action_view_extensions/form_helper.rb +4 -1
  15. data/lib/simple_form/components/errors.rb +15 -2
  16. data/lib/simple_form/components/hints.rb +1 -0
  17. data/lib/simple_form/components/html5.rb +15 -4
  18. data/lib/simple_form/components/label_input.rb +2 -1
  19. data/lib/simple_form/components/labels.rb +12 -5
  20. data/lib/simple_form/components/maxlength.rb +8 -4
  21. data/lib/simple_form/components/min_max.rb +1 -0
  22. data/lib/simple_form/components/minlength.rb +38 -0
  23. data/lib/simple_form/components/pattern.rb +1 -0
  24. data/lib/simple_form/components/placeholders.rb +2 -1
  25. data/lib/simple_form/components/readonly.rb +1 -0
  26. data/lib/simple_form/components.rb +2 -0
  27. data/lib/simple_form/error_notification.rb +1 -0
  28. data/lib/simple_form/form_builder.rb +117 -35
  29. data/lib/simple_form/helpers/autofocus.rb +1 -0
  30. data/lib/simple_form/helpers/disabled.rb +1 -0
  31. data/lib/simple_form/helpers/readonly.rb +1 -0
  32. data/lib/simple_form/helpers/required.rb +1 -0
  33. data/lib/simple_form/helpers/validators.rb +2 -1
  34. data/lib/simple_form/helpers.rb +1 -0
  35. data/lib/simple_form/i18n_cache.rb +1 -0
  36. data/lib/simple_form/inputs/base.rb +36 -12
  37. data/lib/simple_form/inputs/block_input.rb +1 -0
  38. data/lib/simple_form/inputs/boolean_input.rb +14 -3
  39. data/lib/simple_form/inputs/collection_check_boxes_input.rb +2 -1
  40. data/lib/simple_form/inputs/collection_input.rb +7 -5
  41. data/lib/simple_form/inputs/collection_radio_buttons_input.rb +3 -2
  42. data/lib/simple_form/inputs/collection_select_input.rb +1 -0
  43. data/lib/simple_form/inputs/color_input.rb +14 -0
  44. data/lib/simple_form/inputs/date_time_input.rb +13 -8
  45. data/lib/simple_form/inputs/file_input.rb +1 -0
  46. data/lib/simple_form/inputs/grouped_collection_select_input.rb +1 -0
  47. data/lib/simple_form/inputs/hidden_input.rb +1 -0
  48. data/lib/simple_form/inputs/numeric_input.rb +1 -0
  49. data/lib/simple_form/inputs/password_input.rb +2 -1
  50. data/lib/simple_form/inputs/priority_input.rb +1 -4
  51. data/lib/simple_form/inputs/range_input.rb +1 -0
  52. data/lib/simple_form/inputs/string_input.rb +3 -2
  53. data/lib/simple_form/inputs/text_input.rb +2 -1
  54. data/lib/simple_form/inputs.rb +2 -0
  55. data/lib/simple_form/map_type.rb +1 -0
  56. data/lib/simple_form/railtie.rb +1 -0
  57. data/lib/simple_form/tags.rb +7 -2
  58. data/lib/simple_form/version.rb +2 -1
  59. data/lib/simple_form/wrappers/builder.rb +1 -0
  60. data/lib/simple_form/wrappers/leaf.rb +2 -1
  61. data/lib/simple_form/wrappers/many.rb +1 -0
  62. data/lib/simple_form/wrappers/root.rb +2 -0
  63. data/lib/simple_form/wrappers/single.rb +2 -1
  64. data/lib/simple_form/wrappers.rb +1 -0
  65. data/lib/simple_form.rb +79 -14
  66. data/test/action_view_extensions/builder_test.rb +28 -9
  67. data/test/action_view_extensions/form_helper_test.rb +3 -2
  68. data/test/components/custom_components_test.rb +62 -0
  69. data/test/components/label_test.rb +33 -4
  70. data/test/form_builder/association_test.rb +33 -2
  71. data/test/form_builder/button_test.rb +1 -0
  72. data/test/form_builder/error_notification_test.rb +1 -0
  73. data/test/form_builder/error_test.rb +44 -9
  74. data/test/form_builder/general_test.rb +92 -20
  75. data/test/form_builder/hint_test.rb +6 -0
  76. data/test/form_builder/input_field_test.rb +76 -70
  77. data/test/form_builder/label_test.rb +27 -4
  78. data/test/form_builder/wrapper_test.rb +66 -14
  79. data/test/generators/simple_form_generator_test.rb +4 -3
  80. data/test/inputs/boolean_input_test.rb +35 -0
  81. data/test/inputs/collection_check_boxes_input_test.rb +38 -14
  82. data/test/inputs/collection_radio_buttons_input_test.rb +48 -24
  83. data/test/inputs/collection_select_input_test.rb +40 -39
  84. data/test/inputs/color_input_test.rb +10 -0
  85. data/test/inputs/datetime_input_test.rb +12 -8
  86. data/test/inputs/disabled_test.rb +14 -0
  87. data/test/inputs/discovery_test.rb +23 -0
  88. data/test/inputs/file_input_test.rb +1 -0
  89. data/test/inputs/general_test.rb +3 -2
  90. data/test/inputs/grouped_collection_select_input_test.rb +11 -10
  91. data/test/inputs/hidden_input_test.rb +1 -0
  92. data/test/inputs/numeric_input_test.rb +5 -1
  93. data/test/inputs/priority_input_test.rb +7 -6
  94. data/test/inputs/readonly_test.rb +1 -0
  95. data/test/inputs/required_test.rb +45 -0
  96. data/test/inputs/string_input_test.rb +18 -16
  97. data/test/inputs/text_input_test.rb +13 -0
  98. data/test/simple_form_test.rb +1 -0
  99. data/test/support/discovery_inputs.rb +8 -0
  100. data/test/support/misc_helpers.rb +44 -2
  101. data/test/support/mock_controller.rb +7 -1
  102. data/test/support/models.rb +105 -22
  103. data/test/test_helper.rb +14 -3
  104. metadata +42 -36
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: UTF-8
2
3
  require 'test_helper'
3
4
 
@@ -30,6 +31,12 @@ class FormBuilderTest < ActionView::TestCase
30
31
  end
31
32
  end
32
33
 
34
+ test 'builder works with decorated object responsive to #to_model' do
35
+ assert_nothing_raised do
36
+ with_form_for @decorated_user, :name
37
+ end
38
+ end
39
+
33
40
  test 'builder input allows a block to configure input' do
34
41
  with_form_for @user, :name do
35
42
  text_field_tag :foo, :bar, id: :cool
@@ -46,8 +53,19 @@ class FormBuilderTest < ActionView::TestCase
46
53
  end
47
54
  end
48
55
 
56
+ test 'builder does not override custom input mappings for custom collection' do
57
+ swap SimpleForm, input_mappings: { /gender$/ => :check_boxes } do
58
+ with_concat_form_for @user do |f|
59
+ f.input :gender, collection: %i[male female]
60
+ end
61
+
62
+ assert_no_select 'select option', 'Male'
63
+ assert_select 'input[type=checkbox][value=male]'
64
+ end
65
+ end
66
+
49
67
  test 'builder allows to skip input_type class' do
50
- swap SimpleForm, generate_additional_classes_for: [:label, :wrapper] do
68
+ swap SimpleForm, generate_additional_classes_for: %i[label wrapper] do
51
69
  with_form_for @user, :post_count
52
70
  assert_no_select "form input#user_post_count.integer"
53
71
  assert_select "form input#user_post_count"
@@ -108,9 +126,40 @@ class FormBuilderTest < ActionView::TestCase
108
126
 
109
127
  test 'builder generates text areas for text columns' do
110
128
  with_form_for @user, :description
129
+ assert_no_select 'form input#user_description.string'
130
+ assert_select 'form textarea#user_description.text'
131
+ end
132
+
133
+ test 'builder generates text areas for text columns when hinted' do
134
+ with_form_for @user, :description, as: :text
135
+ assert_no_select 'form input#user_description.string'
111
136
  assert_select 'form textarea#user_description.text'
112
137
  end
113
138
 
139
+ test 'builder generates text field for text columns when hinted' do
140
+ with_form_for @user, :description, as: :string
141
+ assert_no_select 'form textarea#user_description.text'
142
+ assert_select 'form input#user_description.string'
143
+ end
144
+
145
+ test 'builder generates text areas for hstore columns' do
146
+ with_form_for @user, :hstore
147
+ assert_no_select 'form input#user_hstore.string'
148
+ assert_select 'form textarea#user_hstore.text'
149
+ end
150
+
151
+ test 'builder generates text areas for json columns' do
152
+ with_form_for @user, :json
153
+ assert_no_select 'form input#user_json.string'
154
+ assert_select 'form textarea#user_json.text'
155
+ end
156
+
157
+ test 'builder generates text areas for jsonb columns' do
158
+ with_form_for @user, :jsonb
159
+ assert_no_select 'form input#user_jsonb.string'
160
+ assert_select 'form textarea#user_jsonb.text'
161
+ end
162
+
114
163
  test 'builder generates a checkbox for boolean columns' do
115
164
  with_form_for @user, :active
116
165
  assert_select 'form input[type=checkbox]#user_active.boolean'
@@ -128,7 +177,16 @@ class FormBuilderTest < ActionView::TestCase
128
177
 
129
178
  test 'builder generates uuid fields for uuid columns' do
130
179
  with_form_for @user, :uuid
131
- assert_select 'form input#user_uuid.string.uuid'
180
+ if defined? ActiveModel::Type
181
+ assert_select 'form input#user_uuid.string.string'
182
+ else
183
+ assert_select 'form input#user_uuid.string.uuid'
184
+ end
185
+ end
186
+
187
+ test 'builder generates string fields for citext columns' do
188
+ with_form_for @user, :citext
189
+ assert_select 'form input#user_citext.string'
132
190
  end
133
191
 
134
192
  test 'builder generates password fields for columns that matches password' do
@@ -181,20 +239,24 @@ class FormBuilderTest < ActionView::TestCase
181
239
  assert_select 'form select#user_updated_at_1i.datetime'
182
240
  end
183
241
 
184
- test 'builder generates file for file columns' do
185
- @user.avatar = MiniTest::Mock.new
186
- @user.avatar.expect(:public_filename, true)
242
+ test 'builder generates file input for ActiveStorage >= 5.2 and Refile >= 0.2.0 <= 0.4.0' do
243
+ with_form_for UserWithAttachment.build, :avatar
244
+ assert_select 'form input#user_with_attachment_avatar.file'
245
+ end
187
246
 
188
- with_form_for @user, :avatar
189
- assert_select 'form input#user_avatar.file'
247
+ test 'builder generates file input for Shrine >= 0.9.0, Refile >= 0.6.0 and CarrierWave >= 0.2.1' do
248
+ with_form_for UserWithAttachment.build, :cover
249
+ assert_select 'form input#user_with_attachment_cover.file'
190
250
  end
191
251
 
192
- test 'builder generates file for attributes that are real db columns but have file methods' do
193
- @user.home_picture = MiniTest::Mock.new
194
- @user.home_picture.expect(:mounted_as, true)
252
+ test 'builder generates file input for Refile >= 0.4.0 and Shrine >= 0.9.0' do
253
+ with_form_for UserWithAttachment.build, :profile_image
254
+ assert_select 'form input#user_with_attachment_profile_image.file'
255
+ end
195
256
 
196
- with_form_for @user, :home_picture
197
- assert_select 'form input#user_home_picture.file'
257
+ test 'builder generates file input for Paperclip ~> 2.0' do
258
+ with_form_for UserWithAttachment.build, :portrait
259
+ assert_select 'form input#user_with_attachment_portrait.file'
198
260
  end
199
261
 
200
262
  test 'build generates select if a collection is given' do
@@ -202,15 +264,25 @@ class FormBuilderTest < ActionView::TestCase
202
264
  assert_select 'form select#user_age.select'
203
265
  end
204
266
 
267
+ test 'builder does not generate url fields for columns that contain only the letters url' do
268
+ with_form_for @user, :hourly
269
+ assert_no_select 'form input#user_url.string.url'
270
+ assert_select 'form input#user_hourly.string'
271
+ end
272
+
205
273
  test 'builder allows overriding default input type for text' do
206
274
  with_form_for @user, :name, as: :text
207
275
  assert_no_select 'form input#user_name'
208
276
  assert_select 'form textarea#user_name.text'
277
+ end
209
278
 
279
+ test 'builder allows overriding default input type for radio_buttons' do
210
280
  with_form_for @user, :active, as: :radio_buttons
211
281
  assert_no_select 'form input[type=checkbox]'
212
282
  assert_select 'form input.radio_buttons[type=radio]', count: 2
283
+ end
213
284
 
285
+ test 'builder allows overriding default input type for string' do
214
286
  with_form_for @user, :born_at, as: :string
215
287
  assert_no_select 'form select'
216
288
  assert_select 'form input#user_born_at.string'
@@ -256,7 +328,7 @@ class FormBuilderTest < ActionView::TestCase
256
328
  end
257
329
 
258
330
  test 'builder does not propagate input options to wrapper with custom wrapper' do
259
- swap_wrapper :default, self.custom_wrapper_with_wrapped_input do
331
+ swap_wrapper :default, custom_wrapper_with_wrapped_input do
260
332
  with_form_for @user, :name, input_html: { class: 'my_input' }
261
333
  assert_no_select 'form div.input.my_input'
262
334
  assert_select 'form input.my_input.string'
@@ -264,7 +336,7 @@ class FormBuilderTest < ActionView::TestCase
264
336
  end
265
337
 
266
338
  test 'builder does not propagate label options to wrapper with custom wrapper' do
267
- swap_wrapper :default, self.custom_wrapper_with_wrapped_label do
339
+ swap_wrapper :default, custom_wrapper_with_wrapped_label do
268
340
  with_form_for @user, :name, label_html: { class: 'my_label' }
269
341
  assert_no_select 'form div.label.my_label'
270
342
  assert_select 'form label.my_label.string'
@@ -350,18 +422,18 @@ class FormBuilderTest < ActionView::TestCase
350
422
  end
351
423
 
352
424
  # DEFAULT OPTIONS
353
- [:input, :input_field].each do |method|
425
+ %i[input input_field].each do |method|
354
426
  test "builder receives a default argument and pass it to the inputs when calling '#{method}'" do
355
427
  with_concat_form_for @user, defaults: { input_html: { class: 'default_class' } } do |f|
356
- f.send(method, :name)
428
+ f.public_send(method, :name)
357
429
  end
358
430
  assert_select 'input.default_class'
359
431
  end
360
432
 
361
433
  test "builder receives a default argument and pass it to the inputs without changing the defaults when calling '#{method}'" do
362
434
  with_concat_form_for @user, defaults: { input_html: { class: 'default_class', id: 'default_id' } } do |f|
363
- concat(f.send(method, :name))
364
- concat(f.send(method, :credit_limit))
435
+ concat(f.public_send(method, :name))
436
+ concat(f.public_send(method, :credit_limit))
365
437
  end
366
438
 
367
439
  assert_select "input.string.default_class[name='user[name]']"
@@ -372,9 +444,9 @@ class FormBuilderTest < ActionView::TestCase
372
444
  @user.company = Company.new(1, 'Empresa')
373
445
 
374
446
  with_concat_form_for @user, defaults: { input_html: { class: 'default_class' } } do |f|
375
- concat(f.send(method, :name))
447
+ concat(f.public_send(method, :name))
376
448
  concat(f.simple_fields_for(:company) do |company_form|
377
- concat(company_form.send(method, :name))
449
+ concat(company_form.public_send(method, :name))
378
450
  end)
379
451
  end
380
452
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  # Tests for f.hint
@@ -18,6 +19,11 @@ class HintTest < ActionView::TestCase
18
19
  assert_select 'span.hint', 'Use with care...'
19
20
  end
20
21
 
22
+ test 'hint is generated with decorated object responsive to #to_model' do
23
+ with_hint_for @decorated_user, :name, hint: 'Use with care...'
24
+ assert_select 'span.hint', 'Use with care...'
25
+ end
26
+
21
27
  test 'hint does not modify the options hash' do
22
28
  options = { hint: 'Use with care...' }
23
29
  with_hint_for @user, :name, options
@@ -1,11 +1,11 @@
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
6
  test "builder input_field only renders the input tag, nothing else" do
6
- with_concat_form_for(@user) do |f|
7
- f.input_field :name
8
- end
7
+ with_input_field_for @user, :name
8
+
9
9
  assert_select 'form > input.required.string'
10
10
  assert_no_select 'div.string'
11
11
  assert_no_select 'label'
@@ -13,45 +13,34 @@ class InputFieldTest < ActionView::TestCase
13
13
  end
14
14
 
15
15
  test 'builder input_field allows overriding default input type' do
16
- with_concat_form_for(@user) do |f|
17
- f.input_field :name, as: :text
18
- end
16
+ with_input_field_for @user, :name, as: :text
19
17
 
20
18
  assert_no_select 'input#user_name'
21
19
  assert_select 'textarea#user_name.text'
22
20
  end
23
21
 
24
22
  test 'builder input_field generates input type based on column type' do
25
- with_concat_form_for(@user) do |f|
26
- f.input_field :age
27
- end
23
+ with_input_field_for @user, :age
28
24
 
29
25
  assert_select 'input[type=number].integer#user_age'
30
26
  end
31
27
 
32
28
  test 'builder input_field is able to disable any component' do
33
- with_concat_form_for(@user) do |f|
34
- f.input_field :age, html5: false
35
- end
29
+ with_input_field_for @user, :age, html5: false
36
30
 
37
31
  assert_no_select 'input[html5=false]#user_age'
38
32
  assert_select 'input[type=text].integer#user_age'
39
33
  end
40
34
 
41
35
  test 'builder input_field allows 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
36
+ with_input_field_for @user, :name, id: 'name_input', class: 'name'
45
37
 
46
38
  assert_select 'input.string.name#name_input'
47
39
  end
48
40
 
49
41
  test 'builder input_field does not modify the options hash' do
50
42
  options = { id: 'name_input', class: 'name' }
51
-
52
- with_concat_form_for(@user) do |f|
53
- f.input_field :name, options
54
- end
43
+ with_input_field_for @user, :name, options
55
44
 
56
45
  assert_select 'input.string.name#name_input'
57
46
  assert_equal({ id: 'name_input', class: 'name' }, options)
@@ -59,9 +48,7 @@ class InputFieldTest < ActionView::TestCase
59
48
 
60
49
 
61
50
  test 'builder input_field generates 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
51
+ with_input_field_for @user, :name, as: :integer, class: 'name'
65
52
 
66
53
  assert_no_select 'input.integer[input_html]'
67
54
  assert_no_select 'input.integer[as]'
@@ -71,67 +58,57 @@ class InputFieldTest < ActionView::TestCase
71
58
  store_translations(:en, simple_form: { placeholders: { user: {
72
59
  name: 'Name goes here'
73
60
  } } }) do
74
-
75
- with_concat_form_for(@user) do |f|
76
- f.input_field :name
77
- end
61
+ with_input_field_for @user, :name
78
62
 
79
63
  assert_select 'input.string[placeholder="Name goes here"]'
80
64
  end
81
65
  end
82
66
 
83
67
  test 'builder input_field uses min_max component' do
84
- with_concat_form_for(@other_validating_user) do |f|
85
- f.input_field :age, as: :integer
86
- end
68
+ with_input_field_for @other_validating_user, :age, as: :integer
87
69
 
88
70
  assert_select 'input[min="18"]'
89
71
  end
90
72
 
91
73
  test 'builder input_field does not use pattern component by default' do
92
- with_concat_form_for(@other_validating_user) do |f|
93
- f.input_field :country, as: :string
94
- end
74
+ with_input_field_for @other_validating_user, :country, as: :string
95
75
 
96
76
  assert_no_select 'input[pattern="\w+"]'
97
77
  end
98
78
 
99
79
  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
80
+ with_input_field_for @other_validating_user, :country, as: :string, pattern: true
103
81
 
104
- assert_select 'input[pattern="\w+"]'
82
+ assert_select "input:match('pattern', ?)", /\w+/
105
83
  end
106
84
 
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
85
+ test 'builder input_field accepts custom pattern' do
86
+ with_input_field_for @other_validating_user, :country, as: :string, pattern: '\d+'
111
87
 
112
- assert_select 'input[pattern="\d+"]'
88
+ assert_select "input:match('pattern', ?)", /\\d+/
113
89
  end
114
90
 
115
91
  test 'builder input_field uses readonly component' do
116
- with_concat_form_for(@other_validating_user) do |f|
117
- f.input_field :age, as: :integer, readonly: true
118
- end
92
+ with_input_field_for @other_validating_user, :age, as: :integer, readonly: true
119
93
 
120
94
  assert_select 'input.integer.readonly[readonly]'
121
95
  end
122
96
 
123
97
  test 'builder input_field uses maxlength component' do
124
- with_concat_form_for(@validating_user) do |f|
125
- f.input_field :name, as: :string
126
- end
98
+ with_input_field_for @validating_user, :name, as: :string
127
99
 
128
100
  assert_select 'input.string[maxlength="25"]'
129
101
  end
130
102
 
103
+ test 'builder input_field uses minlength component' do
104
+ with_input_field_for @validating_user, :name, as: :string
105
+
106
+ assert_select 'input.string[minlength="5"]'
107
+ end
108
+
131
109
  test 'builder collection input_field generates input tag with a clean HTML' do
132
- with_concat_form_for(@user) do |f|
133
- f.input_field :status, collection: ['Open', 'Closed'], class: 'status', label_method: :to_s, value_method: :to_s
134
- end
110
+ with_input_field_for @user, :status, collection: %w[Open Closed],
111
+ class: 'status', label_method: :to_s, value_method: :to_s
135
112
 
136
113
  assert_no_select 'select.status[input_html]'
137
114
  assert_no_select 'select.status[collection]'
@@ -140,50 +117,79 @@ class InputFieldTest < ActionView::TestCase
140
117
  end
141
118
 
142
119
  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
145
- end
120
+ with_input_field_for @user, :active, boolean_style: :nested
146
121
 
147
122
  assert_no_select 'input.boolean[boolean_style]'
148
123
  end
149
124
 
125
+ test 'build input_field does not treat "prompt" as a HTML attribute' do
126
+ with_input_field_for @user, :attempts, collection: [1,2,3,4,5], prompt: :translate
127
+
128
+ assert_no_select 'select[prompt]'
129
+ end
130
+
150
131
  test 'build input_field without pattern component use the pattern string' do
151
- swap_wrapper :default, self.custom_wrapper_with_html5_components do
152
- with_concat_form_for(@user) do |f|
153
- f.input_field :name, pattern: '\w+'
154
- end
132
+ swap_wrapper :default, custom_wrapper_with_html5_components do
133
+ with_input_field_for @user, :name, pattern: '\w+'
155
134
 
156
- assert_select 'input[pattern="\w+"]'
135
+ assert_select "input:match('pattern', ?)", /\w+/
157
136
  end
158
137
  end
159
138
 
160
139
  test 'build input_field without placeholder component use the placeholder string' do
161
- swap_wrapper :default, self.custom_wrapper_with_html5_components do
162
- with_concat_form_for(@user) do |f|
163
- f.input_field :name, placeholder: 'Placeholder'
164
- end
140
+ swap_wrapper :default, custom_wrapper_with_html5_components do
141
+ with_input_field_for @user, :name, placeholder: 'Placeholder'
165
142
 
166
143
  assert_select 'input[placeholder="Placeholder"]'
167
144
  end
168
145
  end
169
146
 
170
147
  test 'build input_field without maxlength component use the maxlength string' do
171
- swap_wrapper :default, self.custom_wrapper_with_html5_components do
172
- with_concat_form_for(@user) do |f|
173
- f.input_field :name, maxlength: 5
174
- end
148
+ swap_wrapper :default, custom_wrapper_with_html5_components do
149
+ with_input_field_for @user, :name, maxlength: 5
175
150
 
176
151
  assert_select 'input[maxlength="5"]'
177
152
  end
178
153
  end
179
154
 
155
+ test 'build input_field without minlength component use the minlength string' do
156
+ swap_wrapper :default, custom_wrapper_with_html5_components do
157
+ with_input_field_for @user, :name, minlength: 5
158
+
159
+ assert_select 'input[minlength="5"]'
160
+ end
161
+ end
162
+
180
163
  test 'build input_field without readonly component use the readonly string' do
181
- swap_wrapper :default, self.custom_wrapper_with_html5_components do
182
- with_concat_form_for(@user) do |f|
183
- f.input_field :name, readonly: true
184
- end
164
+ swap_wrapper :default, custom_wrapper_with_html5_components do
165
+ with_input_field_for @user, :name, readonly: true
185
166
 
186
167
  assert_select 'input[readonly="readonly"]'
187
168
  end
188
169
  end
170
+
171
+ test 'adds valid class to input_field when it is configured' do
172
+ swap SimpleForm, input_field_valid_class: 'is-valid' do
173
+ @user.instance_eval { undef errors }
174
+ with_input_field_for @user, :name
175
+
176
+ assert_select 'input.string.required.is-valid'
177
+ end
178
+ end
179
+
180
+ test 'adds error class to input_field when it is configured' do
181
+ swap SimpleForm, input_field_error_class: 'is-invalid' do
182
+ with_input_field_for @user, :name
183
+
184
+ assert_select 'input.string.required.is-invalid'
185
+ end
186
+ end
187
+
188
+ test 'does not add validation classes to input_field when it is not configured' do
189
+ swap SimpleForm, input_field_error_class: nil, input_field_valid_class: nil do
190
+ with_input_field_for @user, :name
191
+
192
+ assert_select 'input.string.required'
193
+ end
194
+ end
189
195
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: UTF-8
2
3
  require 'test_helper'
3
4
 
@@ -13,6 +14,11 @@ class LabelTest < ActionView::TestCase
13
14
  assert_select 'label.string[for=user_name]', /Name/
14
15
  end
15
16
 
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
+
16
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/
@@ -29,6 +35,16 @@ class LabelTest < ActionView::TestCase
29
35
  assert_select 'label.string.required[for=validating_user_name]', /Name/
30
36
  end
31
37
 
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
+
32
48
  test 'builder escapes label text' do
33
49
  with_label_for @user, :name, label: '<script>alert(1337)</script>', required: false
34
50
  assert_no_select 'label.string script'
@@ -80,7 +96,7 @@ class LabelTest < ActionView::TestCase
80
96
  end
81
97
 
82
98
  test 'configuration allow set label text for wrappers' do
83
- swap_wrapper :default, self.custom_wrapper_with_label_text do
99
+ swap_wrapper :default, custom_wrapper_with_label_text do
84
100
  with_concat_form_for(@user) do |f|
85
101
  concat f.input :age
86
102
  end
@@ -89,7 +105,7 @@ class LabelTest < ActionView::TestCase
89
105
  end
90
106
 
91
107
  test 'configuration allow set rewrited label tag for wrappers' do
92
- swap_wrapper :default, self.custom_wrapper_with_custom_label_component do
108
+ swap_wrapper :default, custom_wrapper_with_custom_label_component do
93
109
  with_concat_form_for(@user) do |f|
94
110
  concat f.input :age
95
111
  end
@@ -98,16 +114,23 @@ class LabelTest < ActionView::TestCase
98
114
  end
99
115
 
100
116
  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
117
+ swap SimpleForm, label_text: ->(l, r, explicit_label) { explicit_label ? l : "#{l.titleize}:" } do
102
118
  with_label_for @user, :time_zone, 'What is your home time zone?'
103
119
  assert_select 'label[for=user_time_zone]', 'What is your home time zone?'
104
120
  end
105
121
  end
106
122
 
107
123
  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
124
+ swap SimpleForm, label_text: ->(l, r, explicit_label) { explicit_label ? l : "#{l.titleize}:" } do
109
125
  with_label_for @user, :time_zone
110
126
  assert_select 'label[for=user_time_zone]', 'Time Zone:'
111
127
  end
112
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
113
136
  end